为什么以下代码在不同的编译器上打印不同的结果?
#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
谁是对的?为什么会这样?
我认为gcc是对的:
C++11:中的7.3.1.2/3
如果在-局部类首先声明一个类或函数友元类或函数是最内部封闭命名空间的成员。的名称该好友不是通过未经鉴定的查找(3.4.1)或通过鉴定找到的查找(3.4.3),直到在命名空间范围(在类定义之前或之后
C++03在同一个地方有类似的语言。
我不知道为什么MSVC-11找不到::foo
,但我想您可以阅读此文本,表示根本找不到名称foo
。我认为其本意是在最内部的封闭命名空间中找不到名称,但在外部范围中可以找到拼写相同的名称。但如果微软想争论其意图,我不是他们会争论的人。
MSVC-10是错误的,因为它找到了一个标准明确指出没有找到的名称。因此,对MSVC-11行为的解释可能很简单,就像"它在10年被报告为一个错误,他们试图修复它,但做得太过分了"。
无论如何,修复方法是在名称空间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找到了friend函数。我还没有测试过任何版本的微软风投。