I'm learning C using the books listed here. In particular I read about variadic templates. Now, to further clear my concepts I'm also writing simple examples and trying to understand them by myself using debugger and cout statements.
One such program that compiles with gcc but is rejected by clang is given below. Demo.
template<typename T, typename... V>
struct C
{
T v(V()...);;
};
int main()
{
C<int> c; //works with gcc but rejected in clang
C<int, double, int, int> c2; //same here: works with gcc but rejected in clang
}
So my question is which compiler is right here(if any)?
Here is the error that clang gives:
<source>:6:12: error: '...' must be innermost component of anonymous pack declaration
T v(V()...);;
^~~
...
1 error generated.
Compiler returned: 1
CodePudding user response:
Clang is wrong in rejecting the program because T v(V()...);
is a valid member function declaration and the program is well-formed as V()
is a valid pattern for the pack expansion V()...
.
Here is the clang bug report:
Clang rejects valid function declaration involving pack expansion
CodePudding user response:
This is a GCC bug. The correct syntax is T v(V...());
, which Clang accepts and GCC rejects (incorrectly).
In a function parameter list, the ...
that expands a pack must precede the parameter name, or be in the place where the name would otherwise be. This is more commonly seen in cases like V &&... v
.
The related grammar is: function-definition -> declarator -> parameters-and-qualifiers -> ... -> parameter-declaration -> abstract-declarator ("abstract" = no parameter name).
[dcl.fct]/26
says that if there's an ambiguity in a function parameter list whether ...
is a pack expansion or a C-style variadic parameter, it resolves to a pack expansion. But in this case there's no ambiguity, V()...
leaves the pack unexpanded (which should be a compilation error) and ...
should be a C-style variadic parameter.