I\'ve been into C++ for some years but I have not found yet the solution to a problem I constantly have. Know how to solve it would be awesome.
What I have at the mo
This class makes a jump table for a given Enum
up to a certain count
size based off constructing some template and invoking it with the supplied args. It assumes the enum values start at 0, and go to Count-1.
templateclass Z>
struct magic_switch {
// return value of a call to magic_switch(Args...)
template
using R = std::result_of_t(Args...)>;
// A function pointer for a jump table:
template
using F = R(*)(Args&&...);
// Produces a single function pointer for index I and args Args...
template
F f() const {
using ret = R;
return +[](Args&&...args)->ret{
using Invoke=Z;
return Invoke{}(std::forward(args)...);
};
}
// builds a jump table:
template
std::array,size_t(Count)>
table( std::index_sequence ) const {
return {{
f()...
}};
}
template
R operator()(Enum n, Args&&...args) {
// a static jump table for this case of Args...:
static auto jump=table(std::make_index_sequence{});
// Look up the nth entry in the jump table, and invoke it:
return jump[size_t(n)](std::forward(args)...);
}
};
then if you have an enum:
enum class abc_enum { a, b, c, count };
and a function object template:
template
struct stuff {
void operator()() const {
std::cout << (int)e << '\n';
}
};
you can dispatch:
magic_switch{}(abc_enum::b);
in any case, within the template stuff
, you get the enum value as a compile time constant. You call it with a run time constant.
Overhead should be similar to a switch statement, or a vtable call, depending on what the compiler does optimization wise.
live example.
Note that setting Enum
to std::size_t
is valid.
In C++11 you need make_index_sequence
and index_sequence
:
template
struct index_sequence {};
namespace details {
template
struct sequence_maker : sequence_maker {};
template
struct sequence_maker<0,szs...> {
using type = index_sequence;
};
}
template
using make_index_sequence=typename details::sequence_maker::type;
template
using index_sequence_for=make_index_sequence;
and this alias:
template
using result_of_t=typename std::result_of::type;
then strip std::
off their use in the above code.
live example.