不同编译器的不同输出

时间:2012-12-18 17:08:51

标签: 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();
   };

   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

谁是对的?为什么会这样呢?

1 个答案:

答案 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上测试过。