开发者

g++ 4.5 can't find a friend function

开发者 https://www.devze.com 2023-02-18 04:42 出处:网络
G\'day! I have a question around the use of friend in C++. Consider the following piece of code: #include <ostream>

G'day!

I have a question around the use of friend in C++. Consider the following piece of code:

#include <ostream>

struct F {
};

struct N {
  friend std::ostream&a开发者_如何学运维mp; operator<< (std::ostream&, const N&);
  friend std::ostream& operator<< (std::ostream&, const F&);    
};

void foo(std::ostream &out) {
  F bar;
  out << bar;
}

My understanding always was, that friend is similar to static with the additional property that the friend function has access to the private part of the class. Under that assumption, the code should compile, since there is an operator<< that takes an ostream& and a (const) F&.

It appears that g++ 4.0 shares my thoughts on this, as it accepts that code. The much newer g++ 4.5(.2) however, rejects the code with the message:

ns.cc: In function 'void foo(std::ostream&)':
ns.cc:14:10: error: no match for 'operator<<' in 'out << bar'

is g++ 4.5 wrong or am I (and g++ 4.0) wrong?

(The solution to move the friend declaration into the F class doesn't help, as the operator<< will need access to the private part of N.)

Regards, Stefan


The problem is that a friend declaration doesn't provide a global function declaration, unless you provide an inline implementation.

struct N {
   friend void func1() { }
   friend void func2();
   friend void func3();
};

void func3();

func1(); /* OK */
func2(); /* not OK */
func3(); /* OK */


You have to declare the operators outside the struct as well. Same error is reported by gcc 4.4.

#include <ostream>

struct F {
};

struct N {
  friend std::ostream& operator<< (std::ostream&, const N&);
  friend std::ostream& operator<< (std::ostream&, const F&);    
};

std::ostream& operator<< (std::ostream&, const N&);
std::ostream& operator<< (std::ostream&, const F&);    

void foo(std::ostream &out) {
  F bar;
  out << bar;
}


I've been trudging through the standard (FCD, n3242) since I saw the question

In [class.friend] one can read:

6) A function can be defined in a friend declaration of a class if and only if the class is a non-local class (9.8), the function name is unqualified, and the function has namespace scope.

7) Such a function is implicitly inline. A friend function defined in a class is in the (lexical) scope of the class in which it is defined. A friend function defined outside the class is not (3.4.1).

9) A name nominated by a friend declaration shall be accessible in the scope of the class containing the friend declaration.

So, what happens here ?

struct F {
};

struct N {
  friend std::ostream& operator<< (std::ostream&, const F&);    
};

The friend declaration nominates this overload of operator<< to be a friend of N. However this overload has not been declared in a lexical scope (either namespace or class). Also, 7 does not apply because it is not defined within N either.

Therefore, when looking up the overloads of operator<< that can apply in:

void foo(std::ostream &out) {
  F bar;
  out << bar;
}

There is no valid overload (actually, it could be there is no overload at all).

You have two solutions:

  • use 7: define the function inline following the friend declaration.
  • use 9: declare the function in the namespace too

Because of 4 though:

4) A function first declared in a friend declaration has external linkage (3.5). Otherwise, the function retains its previous linkage (7.1.1).

I would recommend declaring it prior to the friend declaration to control its linkage, but it will rarely matters.

0

精彩评论

暂无评论...
验证码 换一张
取 消