空包Variadic模板

Bia*_*sta 2 c++ templates template-meta-programming variadic-templates c++11

假设我在编译时要执行一些操作:

enum class Action {A, B};
Run Code Online (Sandbox Code Playgroud)

现在我编写一个模板可变参数函数,它按顺序执行一个可能的动作组合:

template <Action a>
void applyAction();

template <typename = void>
void applyActions() {}

template <Action a, Action... as>
void applyActions() {
  applyAction<a>();
  applyActions<as...>();
}
Run Code Online (Sandbox Code Playgroud)

这段代码很好.确实:

void foo() {
  applyActions<Action::A, Action::B>();
}
Run Code Online (Sandbox Code Playgroud)

正确生成:

call void applyAction<(Action)0>()
call void applyAction<(Action)1>()
Run Code Online (Sandbox Code Playgroud)

GodBolt示例在这里


为了实现扩展包终止,我不得不声明虚函数:

template <typename = void> void applyActions() {}
Run Code Online (Sandbox Code Playgroud)

这对我来说非常"难看",因为它提供了调用泛型类型的可能性.

在C++ 11中,有没有办法声明一个接受空参数包的可变参数函数?

当然,它的声明不必带来所需函数的模糊性:

template <Action a, Action... as>
void applyActions();
Run Code Online (Sandbox Code Playgroud)

就像是:

template <Action.. = {}>
void applyActions() {}
Run Code Online (Sandbox Code Playgroud)

是一个不可编译的例子,因为调用含糊不清.但它给出了我想要实现的目标.

rma*_*son 5

另一种构造它的方法,以便您可以删除"丑陋"的默认值,如下所示,它也会删除递归,并且可以使用空操作参数包,

#include <iostream>
using namespace std;

enum class Action {A, B};

template <Action a>
void applyAction()
{
   std::cout << "Action  " << (int)a << std::endl;
}

template <Action... as>
void applyActions() {
    using do_= int[];
    (void)do_{0, ( 
       applyAction<as>()
    ,0)...}; 
}

void foo() {
  applyActions<Action::A, Action::B>();
}

void bar() {
  applyActions<Action::B, Action::A>();
}


int main() {
    foo();
    bar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

演示

正如HolyBlackCat所指出的,在c ++ 17中你可以使用折叠表达式,

template <Action... as>
void applyActions() {

       (applyAction<as>(), ...);
}
Run Code Online (Sandbox Code Playgroud)