繁体   English   中英

空包可变参数模板

[英]Empty Pack Variadic Template

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

enum class Action {A, B};

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

template <Action a>
void applyAction();

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

template <Action a, Action... as>
void applyActions() {
  applyAction<a>();
  applyActions<as...>();
}

这段代码很好。 确实:

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

正确生成:

call void applyAction<(Action)0>()
call void applyAction<(Action)1>()

GodBolt示例在这里


为了实现扩展包终止,我必须声明哑元函数:

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

这对我来说非常“丑陋”,因为它使调用通用类型成为可能。

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

当然,它的声明不必使所需的功能产生歧义:

template <Action a, Action... as>
void applyActions();

就像是:

template <Action.. = {}>
void applyActions() {}

由于呼叫歧义, 这里是不可编译的示例。 但是它给出了我想要实现的想法。

下面是另一种结构化方式,您可以删除“ ugly”默认值,它也删除了递归,并且可以与空的action参数包一起使用,

#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;
}

演示

正如HolyBlackCat指出的那样,在c ++ 17中,您可以使用fold表达式,

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

       (applyAction<as>(), ...);
}

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

是的:存在,而且微不足道

template <Action...>
void applyActions()

问题是,在您的情况下,与一个或多个元素接受的函数冲突

template <Action a, Action... as>
void applyActions()

以及当您调用applyActions<as...>(); 带有不为空的as...包,两个模板都匹配。

使用名称相同但类型不同的模板函数(以及默认值)

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

(IMHO)这是一种非常聪明,便宜且优雅的解决终端问题的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM