gcc failes用前缀命名空间编译运算符定义

led*_*kol 8 c++ gcc namespaces operator-overloading

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

namespace my_namespace {
 class my_type
 {
  friend std::ostream& operator << (std::ostream& out, my_type t);
 }
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试在实现文件中定义这些运算符,但是当我写这样的东西时

std::ostream& my_namespace::operator << (std::ostream& out, my_type t)
{
 out << t;
 return out;
}
Run Code Online (Sandbox Code Playgroud)

我收到错误消息

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

当我改为

namespace my_namespace {
    std::ostream& operator << (std::ostream& out, my_type t)
    {
     out << t;
     return out;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后它编译,但我不明白这个问题.为什么这不能编译?那一切都是正确的吗?我很感激链接到标准,因为我真的不知道要搜索什么.

添加

file.h

#ifndef A_H
#define A_H

#include <iosfwd>

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

#endif
Run Code Online (Sandbox Code Playgroud)

file.cpp

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

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

int main() {}
Run Code Online (Sandbox Code Playgroud)

这是完整的例子.这在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);
}
Run Code Online (Sandbox Code Playgroud)

我一直在想,在可见性方面,在课堂上声明朋友操作符与在课堂外声明是一样的.看起来并非如此.谢谢.

非常感谢提前.

Dan*_*ger 10

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

namespace my_namespace {
    std::ostream& operator << (std::ostream& out, my_type t);
}
Run Code Online (Sandbox Code Playgroud)

C++标准非常明确:

7.3.1.2/3:

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

下面的链接把它更简单,并增加了几个例子:http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref /cplr043.htm

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

  • 它已经在命名空间中声明(在头文件中),不是吗? (2认同)
  • 链接已死。 (2认同)