c++namespacesgloballinkageunnamed-namespace

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

:/


Solution

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