why variadic template parameter packs not expanded?

Viewed 1116
#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, given one value, I have 3 different classes to handle this same value in 3 different ways. The problem I got here is how to expand the parameter packs and initialize each class with the given single value a.

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

I would think the above code would be expanded into

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

Looks like the compiler doesn't like this. However, all following codes would just compile fine

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)... fails to expand? What is the difference between Args(a)... and Args{a}...? How about std::forward(a)...)?

I am using gnu 4.7.1

2 Answers
Related