Reputation: 59
#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
Upvotes: 4
Views: 1310
Reputation: 878
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. It is seen as a function declaration.
This argstuple3 looks like a function name, that returns a tuple<> and has arguments Args(a).
This Args(a) is seen as function pointer that returns 'Args' (type) and being passed 'a'
Compiler will see it as something like this
tuple<int> argtuple3(int());
If you give it a try, you'll see the same exact error.
Another option to solve this:
tuple<Args...> argstuple3{Args(a)...};
Upvotes: -1
Reputation: 69912
// now it will
using tuple_args = tuple< Args... >;
tuple_args argstuple3((Args(a))...);
Upvotes: 3