Joseph Garvin
Joseph Garvin

Reputation: 21984

Why can't I explicitly instantiate a class template in an unnamed namespace if it was declared in another namespace?

In C++ you specify internal linkage by wrapping your class and function definitions inside an unnamed 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 unnamed 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 '::')

:/

Upvotes: 7

Views: 4066

Answers (4)

Marc Mutz - mmutz
Marc Mutz - mmutz

Reputation: 25343

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.

Upvotes: 7

CB Bailey
CB Bailey

Reputation: 793139

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.

Upvotes: 10

John Weldon
John Weldon

Reputation: 40799

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...

Upvotes: 0

Drew Hoskins
Drew Hoskins

Reputation: 4186

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.

Upvotes: 6

Related Questions