具有类型名的模板的递归实例化
Recursive instantiation of a template with a typename?
对于采用整数的模板化函数,我编写了以下通用调度程序:
#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 %in", 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必须位于函数内部,因为函数本身是模板化的。
无法让声明在函数中工作,因为块范围内不允许使用模板。这是一个死胡同。
因此,您需要一种方法来在函数外部声明它。
事实证明,宏是邪恶的,只需将宏重写为模板即可使一切正常工作。
#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 实现,例如从这里。尝试在没有它的情况下实现嵌套的部分专用结构是混乱的,因为您无法在模板内专门化功能。
相关文章:
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 字符串化递归的"std::vector<std::vector<...>>"而不使用部分模板函数专用化
- C++类 - 初始化列表 - 递归 - 按值传递
- C++:递归地将字符串中一个字母的所有实例替换为另一个字母
- 使用元编程递归初始化 std::array
- 如果我具有调用其其他实例之一的超载函数,它是否被认为是递归功能
- 使用迭代器对向量的C 递归初始化产生不一致的结果
- 具有类型名的模板的递归实例化
- 尝试使用 OpenMP 并行化递归函数的冗余计算
- 是否有可能摆脱模板专用化以停止递归
- 无限递归模板实例化使用clang时GCC工作正常
- 可变参数模板实例化中的无限递归,试图构建任意深度的树状结构
- 包含自身实例化的模板,C++中的递归
- 递归序列化导致vc10/11中出现堆栈溢出错误,但vc9中没有
- Boost多精度:递归模板实例化超过最大长度256
- 类在递归函数内部实例化,c++
- 内部模板类的递归专用化结束
- 如何理解和修复递归模板实例化错误使用boostublas
- 全局范围的对象不是递归初始化的
- 递归模板实例化超出了最大深度 256