Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a function be defined in global namespace if it is declared in an anonymous namespace?

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?

like image 852
sebrockm Avatar asked Jun 14 '19 15:06

sebrockm


People also ask

What is the point of an unnamed namespace?

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.

Which is reserved in the global namespace?

Identifiers starting with an underscore which is not followed by an underscore or uppercase letter are reserved in the global namespace.

What is global namespace in C++?

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.

What are is difference between using namespace directive and using the using declaration for accessing namespace members?

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.


Video Answer


1 Answers

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.

like image 127
Fred Larson Avatar answered Sep 25 '22 07:09

Fred Larson