Why can't we specialize a template class inside another namespace?

Hi,

I know the question seems silly - it's actually what I would expect. Yet, I would appreciate to know the exact reason just so my understanding of namespaces becomes richer.

This has to do with the MPL library from Boost (1.63.x).

The code simplified is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <boost/mpl/at.hpp>
// .... other includes ...
namespace mpl = boost::mpl;
struct tiny_tag {};

	namespace Foo
	{
	        template<>
		struct mpl::at_impl<tiny_tag>				
		{
			template<typename Tiny, typename N>
			struct apply : tiny_at<Tiny, N::value>
			{};
		};
        }


When compiling in VStudio 2015 update 3 I get:


error C2888: 'boost::mpl::at_impl<tiny_tag>': symbol cannot be defined within namespace 'Foo'


I appreciate any feedback!

Regards,
Juan Dent
This was actually changed in C++17 as a defect report (so it will apply to previous revisions), the new rule is, as quoted in http://en.cppreference.com/w/cpp/language/template_specialization#In_detail

"specialization may be declared in any scope where its primary template may be defined"

If you declare a primary template in a namespace, you can provide a definition (and, therefore, a specialization) in any enclosing namespace:

1
2
3
4
5
namespace N {
    template<class T> class X; // primary template declaratoin
}
template<class T> class N::X {}; // primary template definition
template<> class N::X<double> {}; // full specialization (works in every clang, but in gcc only as of 7.0 trunk) 



As for why you can't put an out-of-namespace definition (of anything, not just templates) in an unrelated namespace, and are required to use an enclosing namespace.. perhaps there's a proposal that explained it.
Last edited on
Okay Cubbi. However if I modify your example by moving the full specialization inside another unrelated namespace, say Foo, is this then Not an error in C++17?

E.G.

1
2
3
4
5
6
7
namespace N {
    template<class T> class X; // primary template declaratoin
}
namespace Foo {
    template<class T> class N::X {}; // primary template definition
    template<> class N::X<double> {}; // full specialization 
}


Is this then okay as per C++17?

Regards,
Juan Dent
Is this then okay as per C++17?

no, it has to be an enclosing namespace.
The rule for specializations (which used to be 'same namespace')) becomes exact same as the rule for definitions ('enclosing namespace').
Got it! Thanks!!
Topic archived. No new replies allowed.