Last active
August 28, 2017 23:18
-
-
Save gatchamix/39bba179dcb23f47cbd4d5c44924e976 to your computer and use it in GitHub Desktop.
hard jump-list generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <type_traits> | |
#include <utility> | |
// | |
template <auto... Vs> | |
struct auto_t | |
{ static auto constexpr size = sizeof...(Vs); }; | |
template <auto... Vs> | |
auto constexpr auto_v = auto_t<Vs...>{}; | |
template <auto... L, auto... R> | |
auto constexpr operator+(auto_t<L...>, auto_t<R...>) | |
{ return auto_t<L..., R...>{}; } | |
template <auto... Vs> | |
auto constexpr min(auto_t<Vs...>) | |
{ | |
using type = std::common_type_t<decltype(Vs)...>; | |
auto val = std::numeric_limits<type>::max(); | |
(((val > Vs) ? val = Vs : 0), ...); | |
return val; | |
} | |
template <auto... Vs> | |
auto constexpr max(auto_t<Vs...>) | |
{ | |
using type = std::common_type_t<decltype(Vs)...>; | |
auto val = std::numeric_limits<type>::min(); | |
(((val < Vs) ? val = Vs : 0), ...); | |
return val; | |
} | |
template <auto... Vs> | |
auto constexpr common_type(auto_t<Vs...>) | |
-> std::common_type_t<decltype(Vs)...>; | |
template <class T> | |
using common_type_t = decltype(common_type(T{})); | |
// | |
template <auto Val> | |
auto constexpr parse(); | |
auto constexpr default_parse() | |
{ return 10; } | |
template <> | |
auto constexpr parse<'#'>() | |
{ return 1; } | |
template <> | |
auto constexpr parse<','>() | |
{ return 2; } | |
template <> | |
auto constexpr parse<':'>() | |
{ return 3; } | |
template <> | |
auto constexpr parse<'+'>() | |
{ return 4; } | |
template <> | |
auto constexpr parse<'-'>() | |
{ return 5; } | |
template <> | |
auto constexpr parse<'.'>() | |
{ return 6; } | |
template <> | |
auto constexpr parse<'!'>() | |
{ return 7; } | |
template <> | |
auto constexpr parse<'('>() | |
{ return 8; } | |
template <> | |
auto constexpr parse<')'>() | |
{ return 9; } | |
template <> | |
auto constexpr parse<'['>() | |
{ return 10; } | |
template <> | |
auto constexpr parse<']'>() | |
{ return 11; } | |
template <> | |
auto constexpr parse<'{'>() | |
{ return 12; } | |
template <> | |
auto constexpr parse<'}'>() | |
{ return 13; } | |
template <> | |
auto constexpr parse<'&'>() | |
{ return 14; } | |
template <> | |
auto constexpr parse<'<'>() | |
{ return 15; } | |
template <> | |
auto constexpr parse<'>'>() | |
{ return 16; } | |
template <> | |
auto constexpr parse<'='>() | |
{ return 17; } | |
template <> | |
auto constexpr parse<'|'>() | |
{ return 18; } | |
template <> | |
auto constexpr parse<'?'>() | |
{ return 19; } | |
template <> | |
auto constexpr parse<'^'>() | |
{ return 20; } | |
template <> | |
auto constexpr parse<'/'>() | |
{ return 21; } | |
template <> | |
auto constexpr parse<'*'>() | |
{ return 22; } | |
template <> | |
auto constexpr parse<'%'>() | |
{ return 23; } | |
template <> | |
auto constexpr parse<'~'>() | |
{ return 24; } | |
// | |
template <> | |
auto constexpr parse<1'000>() | |
{ return 1'000; } | |
template <> | |
auto constexpr parse<10'000>() | |
{ return 10'000; } | |
template <> | |
auto constexpr parse<100'000>() | |
{ return 100'000; } | |
template <> | |
auto constexpr parse<1'000'000>() | |
{ return 1'000'000; } | |
template <> | |
auto constexpr parse<10'000'000>() | |
{ return 10'000'000; } | |
template <> | |
auto constexpr parse<100'000'000>() | |
{ return 100'000'000; } | |
// | |
template <class Vals, class Funcs, auto Def = nullptr, auto Limit = 128> | |
struct jumplist | |
{ | |
constexpr jumplist(Vals, Funcs, auto_t<Def> = {}, auto_t<Limit> = {}) | |
{} | |
private: | |
using T = std::conditional_t<std::is_signed_v<common_type_t<Vals>>, | |
std::make_signed_t<size_t>, std::size_t>; | |
using func_t = common_type_t<Funcs>; | |
static auto constexpr MIN = min(Vals{}); | |
static auto constexpr MAX = max(Vals{}); | |
static auto constexpr BIG = MAX-MIN+1 > Limit; | |
static auto constexpr N = BIG ? Vals::size : MAX-MIN+1; | |
template <auto... Vs, auto... Is> | |
static auto constexpr get__(T v, auto_t<Vs...>, std::index_sequence<Is...>) | |
{ | |
auto fun = Def; | |
(((v == Vs) ? fun = table_[Is] : 0) || ...); | |
return fun; | |
} | |
public: | |
auto constexpr operator[](T i) const | |
{ | |
if (std::size_t(i-MIN) > MAX-MIN) | |
{ return static_cast<func_t>(Def); } | |
if constexpr (BIG) | |
{ return get__(i, Vals{}, std::make_index_sequence<N>{}); } | |
else | |
{ return table_[i - MIN]; } | |
} | |
template <class... Args> | |
auto constexpr operator()(T i, Args&&... args) const | |
{ return (this->operator[](i))(std::forward<Args>(args)...); } | |
private: | |
template <auto... Vs, auto... Fs> | |
static auto constexpr make_table__(auto_t<Vs...>, auto_t<Fs...>) | |
{ | |
if constexpr (BIG) | |
{ | |
return std::array<func_t, N>{ Fs... }; | |
} | |
else | |
{ | |
auto arr = std::array<func_t, N>{}; | |
for (auto& f : arr) f = Def; | |
((arr[Vs - MIN] = Fs), ...); | |
return arr; | |
} | |
} | |
static auto constexpr table_ = make_table__(Vals{}, Funcs{}); | |
}; | |
// | |
template <auto... Vs> | |
auto constexpr make_funcs(auto_t<Vs...>) | |
{ return auto_v<&parse<Vs>...>; } | |
int main(int argc, char **argv) | |
{ | |
auto constexpr core = auto_v | |
< | |
':', '+', '-', '.', '!', '(', ')', '[', ']', '{', '}', '#', | |
'&', '<', '>', '=', '|', '?', '^', '/', '*', '%', '~', ',' | |
>; | |
#if 1 | |
auto constexpr seq = core; | |
#else | |
auto constexpr seq = core + auto_v | |
<1'000, 10'000, 100'000, 1'000'000, 10'000'000, 100'000'000>; | |
#endif | |
auto constexpr test = auto_v<>; | |
auto constexpr fun = make_funcs(seq); | |
auto constexpr jl = jumplist{ seq, fun, auto_v<&default_parse> }; | |
return jl(argv[0][0]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment