为什么以下代码在不同的编译器上打印出不同的结果?
#include <iostream>
void foo() { std::cout << "::foo() \n"; }
namespace Foo
{
struct Bar
{
friend void foo() { std::cout << "Bar::foo() \n"; }
void bar() { foo(); }
void baz();
};
void Bar::baz() { foo(); }
}
int main()
{
Foo::Bar instance;
instance.bar();
instance.baz();
}
输出
gcc 4.7.2
::foo() ::foo()
MSVC-10.0
Bar::foo() Bar::foo()
MSVC-11.0
error C3861: 'foo': identifier not found error C3861: 'foo': identifier not found
谁是对的?为什么会这样呢?
答案 0 :(得分:2)
我认为gcc是对的:
7.3.1.2/3 in C ++ 11:
如果非朋友声明 本地类首先声明一个类或函数的朋友类或 function是最内层封闭命名空间的成员。的名字 通过不合格的查找(3.4.1)或通过资格查找找不到朋友 查找(3.4.3)直到在其中提供匹配的声明 命名空间范围(在课程定义之前或之后
C ++ 03在同一个地方有类似的语言。
我不确定为什么MSVC-11无法找到::foo
,但我认为您 可以阅读此文字以表示名称foo
可以&# 39;不要抬头看。我认为预期的意思是找不到最里面的封闭命名空间中的名称,但外部范围中相同拼写的名称可以。但是,如果微软想要论证其预期的含义,那么我并不是他们与之争辩的人。
MSVC-10是错误的,因为它找到了标准没有找到的名称。因此,对MSVC-11行为的解释可能就像&#34;它被报告为10中的一个错误,他们试图修复它并且走得太远&#34;。
无论如何,修复是在名称空间foo
中引入Foo
声明:
namespace Foo
{
void foo(); // this is a matching declaration
struct Bar
{
friend void foo() { std::cout << "Bar::foo() \n"; }
void bar() { foo(); }
void baz();
};
void Bar::baz() { foo(); }
}
这使得gcc找到了朋友的功能。我没有在任何版本的MSVC上测试过。