Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic template works in gcc but not in clang

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

2 Answers

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.

like image 88
HolyBlackCat Avatar answered Jan 30 '26 04:01

HolyBlackCat


GCC is wrong in accepting the program because a function parameter pack is introduced using an ellipsis (...) prior to (or in the place of) the function parameter name.

This means in your example the correct way to declare the function with parameter of type pointer to function is T v(V...());. But note that gcc rejects this modified code. Demo

Here is the gcc bug report:

GCC accepts invalid program involving function declaration with pack expansion

Note

It quite interesting to note that gcc rejects T v(V...()) but accepts T v(V...b()). Demo

template<typename T, typename... V> 
struct C 
{
//-------vvv---------->this is the correct way which gcc rejects 
    T v(V...());
//-------vvv---------->but gcc accepts this when we name the parameter
    T v(V...b());
};
like image 23
Anoop Rana Avatar answered Jan 30 '26 04:01

Anoop Rana



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!