gcc 无法编译带有前缀命名空间的运算符定义

发布于 2024-10-13 22:09:50 字数 1630 浏览 2 评论 0原文

我在命名空间 my_namespace 中为类 my_type 声明了运算符。

namespace my_namespace {
 class my_type
 {
  friend std::ostream& operator << (std::ostream& out, my_type t);
 }
}

我正在尝试在实现文件中定义这些运算符,但是当我编写类似的内容时

std::ostream& my_namespace::operator << (std::ostream& out, my_type t)
{
 out << t;
 return out;
}

,我收到错误消息

error: ... 运算符应该在 'my_namespace' 内声明

当我将其更改为

namespace my_namespace {
    std::ostream& operator << (std::ostream& out, my_type t)
    {
     out << t;
     return out;
    }
}

then它可以编译,但我不明白这个问题。为什么这个编译失败?一切都对吗? 我希望能链接到标准,因为我真的不知道要搜索什么。

添加

file.h

#ifndef A_H
#define A_H

#include <iosfwd>

namespace N
{
 class A
 {
  friend std::ostream& operator << (std::ostream& out, A& obj);
 };
}

#endif

file.cpp

#include "file.h"
#include <iostream>

std::ostream& N::operator << (std::ostream& out, N::A& obj)
{
 return out;
}

int main() {}

这里是完整的示例。这在 VS2010 上工作正常,但在 gcc 4.4.5 上出现上述错误。

添加

嗯...是的,这个有效,

namespace N
{
    class A
    {
        friend std::ostream& operator << (std::ostream& out, A& obj);
    };
    std::ostream& operator << (std::ostream& out, A& obj);
}

我一直认为就可见性而言,在类中声明友元运算符与在类外声明是一样的......看起来并非如此。谢谢。

提前非常感谢。

I have operators declared for class my_type in namespace my_namespace.

namespace my_namespace {
 class my_type
 {
  friend std::ostream& operator << (std::ostream& out, my_type t);
 }
}

I'm trying to define these operators in implementation file, but when I write something like that

std::ostream& my_namespace::operator << (std::ostream& out, my_type t)
{
 out << t;
 return out;
}

I get error message

error: ... operator should have been declared inside 'my_namespace'

When I change it to

namespace my_namespace {
    std::ostream& operator << (std::ostream& out, my_type t)
    {
     out << t;
     return out;
    }
}

then it's compiles, but I don't understand the problem. Why does this failed to compile? Is there everything right with that?
I would appreciate link to standard as I really don't know what to search.

added

file.h

#ifndef A_H
#define A_H

#include <iosfwd>

namespace N
{
 class A
 {
  friend std::ostream& operator << (std::ostream& out, A& obj);
 };
}

#endif

file.cpp

#include "file.h"
#include <iostream>

std::ostream& N::operator << (std::ostream& out, N::A& obj)
{
 return out;
}

int main() {}

here is complete example. This works fine on VS2010, but gives above mentioned error on gcc 4.4.5.

added

hmm...yes, this one works

namespace N
{
    class A
    {
        friend std::ostream& operator << (std::ostream& out, A& obj);
    };
    std::ostream& operator << (std::ostream& out, A& obj);
}

I was always thinking that in terms of visibility declaring friend operator in class is same thing as declaring outside of the class..looks like it's not. Thanks.

Thanks much in advance.

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

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

发布评论

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

评论(2

浮华 2024-10-20 22:09:50

实际上,错误消息说明了一切。您可以将函数定义保留在实现文件中,但需要先在命名空间中声明它:

namespace my_namespace {
    std::ostream& operator << (std::ostream& out, my_type t);
}

C++ 标准对此非常清楚:

7.3.1.2/3:

首先在命名空间中声明的每个名称都是该命名空间的成员。如果非本地类中的友元声明首先声明了一个类或函数,则该友元类或函数是最内层封闭命名空间的成员。在该命名空间范围内(在授予友谊的类声明之前或之后)提供匹配的声明之前,无法通过简单的名称查找找到好友的名称。如果调用友元函数,则可以通过名称查找来找到其名称,该名称查找考虑来自与函数参数类型关联的命名空间和类的函数(3.4.2)。当查找声明为友元的类或函数的先前声明时,并且当友元类或函数的名称既不是限定名称也不是模板 ID 时,不考虑最内部封闭命名空间范围之外的范围。 .

以下链接更简单,并添加了一些示例:http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language /ref/cplr043.htm

所以我想说 gcc 在这里是错误的。。相关句子似乎是“通过简单的名称查找无法找到朋友的名字,直到在该名称空间范围内提供匹配的声明(在授予友谊的类声明之前或之后)

The error message says it all, actually. You can keep your function definition in the implementation file, but you need to declare it in the namespace first:

namespace my_namespace {
    std::ostream& operator << (std::ostream& out, my_type t);
}

The C++ standard is quite clear about this:

7.3.1.2/3:

Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship). If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2). When looking for a prior declaration of a class or a function declared as a friend, and when the name of the friend class or function is neither a qualified name nor a template-id, scopes outside the innermost enclosing namespace scope are not considered. .

The following link puts it more simply, and adds a few examples: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr043.htm

So I'd say that gcc is wrong here.. The relevant sentence seems to be "The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship).

完美的未来在梦里 2024-10-20 22:09:50

声明引用了一组其他名称,并引入了一个新名称;这个新名称不能用名称空间标识符限定,但声明需要位于应声明新名称的名称空间块内。

相同的规则适用于定义,因为它们意味着声明。友元声明很特殊,因为它存在于另一个定义中,并且没有真正声明任何内容。

Declarations refer to a set of other names, and introduce a single new name; this new name must not be qualified with a namespace identifier, but rather the declaration needs to be inside the namespace block in which the new name should be declared.

The same rules apply to definitions, as they imply a declaration. The friend declaration is special, because it lives inside another definition and doesn't really declare anything.

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