You cannot embed code blocks (ie {...} ) outside functions.
Let's say we have this common part:
namespace A1 { namespace A2 { class MyClass1; }} namespace B1 { namespace B2 { class MyClass2; }} namespace A { template<typename T> struct C { static int member1_; static int member2_; static int member3_; }; }
You can import names into namespace A , making them accessible through the A:: qualification:
namespace A { using A1::A2::MyClass1; template <> int C<MyClass1>::member1_ = 5; template <> int C<MyClass1>::member2_ = 5; template <> int C<MyClass1>::member3_ = 5; using B1::B2::MyClass2; template <> int C<MyClass2>::member1_ = 6; template <> int C<MyClass2>::member2_ = 6; template <> int C<MyClass2>::member3_ = 6; }
but I suppose this is undesirable, and you see it as pollution. So, the only thing you can do is use an extra namespace to reduce the number of ::
namespace A { namespace T { using T1 = A1::A2::MyClass1; using T2 = B1::B2::MyClass2; } template <> int C<T::T1>::member1_ = 5; template <> int C<T::T1>::member2_ = 5; template <> int C<T::T1>::member3_ = 5; template <> int C<T::T2>::member1_ = 6; template <> int C<T::T2>::member2_ = 6; template <> int C<T::T2>::member3_ = 6; }
This prevents the removal of namespace A from unwanted names, although it is an "implementation namespace" T (which is a terrible name for a namespace !!!).
The third option specializes in struct template C for the types you want :
namespace A{ template<> struct C<A1::A2::MyClass1> { static const int member1_ = 5; static const int member2_ = 5; static const int member3_ = 5; }; template<> struct C<B1::B2::MyClass2> { static const int member1_ = 5; static const int member2_ = 5; static const int member3_ = 5; }; }
Note that this requires static const data members. You can also opt out of declaring a struct template as follows:
namespace A { template<typename T> struct C; }
to limit its use (at compile time) to only the types you want. That would be my preferred solution.