在我的程序中,我有一些看起来像这样的代码:一组函数或类,它们通过模板特化独特地实现了一个通用模板:
constexpr int NUM_SPECIALIZATIONS = 32;
template<int num>
void print_num(){}
template<>
void print_num<0>(){cout << "Zero" << endl;}
template<>
void print_num<1>(){cout << "One" << endl;}
template<>
void print_num<2>(){cout << "Two" << endl;}
// etc, ...
template<>
void print_num<31>(){cout << "Thirty-One" << endl;}
Run Code Online (Sandbox Code Playgroud)
然后我有一个变量,它的值只在运行时才知道:
int my_num;
cin >> my_num; // Could be 0, could be 2, could be 27, who tf knows
Run Code Online (Sandbox Code Playgroud)
然后我需要调用对应于变量值的模板特化。由于我不能使用变量作为模板参数,我会创建一种“解释器”:
switch(my_num)
{
case 0:
print_num<0>();
break;
case 1:
print_num<1>();
break;
case 2:
print_num<2>();
break;
// etc, ...
case 31: …Run Code Online (Sandbox Code Playgroud) 我的 C++ 项目中有几段代码,如下所示:
system<0>::global_instance.do_something();
system<1>::global_instance.do_something();
system<2>::global_instance.do_something();
system<3>::global_instance.do_something();
//...
system<29>::global_instance.do_something();
system<30>::global_instance.do_something();
system<31>::global_instance.do_something();
Run Code Online (Sandbox Code Playgroud)
好像有点重复吧?如果我能做这样的事情就太好了:
for(int i = 0; i < 32; i++)
{
system<i>::global_instance.do_something();
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这行不通,因为 的值i在编译时未知,因此不能用作system.
我需要的是一种在编译时展开或展开循环的方法。
我已经看到一些使用模板来实现展开的实现,但它们不适用于我想要做的事情。理想情况下,循环展开将在预处理期间进行,并且可以将任意语句作为输入。
例如,这个:
#unroll NUM 0 5
foo<NUM>();
#endunroll
Run Code Online (Sandbox Code Playgroud)
会被翻译成这样:
foo<0>();
foo<1>();
foo<2>();
foo<3>();
foo<4>();
foo<5>();
Run Code Online (Sandbox Code Playgroud)
和这个:
#unroll NUM 0 5
blah blah blah NUM
#endunroll
Run Code Online (Sandbox Code Playgroud)
会被翻译成这样:
blah blah blah 0
blah blah blah 1
blah blah blah 2
blah blah blah 3
blah blah blah 4
blah blah blah 5 …Run Code Online (Sandbox Code Playgroud) 我希望能够使用文字作为 id 来引用不同的类型。
template<auto>
using type = void;
template<>
using type<0> = int;
template<>
using type<1> = char;
template<>
using type<2> = string;
int main()
{
type<0> var0;
type<1> var1;
type<2> var2;
}
Run Code Online (Sandbox Code Playgroud)
这会导致编译器给出错误,因为 C++ 尚不支持类型别名专门化。(实现这种功能所需的技术根本不存在)
我想:
\ntemplate<class ... T>\nauto foo()\n{\n // \xe2\x9c\xa8 magic \xe2\x9c\xa8\n}\nRun Code Online (Sandbox Code Playgroud)\n这样:
\n(foo<int, char, bool>() == foo<char, int, bool>()) // True\n(foo<int>() == foo<char>()) // False\nRun Code Online (Sandbox Code Playgroud)\n换句话说,我希望 foo 为传递给它的类型组合返回一个唯一的 id ,而不是传递给它的类型的排列。
\n我的第一个想法是,可能有某种方法可以在编译时对参数包进行排序,尽管我不确定这到底是如何工作的。
\n我目前的解决方案是这样的:
\n// Precondition: Client must pass the parameters in alphabetical order to ensure the same result each time\ntemplate<class ... T>\nstd::type_index foo()\n{\n return std::make_type_index(typeid(std::tuple<T ... >));\n}\nRun Code Online (Sandbox Code Playgroud)\n这样做的问题是,如果客户端使用类型别名,它就不起作用。例如:
\nusing my_type = char;\n(foo<bool, int, my_type>() == foo<bool, char, int>()) // False\nRun Code Online (Sandbox Code Playgroud)\n …