g++ 4.5 找不到好友功能

发布于 2024-10-24 19:59:02 字数 984 浏览 5 评论 0原文

日安!

我对 C++ 中 friend 的使用有疑问。考虑下面的代码:

#include <ostream>

struct F {
};

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

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

我一直以来的理解是,friendstatic 类似,并且具有 friend 函数可以访问的附加属性班级的私人部分。在这个假设下,代码应该可以编译,因为有一个 operator<< 需要一个 ostream& 和一个(const)F&

看来 g++ 4.0 同意我的想法,因为它接受该代码。然而,较新的 g++ 4.5(.2) 拒绝代码并显示以下消息:

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

是 g++ 4.5 错误还是我(和 g++ 4.0)错误?

(将友元声明移动到 F 类中的解决方案没有帮助,因为 operator<< 将需要访问 N< 的私有部分/代码>。)

问候, 斯特凡

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& 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风情万种。 2024-10-31 19:59:03

自从我在 [class.friend] 中看到问题以来,我一直在艰难地研究标准(FCD,n3242),

人们可以阅读:

6) 当且仅当该类是非本地类 (9.8)、函数名称未限定且函数具有命名空间作用域时,才可以在类的友元声明中定义函数。

7) 这样的函数是隐式内联的。类中定义的友元函数位于定义它的类的(词法)范围内。在类外部定义的友元函数不是 (3.4.1)。

9) 由友元声明指定的名称应在包含友元声明的类范围内可访问。

那么,这里会发生什么?

struct F {
};

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

友元声明指定 operator<< 的重载为 N 的友元。但是,此重载尚未在词法范围(命名空间或类)中声明。此外,7 也不适用,因为它也没有在 N 中定义。

因此,当查找可应用于以下情况的 operator<< 重载时:

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

没有有效的重载(实际上,可能根本没有重载)。

您有两种解决方案:

  • 使用 7:在友元声明之后定义内联函数。
  • 使用 9:也在命名空间中声明该函数

因为 4 但:

4) 首先在友元声明中声明的函数具有外部链接 (3.5)。否则,该函数将保留其先前的链接 (7.1.1)。

我建议在 friend 声明之前声明它以控制其链接,但这很少有关系。

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.

月亮是我掰弯的 2024-10-31 19:59:02

问题是友元声明不提供全局函数声明,除非您提供内联实现。

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

void func3();

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

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 */
回忆那么伤 2024-10-31 19:59:02

您还必须在结构体外部声明运算符。 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;
}

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文