Why are variable patterns of template parameters not expanded?

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

      

What I am trying to do here is one meaning, I have 3 different classes to handle this same value in 3 different ways. The problem I got here is how to extend the parameter packages and initialize each class with a given a value.

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

      

I would have thought the above code would be expanded to

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

      

It looks like the compiler doesn't like this. However, all the following codes just compile small

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

      

I would like to know why Args (a) ... cannot expand? What is the difference between Args (a) ... and Args {a} ...? How about std :: forward (a) ...)?

I am using gnu 4.7.1

+3


source to share


2 answers


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

      



+2


source


clang has a better error code:

<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 should sound familiar. This is considered a function declaration.

This argstuple3 looks like a function name that returns a tuple <> and has Args (a) arguments.

This Args (a) is treated as a function pointer which returns 'Args' (type) and is passed 'a'



The compiler will see it something like this

tuple<int> argtuple3(int());

      

If you try, you will see the same exact error.

Another possibility to solve this problem:

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

      

-1


source







All Articles