Why does the following code prints different results on different compilers?
#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();
}
Output
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
Who is right? And why is it so?
I think gcc is right:
7.3.1.2/3 in C++11:
If a friend declaration in a non- local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition
C++03 has similar language in the same place.
I'm not sure why MSVC-11 fails to find ::foo, but I suppose you could read this text to mean that the name foo can't be looked up at all. I think the intended meaning is that the name in the innermost enclosing namespace can't be found, but the identically-spelled name in the outer scope can. But if Microsoft wants to argue the intended meaning I'm not the person they'd argue it with.
MSVC-10 is wrong, because it found a name that the standard specifically says is not found. So the explanation for the MSVC-11 behavior might be as simple as "it was reported as a bug in 10, they tried to fix it and went too far".
Anyway, the fix is to introduce a declaration of foo in namespace 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(); }
}
This makes gcc find the friend function. I haven't tested on any version of MSVC.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With