对于带整数的模板化函数,我编写了以下通用调度程序:
#define Dispatch_Template(funct_name, max) \
template<int i> decltype(&funct_name<0>) Dispatch_template_##funct_name (int index) { \
return (index == i) ? funct_name <i> : Dispatch_template_##funct_name <i - 1>(index); \
} \
template<> decltype(&funct_name<0>) Dispatch_template_##funct_name <-1>(int) { \
return nullptr; \
} \
decltype(&funct_name<0>) Dispatch_##funct_name (int i) { \
return Dispatch_template_##funct_name <max>(i); \
} \
这有效,我可以这样做:
template<int some_int> void PrintInt() {
printf("int is %i\n", some_int);
}
Dispatch_Template(PrintInt, 6);
int main()
{
for (int i = 0; i < 6; ++i) {
Dispatch_PrintInt(i)();
}
return 0;
}
但是如果我想将typename参数传递给我的模板化函数呢?
例如,说它看起来像这样:
template<int some_int, typename some_type> void PrintSomeType(some_type arg) {
// do something
}
我希望能够做到这一点:
template<typename some_type> void caller(some_type arg) {
Dispatch_Template(PrintSomeType, some_type, 6);
for (int i = 0; i < 6; ++i) {
Dispatch_PrintSomeType(i)(arg);
}
}
我不知道该怎么做 - 我遇到了“这里不允许模板声明”的问题。 (注意,Dispatch_Template必须在函数内部,因为函数本身是模板化的。)
答案 0 :(得分:2)
您无法在函数内部使用声明,因为块范围中不允许使用模板。这是一个死胡同。
所以你需要一种方法在函数之外声明它。
事实证明,宏是邪恶的,只是重写宏作为模板使一切正常。
#include <utility>
#include <assert.h>
#include <iostream>
template<template<int, typename...> class func, typename... Ts>
class Dispatcher {
public:
using function_ptr = decltype(&func<0, Ts...>::call);
template<int max=10>
static function_ptr get_func(int i) {
assert(i>=0 && i<max);
return get_func_impl(i, std::make_integer_sequence<int, max>());
}
private:
template<int... vals>
static function_ptr get_func_impl(int i, std::integer_sequence<int, vals...> ) {
static constexpr function_ptr funcs[] = {&func<vals, Ts...>::call...};
return funcs[i];
}
};
template <int i, typename T>
struct Foo {
static void call(T val) {
std::cout << "Hello foo " << i << " " << val << std::endl;
}
};
int main() {
Dispatcher<Foo, double>::get_func<>(5)(2.3); // output: Hello foo 5 2.3
}
最后一步是为所需的template <...> struct X { call(); };
格式创建一个宏。这是必需的,因为您无法将模板函数传递到模板中。
注意:std :: integer_sequence只是c ++ 14,但你可以添加一个polyfill实现,例如来自here。试图在没有它的情况下实现是混乱的嵌套的部分专用结构,因为你不能专门化模板内的函数。