This is a magic switch problem, the solution was described here. However, I was wondering if it was possible to make it 3-dimensional, i.e. let it switch based on three given enums. In the ideal case, n-dimensional would be preferred of course. I tried first to make it 2-dimensional as shown below, but I run into double variadic unpacking, and I cannot find out how that would work.
template<class Enum, class Enum2, template<Enum, Enum2>class Z>
struct magic_switch {
// return value of a call to magic_switch(Args...)
template<class...Args>
using R = std::result_of_t<Z<Enum(0), Enum2(0)>(Args...)>;
// A function pointer for a jump table:
template<class...Args>
using F = R<Args...>(*)(Args&&...);
// Produces a single function pointer for index I and args Args...
template<size_t I, size_t I2, class...Args>
F<Args...> f() const {
using ret = R<Args...>;
return +[](Args&&...args)->ret{
using Invoke=Z<Enum(I), Enum(I2)>;
return Invoke{}(std::forward<Args>(args)...);
};
}
// builds a jump table:
template<class...Args, size_t...Is, size_t ...Is2>
std::array<F<Args...>,size_t(Enum::COUNT)>
table( std::index_sequence<Is...>, std::index_sequence<Is2...> ) const {
return {{
f<Is, Is2, Args...>()... ... // << -- 2d expansion not working
}};
}
template<class...Args>
R<Args...> operator()(Enum n, Enum2 n2, Args&&...args) {
// a static jump table for this case of Args...:
static auto jump=table<Args...>(std::make_index_sequence<size_t(Enum::COUNT)>{}, std::make_index_sequence<size_t(Enum2::COUNT)>{});
// Look up the nth entry in the jump table, and invoke it:
return jump[size_t(n) + size_t(Enum::COUNT) * size_t(n2)](std::forward<Args>(args)...);
}
};
Calling this code would be as follows
enum class abc_enum { a, b, c, COUNT };
enum class defg_enum { d, e, f, g, COUNT };
template<abc_enum e, defg_enum f>
struct stuff {
void operator()() const {
std::cout << (int)e << '\n';
std::cout << (int)f << '\n';
}
};
magic_switch<abc_enum, defg_enum, stuff>{}(abc_enum::b, defg_enum::f);
However, above does not compile due to the double variadic pack expansion. For more dimensions, even more variadic packs would have to be unpacked. Is there a solution for the n-dimensional magic switch problem?