Why do gcc HEAD 10.0.0 20190
and Clang HEAD 9.0.0
both reject this program?
#include <iostream>
void g( int x )
{
std::cout << "Hello g( " << x << " )\n";
}
template <int N>
void g()
{
std::cout << "Hello g<N>( " << N << " )\n";
}
namespace N
{
using ::g;
}
void g( int x = 20 );
template <int N = 10>
void g();
int main()
{
N::g();
N::g<>();
}
For example gcc
issues the error
prog.cc: In function 'int main()':
prog.cc:27:11: error: no matching function for call to 'g()'
27 | N::g<>();
| ^
prog.cc:9:6: note: candidate: 'template<int N> void g()'
9 | void g()
| ^
prog.cc:9:6: note: template argument deduction/substitution failed:
prog.cc:27:11: note: couldn't deduce template parameter 'N'
27 | N::g<>();
| ^
though according to the C++ 20 (and 17) Standard (9.8 The using declaration)
11 [Note: For a using-declaration whose nested-name-specifier names a namespace, members added to the namespace after the using-declaration are not in the set of introduced declarations, so they are not considered when a use of the name is made. Thus, additional overloads added after the using-declaration are ignored, but default function arguments (9.2.3.6), default template arguments (13.1), and template specializations (13.6.5, 13.8.3) are considered. — end note]
Based on my reading of the standard, I believe this is a bug.
This issue is the subject of Core issue 1907. The current direction is to treat such cases as ill-formed, no diagnostic required.
As it turns out, some implementations track default arguments on a "per-entity" basis (so it would be difficult to not consider default arguments added in a later redeclaration), while others track them on a "per-declaration" basis (so it would difficult to make them consider such default arguments). CWG decided to accommodate both implementation strategies by classifying code that depends on such things IFNDR.