C++ 不同编译器上的不同输出
为什么下面的代码在不同的编译器上打印不同的结果C++ 不同编译器上的不同输出,c++,C++,为什么下面的代码在不同的编译器上打印不同的结果 #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(); };
#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();
}
MSVC-10.0
MSVC-11.0
谁是对的?为什么会这样?我认为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年被报告为一个bug,他们试图修复它,但做得太过分了”
无论如何,修复方法是在命名空间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(); }
}
名称空间Foo
{
void foo();//这是一个匹配的声明
结构条
{
福友友(){std::cout Btw,你打印了Bar::foo
,但是这里定义的函数是foo::foo
。它是命名空间foo
中的一个免费函数,不是Bar
的成员@Steve Jessop哦,是的,谢谢。但这不是我的问题。所以,在这种情况下,我怎么能调用friend函数?@Nikita:放一个匹配的d类定义之前的命名空间范围中的eclaration。还要注意,ADL可以找到AFAIK这样的友元函数(也就是说,如果它有任何相关参数,它可以找到),这就是为什么不需要将运算符重载与其定义分开声明为友元的原因。我说“AFAIK”ADL发现了它:这是我引用的位之后的下一句话:-)请,您能发布一个“在类定义之前在命名空间范围中进行匹配声明”的示例吗?您的意思是这样的吗?
Bar::foo()
Bar::foo()
error C3861: 'foo': identifier not found
error C3861: 'foo': identifier not found
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(); }
}