Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the anonymous namespace enclose all namespaces?

In C++ you specify internal linkage by wrapping your class and function definitions inside an anonymous namespace. You can also explicitly instantiate templates, but to be standards conforming any explicit instantiations of the templates must occur in the same namespace. AFAICT this should compile, but GCC fails on it:

namespace foo {

template<class T>
class bar {};

}

using namespace foo;

namespace {
template class bar<int>;
}

int main()
{
    return 0;
}

With the error:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace 'foo')

Which is interesting because the anonymous namespace should just be specifying linkage, not really functioning as a namespace, and the global namespace definitely encloses foo, since it encloses every namespace. But even this doesn't work!:

template<class T>
class bar {};

using namespace foo;

namespace {
template class bar<int>;
}

int main()
{
    return 0;
}

Which fails with the same error, just listing the global namespace instead:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace '::')

:/

like image 489
Joseph Garvin Avatar asked Jul 10 '09 21:07

Joseph Garvin


People also ask

What does an anonymous namespace do?

An anonymous namespace makes the enclosed variables, functions, classes, etc. available only inside that file. In your example it's a way to avoid global variables.

Can you use multiple namespaces C++?

Namespace is a feature added in C++ and is not present in C. A namespace is a declarative region that provides a scope to the identifiers (names of functions, variables or other user-defined data types) inside it. Multiple namespace blocks with the same name are allowed.

Can two namespaces have same name?

Inside a namespace, no two classes can have the same name.

How many namespaces are there in C++?

There are three main namespaces. The ISO C++ standards specify that "all library entities are defined within namespace std." This includes namespaces nested within namespace std , such as namespace std::chrono . Specified by the C++ ABI.


2 Answers

An anonymous namespace is logically equivalent to

namespace _TU_specific_unique_generated_name
{
    // ...
}
using namespace _TU_specific_unique_generated_name;

A namespace, anonymous or otherwise, has no effect on the linkage of its members. In particular members of an anonymous namespace do not magically get internal linkage.

like image 86
CB Bailey Avatar answered Sep 19 '22 14:09

CB Bailey


First: You are explicitly instantiating a class template, you are not defining a new class template. What

template class bar<int>;

says is "please instantiate the class template bar for type int here". You cannot do that in another namespace, just as you cannot partially specialise a class template in another namespace. In particular, the template to be explicitly instantiated must have been defined, and in your example, there's no (anonymous namespace)::bar<>, only foo::bar<>.

Second: The anonymous namespace is a real namespace (it's distinct in every translation unit, though). It also doesn't magically change linkage. Everything declared inside namespace {} has still the default linkage, just like at any other namespace scope. IIRC, it was even added to allow for translation unit-private, yet external-linkage objects.

like image 20
Marc Mutz - mmutz Avatar answered Sep 20 '22 14:09

Marc Mutz - mmutz