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
source to share
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)...};
source to share