0

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?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Doing `friend void ::f<>( const A & )` makes GCC happy. I'm sure this is a bug. – David G Aug 30 '19 at 16:32
  • 3
    Dup of [Qualified friend function template instantiation](https://stackoverflow.com/questions/54055575/qualified-friend-function-template-instantiation) – Language Lawyer Aug 29 '20 at 15:07

1 Answers1

4

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.

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977