Reputation: 6012
In production code I found this in a .cpp file:
namespace
{
void foo(); // declared in anonymous namespace, defined below
}
void bar() // declared in corresponding .h file, defined here
{
::foo(); // call foo
}
void ::foo() // intended to refer to the anonymous foo above
{
}
We are using Visual Studio 2017. I stumbled over this because intellisense gave me a warning for foo
that it could not find the function definition.
However, it compiles and links without errors and the code does what it is supposed to do.
I godbolted it and found that gcc and clang reject this code for the same reason that intellisense gave me a warning for.
So my question is: Which compiler is correct and why?
Furthermore, out of interest I added another declaration of foo
to the global namespace, like so:
namespace
{
void foo();
}
void foo(); // another declaration
void bar()
{
::foo(); // which foo will be called?
}
void ::foo() // which foo will be defined?
{
}
Now, gcc gives me an error:
error: explicit qualification in declaration of 'void foo()'
Clang compiles it, but gives me a warning:
warning: extra qualification on member 'foo' [-Wextra-qualification]
And msvc compiles it just fine.
Again, which compiler - if any - is correct here?
Upvotes: 5
Views: 630
Reputation: 62113
Have a look at the cppreference page on unnamed namespaces:
This definition is treated as a definition of a namespace with unique name and a using-directive in the current scope that nominates this unnamed namespace.
So an "anonymous" namespace is not the global namespace, nor is it even unnamed. Rather, it has a compiler-provided unique name. So ::foo()
is not the function in your anonymous namespace. MSVC is incorrect here.
And you can't define your anonymous namespace function outside its anonymous namespace.
Upvotes: 6