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?
The unnamed namespace will not have any names; These have different properties. They are directly usable in same program. These are used to declare unique identifiers. In this type of namespace name of the namespace is uniquely generated by compiler itself.
Identifiers starting with an underscore which is not followed by an underscore or uppercase letter are reserved in the global namespace.
Beginning of C++ only. Global scope or global namespace scope is the outermost namespace scope of a program, in which objects, functions, types and templates can be defined. A name has global namespace scope if the identifier's declaration appears outside of all blocks, namespaces, and classes.
using directives Use a using directive in an implementation file (i.e. *. cpp) if you are using several different identifiers in a namespace; if you are just using one or two identifiers, then consider a using declaration to only bring those identifiers into scope and not all the identifiers in the namespace.
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.
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