为什么variadic模板参数包未展开?

时间:2017-05-18 16:29:32

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

#include<tuple>
#include<iostream>
using namespace std;

class A                                                                                                                                                           
{                                                                                                                                                                 
public:                                                                                                                                                           
  int v;                                                                                                                                                          
  A(int a) : v(a){}                                                                                                                                               
  operator int (){return v;}                                                                                                                                      
};                                                                                                                                                                

class B                                                                                                                                                           
{                                                                                                                                                                 
public:                                                                                                                                                           
  int v;                                                                                                                                                          
  B(int a) : v(a + 1) {}                                                                                                                                              
  operator int (){return v;}                                                                                                                                      
};                                                                                                                                                                

class C                                                                                                                                                           
{                                                                                                                                                                 
public:                                                                                                                                                           
  int v;                                                                                                                                                          
  C(int a) : v(a + 2){}                                                                                                                                               
  operator int (){return v;}                                                                                                                                      
};                                                                                                                                                                


template <typename... Args >                                                                                                                                      
int f(int a, Args... args )                                                                                                                                      
{                                                                                                                                                                 
  tuple<Args...> argstuple1( std::forward<Args>(a)... );                                                                                                          
  tuple<Args...> argstuple2(Args{a}...);                                                                                                                          
  //The following initialization won't compile
  tuple<Args...> argstuple2(Args(a)...);

  cout << (int)std::get<2>(argstuple2) << endl;                                                                                                                   
  return 1;                                                                                                                                                       
}  

int main()
{
  f< A, B, C>(5,0,0,0);
}

我想在这里做的是,给定一个值,我有3个不同的类以3种不同的方式处理这个相同的值。我在这里遇到的问题是如何扩展参数包并使用给定的单个值a初始化每个类。

tuple<Args...> argstuple2(Args(a)...);

我认为上面的代码会扩展为

tuple<A, B, C> argstuple2(A(a), B(a), C(a));

看起来编译器并不喜欢这样。 但是,以下所有代码都可以正常编译

tuple<Args...> argstuple2(Args(1)...);
tuple<Args...> argstuple2(Args{a}...);
tuple<Args...> argstuple2(std::forward<Args>(a)...);                  

我想知道为什么Args(a)......无法扩展? Args(a)......和Args {a} ......有什么区别? std :: forward(a)怎么样......)?

我正在使用gnu 4.7.1

2 个答案:

答案 0 :(得分:2)

// now it will
using tuple_args = tuple< Args... >;                                                                                                                                                                 
tuple_args argstuple3((Args(a))...);

答案 1 :(得分:-1)

clang有一个更好的错误代码:

<source>:36:28: warning: parentheses were disambiguated as a function 
declaration [-Wvexing-parse]
   tuple<Args...> argstuple3(Args(a)...);
                            ^~~~~~~~~~~~
<source>:36:29: note: add a pair of parentheses to declare a variable
   tuple<Args...> argstuple3(Args(a)...);
                            ^
                            (      )

vexing-parse应该听起来很熟悉。 它被视为功能声明。

这个argstuple3看起来像一个函数名,它返回一个元组&lt;&gt;并有参数Args(a)。

这个Args(a)被视为返回'Args'(类型)并被传递'a'的函数指针

编译器会将其视为此类

tuple<int> argtuple3(int());

如果你试一试,你会看到同样的错误。

解决此问题的另一个选择:

tuple<Args...> argstuple3{Args(a)...};