The nested call of variadic methods with an additional non-type template parameter (with a default value) of class templates results in compiler errors for clang and g++ (msvc compiles without problems) if the non-type template parameter of the called method is explicitly specified. The errors can be reproduced with the following minimal example:
#include <iostream>
#include <vector>
template< typename T >
struct S;
template< typename T >
struct SProxy
{
template< int i = 20, typename... Ts >
auto f( Ts&&... args );
S< T >* s1;
int ii;
};
template< typename T >
struct S
{
template< int i = 20, typename... Ts >
auto f( int ii, Ts && ... args )
{
auto res = std::pair< int, int >( std::forward< Ts >( args )... );
res.first += i + ii;
res.second += i + ii;
return res;
}
};
template< typename T >
template< int i, typename... Ts >
auto SProxy< T >::f( Ts&&... args )
{
return s1->f< i >( ii, std::forward< Ts >( args )... );
}
int main( const int argc, const char* argv[] )
{
S< int > s;
SProxy< int > sProxy{ &s, 3 };
auto pair = sProxy.f< 10 >( 11, 12 );
std::cout << pair.first << " " << pair.second << std::endl;
return 0;
}
The error message produced by clang 9.0.0 is
<source>:36:53: error: expected ')'
return s1->f< i >( ii, std::forward< Ts >( args )... );
If the line return s1->f< i >( ii, std::forward< Ts >( args )... );
is altered to return s1->f( ii, std::forward< Ts >( args )... );
, i.e., the default non-type template parameter is used, the code compiles (and the corresponding binary works) just fine for clang and g++.
My question is if the construct employed in the minimal example is not compliant to the C++17 standard and if so why, or if there is anything wrong with the syntax used and if so how to do it correctly, or (quite unlikely) if the errors are a result of bugs in clang and g++?
Edit: Wrong Compiler Explorer link removed