zpeng
zpeng

Reputation: 101

friend function name visible in class template

Consider the following example:

template <typename T>
class C
{
    public:
        friend void f() {}
        friend void f(C<T>) {}
};

C<int> c;

void g(C<int>* p)
{
     f(); 
     f(*p);
}

Compiling with GCC 5.2 throws the following compile error:

no matching function for call to 'f()'

But the standard says in 14.6.5:

Friend classes or functions can be declared within a class template. When a template is instantiated, the names of its friends are treated as if the specialization had been explicitly declared at its point of instantiation.

Why does this fail to compile? In GCC 3.4, it passes.

Upvotes: 2

Views: 186

Answers (2)

Columbo
Columbo

Reputation: 60979

f can only be found via argument-dependent name lookup (ADL). The second call compiles because the pointee of p, which is passed as an argument, is of type C<int> - this causes ADL to jump in and inspect otherwise invisible functions. In fact, the first overload of f can't be found at all, as there is no way of conveying an association to any specialization of C.

Just see the quote right after yours, [temp.inject]/2:

As with non-template classes, the names of namespace-scope friend functions of a class template specialization are not visible during an ordinary lookup unless explicitly declared at namespace scope (11.3). Such names may be found under the rules for associated classes (3.4.2). 141


141) Friend declarations do not introduce new names into any scope, either when the template is declared or when it is instantiated.

Upvotes: 3

Bo Persson
Bo Persson

Reputation: 92261

The call to f() is in no way associated with class C, so its friends are not used in the overload resolution.

In the other call, f(*p), the parameter is of class type and therefore the class and the namespace of the class are checked for possible candidates. That way the compiler will find both f functions and use overload resolution to select the proper one.

Upvotes: 1

Related Questions