views:

788

answers:

4

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 '::')

:/

+6  A: 

I think you have your answer - anonymous namespaces are distinct, unique namespaces. BTW, the compiler generates some random large integer to represent that namespace internally.

Drew Hoskins
A: 

According to Stroustrup (section 8.2.5.1) the global namespace has access to the anonymous (unnamed) namespace, but it doesn't explicitly say the converse.

I expect you'd have to specify the namespace with a using statement or fully qualify references to other namespaces inside the unnamed namespace...

John Weldon
+6  A: 

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.

+5  A: 

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.

Charles Bailey
I'll add the obvious, which is that the stuff in _TU_specific_unique_generated_name can't be used outside of the file.
Valentein
It's actually described this exact way in the standard, accepted.
Joseph Garvin