2

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.

Columbo
  • 60,038
  • 8
  • 155
  • 203
zpeng
  • 101
  • 5
  • please note that, if a template is instantiated, its friends are treated declared, **which means friend name is visible**. I know the second one can be found by ADL – zpeng Sep 17 '15 at 08:16

2 Answers2

3

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.

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • your said is right. But my questions is not ADL. I really want to know why compile are not line with C++ specification( instantiated means friend visible). – zpeng Sep 17 '15 at 08:22
  • @zpeng "Instantiated means friend visible" is nonsense. – Columbo Sep 17 '15 at 08:24
  • I cannot understand what's real mean in C++ specification("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."). – zpeng Sep 17 '15 at 08:40
  • @zpeng You're misinterpreting that quote. It is not making the `friend`s generally visible. And GCC 3.4 is horribly bugged, so don't base your understanding of the language on that completely outdated version. – Columbo Mar 20 '16 at 10:33
1

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.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203