使用可变参数模板参数包可以做到这一点吗?

时间:2014-07-05 01:22:35

标签: c++ templates c++11 variadic-templates

在下面的代码中,我在初始化列表中展开参数包,同时在每个元素上调用函数DoSomethingReturnInt。在下面,我尝试做一些看似类似的尝试,并在每个元素上调用DoSomething,但得到编译器错误。这根本不可能,或者我只是需要稍微修改它来完成这个?在我看来,这样的事情应该是可能的。

template <class T>
int DoSomethingReturnInt(T&& t) 
{}

template <class T>
void DoSomething(T&& t) 
{}

template <class... T>
void variadic(T&&... args) 
{
    int arr[] = { DoSomethingReturnInt(args)... }; //Compiles OK
    DoSomething(args)...; //error: parameter packs not expanded with '...'
}

int main()
{
    variadic("Testing", "one", 2.0, 3);
}

2 个答案:

答案 0 :(得分:4)

这不是参数包扩展的有效位置。有关包扩展的有效上下文包含在draft C++ standard部分14.5.3 可视化模板中,其中包含:

  

包扩展由模式和省略号组成   其实例化产生零个或多个实例化   列表中的模式(如下所述)。模式的形式取决于   在扩张发生的背景下。包装扩展可以   发生在以下情况中:

     

- 在函数参数包中   (8.3.5);模式是没有的参数声明   省略号。

     

- 在作为包扩展的模板参数包(14.1)中:

     

- 如果模板参数包是参数声明;模式是参数声明   没有省略号;

     

- 如果模板参数包是带有template-parameter-list的type-parameter;模式是   没有省略号的相应类型参数。

     

- 在初始化列表中(8.5);模式是初始化子句。

     

- 在基本说明符列表中(第10条);模式是基本说明符。

     

- 在mem-initializer-list(12.6.2)中;该模式是一个mem-initializer。

     

- 在template-argument-list(14.3)中;模式是模板参数。

     

- 在动态异常规范(15.4)中;模式是一个类型ID。

     

- 在属性列表(7.6.1)中;模式是一个属性。

     

- 在alignment-specifier(7.6.2)中;模式是没有省略号的alignment-specifier。

     

- 在捕获列表(5.1.2)中;模式是捕获。

     

- 在sizeof ...表达式中(5.3.3);模式是一个标识符。

Parameter pack的cppreference部分也介绍了这一点。

答案 1 :(得分:4)

您可以在此处使用逗号运算符。

int dummy[] = { (DoSomething(args), 0)... };

编辑:如果你不喜欢逗号运算符“滥用”,可能是lambda?

int dummy[] = { []() { DoSomething(args); return 0; }()... };

请注意,gcc4.9似乎无法处理这个问题,但是clang会做得很好。