【发布时间】:2020-02-18 08:34:25
【问题描述】:
这是一个魔法开关问题,解决方案描述为here。但是,我想知道是否有可能使它成为 3 维的,即让它基于三个给定的枚举进行切换。在理想情况下,n 维当然是首选。我首先尝试将其设为 2 维,如下所示,但我遇到了双可变参数解包,我不知道它是如何工作的。
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)...);
}
};
调用这段代码如下
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);
但是,由于双可变参数包扩展,上面无法编译。对于更多维度,甚至更多的可变参数包将不得不被解包。 n维魔法开关问题有解决办法吗?
【问题讨论】:
标签: c++ templates variadic-templates