小编Log*_*ick的帖子

(C++) 编译时自动生成switch语句case

在我的程序中,我有一些看起来像这样的代码:一组函数或类,它们通过模板特化独特地实现了一个通用模板:

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++ templates metaprogramming template-meta-programming

5
推荐指数
1
解决办法
202
查看次数

C++ 在编译时展开循环

我的 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)

c++ metaprogramming template-meta-programming

3
推荐指数
1
解决办法
87
查看次数

C++ 中缺乏对类型别名专门化支持的解决方法

我希望能够使用文字作为 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++ 尚不支持类型别名专门化。(实现这种功能所需的技术根本不存在)

c++ template-specialization type-alias

3
推荐指数
2
解决办法
203
查看次数

参数包排序(或等效行为)

我想:

\n
template<class ... T>\nauto foo()\n{\n  // \xe2\x9c\xa8 magic \xe2\x9c\xa8\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这样:

\n
(foo<int, char, bool>() == foo<char, int, bool>()) // True\n(foo<int>() == foo<char>()) // False\n
Run 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}\n
Run Code Online (Sandbox Code Playgroud)\n

这样做的问题是,如果客户端使用类型别名,它就不起作用。例如:

\n
using my_type = char;\n(foo<bool, int, my_type>() == foo<bool, char, int>()) // False\n
Run Code Online (Sandbox Code Playgroud)\n …

c++ templates variadic-templates c++20

1
推荐指数
1
解决办法
334
查看次数