Issue
The following program compiles with using clang HEAD 10.0.0
#include <iostream>
template <class T>
void f( const T & );
class A
{
public:
A( int x = 0 ) : x( x ) {}
friend void ::f( const A & );
private:
int x;
};
template <class T>
void f( const T &t )
{
std::cout << "t.x = " << t.x << '\n';
}
int main()
{
A a( 10 );
f( a );
}
The program output is
t.x = 10
But when the gcc HEAD 10.0.0 20190
compiler is used then it outputs the error
prog.cc:11:32: error: 'void f(const A&)' should have been declared inside '::'
11 | friend void ::f( const A & );
| ^
Is it a bug of the compiler or am I doing something wrong?
Solution
Filed 91618.
[temp.friend]/1 reads:
A friend of a class or class template can be a function template or class template, a specialization of a function template or class template, or a non-template function or class. For a friend function declaration that is not a template declaration:
- if the name of the friend is a qualified or unqualified template-id, the friend declaration refers to a specialization of a function template, otherwise,
- if the name of the friend is a qualified-id and a matching non-template function is found in the specified class or namespace, the friend declaration refers to that function, otherwise,
- if the name of the friend is a qualified-id and a matching function template is found in the specified class or namespace, the friend declaration refers to the deduced specialization of that function template ([temp.deduct.decl]), otherwise,
- the name shall be an unqualified-id that declares (or redeclares) a non-template function.
That third bullet should allow this:
template <class T> void f(T);
struct A {
friend void ::f(A);
};
::f
is a qualified-id and a matching function template is found, so it should work. But gcc requires us to write ::f<>
, which is a template-id, in order to adhere to the first bullet.
Answered By - Barry