强制模板成员函数实例化
Forcing template member function to instantiate
我在命名空间 N 中有一个 class C 和一个 public 模板成员函数 F,如下所示:
namespace N {
class C {
public:
template<int I>
void F() {
// ...
}
};
};
I
对 N::C::F<I>
的值直到运行时才知道。但是,I
的值被限制为 0 <= I < 2^8
。我正在寻找一种方法来强制此函数将模板扩展到所有 256 种可能的形式。
到目前为止,我已经在 C
的第二个函数中手动创建了一个静态数组,它指向每个可能的函数:
template<int I>
void F() {
// ...
}
void G(int I) {
static void(* const funcs[256])() = {
F<0>, F<1>, F<2>, ...
};
funcs[I]();
}
虽然我想知道是否有更好的方法。我已经在 N
中有一个宏,它负责为 I
的每个值构造一个单独的结构(供 F 本身使用),并且正在寻找是否可以集成模板成员函数的实例化不知何故:
template<int> struct S;
#define M(I, n) \
template<> struct S<I> { \
static const char name[] = #n; \
/*
Some how instantiate the function here, like (just guessing here):
static const SEvaluator<I> eval = &C::F<I>;
given
template<int I>
using SEvaluator = void(*)();
*/
};
M(0, "foo"); M(1, "bar");
#undef M
我提出的方法无法按原样运行,编译器抱怨 F 不是 constexpr。 F 操作 C
的几个变量并调用外部方法,不能声明为 constexpr。有没有办法挽救这个,还是我必须求助于我的第一个 hackish 方法?
您可以使用 index_sequence<I...>
(C++14) 并将 I
扩展到静态数组中。
template<std::size_t... Is>
void G(int i, std::index_sequence<Is...>) {
using C = void(C::*)();
static C funcs[sizeof...(Is)] = { &C::F<Is>... };
(this->*funcs[i])();
}
void G(int i) {
G(i, std::make_index_sequence<256>());
}
对于非 C++14 解决方案,您可以编写自己的 index_sequence
版本:
template<int... Is>
struct index_sequence { };
template<int N, int... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> { };
template<int... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> { };
显然我被蝙蝠侠打败了。无论如何我都会post这个:原理是一样的,只是换了一种方式。
template <std::size_t... Idx>
auto const &makeFunctions(std::index_sequence<Idx...>) {
static auto funcs = {&N::C::F<Idx>...};
return funcs;
}
auto const &function(std::size_t i) { return *(begin(makeFunctions(std::make_index_sequence<256>{})) + i); }
致电:
N::C c;
for(int i = 0; i < 10; ++i)
(c.*function(i))();
我在命名空间 N 中有一个 class C 和一个 public 模板成员函数 F,如下所示:
namespace N {
class C {
public:
template<int I>
void F() {
// ...
}
};
};
I
对 N::C::F<I>
的值直到运行时才知道。但是,I
的值被限制为 0 <= I < 2^8
。我正在寻找一种方法来强制此函数将模板扩展到所有 256 种可能的形式。
到目前为止,我已经在 C
的第二个函数中手动创建了一个静态数组,它指向每个可能的函数:
template<int I>
void F() {
// ...
}
void G(int I) {
static void(* const funcs[256])() = {
F<0>, F<1>, F<2>, ...
};
funcs[I]();
}
虽然我想知道是否有更好的方法。我已经在 N
中有一个宏,它负责为 I
的每个值构造一个单独的结构(供 F 本身使用),并且正在寻找是否可以集成模板成员函数的实例化不知何故:
template<int> struct S;
#define M(I, n) \
template<> struct S<I> { \
static const char name[] = #n; \
/*
Some how instantiate the function here, like (just guessing here):
static const SEvaluator<I> eval = &C::F<I>;
given
template<int I>
using SEvaluator = void(*)();
*/
};
M(0, "foo"); M(1, "bar");
#undef M
我提出的方法无法按原样运行,编译器抱怨 F 不是 constexpr。 F 操作 C
的几个变量并调用外部方法,不能声明为 constexpr。有没有办法挽救这个,还是我必须求助于我的第一个 hackish 方法?
您可以使用 index_sequence<I...>
(C++14) 并将 I
扩展到静态数组中。
template<std::size_t... Is>
void G(int i, std::index_sequence<Is...>) {
using C = void(C::*)();
static C funcs[sizeof...(Is)] = { &C::F<Is>... };
(this->*funcs[i])();
}
void G(int i) {
G(i, std::make_index_sequence<256>());
}
对于非 C++14 解决方案,您可以编写自己的 index_sequence
版本:
template<int... Is>
struct index_sequence { };
template<int N, int... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> { };
template<int... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> { };
显然我被蝙蝠侠打败了。无论如何我都会post这个:原理是一样的,只是换了一种方式。
template <std::size_t... Idx>
auto const &makeFunctions(std::index_sequence<Idx...>) {
static auto funcs = {&N::C::F<Idx>...};
return funcs;
}
auto const &function(std::size_t i) { return *(begin(makeFunctions(std::make_index_sequence<256>{})) + i); }
致电:
N::C c;
for(int i = 0; i < 10; ++i)
(c.*function(i))();