我想定义一些模板特化的静态成员,如下所示:
namespace A {
template <> int C<A1::A2::...::MyClass1>::member1_ = 5;
template <> int C<A1::A2::...::MyClass1>::member2_ = 5;
template <> int C<A1::A2::...::MyClass1>::member3_ = 5;
template <> int C<B1::B2::...::MyClass2>::member1_ = 6;
template <> int C<B1::B2::...::MyClass2>::member2_ = 6;
template <> int C<B1::B2::...::MyClass2>::member3_ = 6;
...
}
但是为了简化代码(并让它看起来更结构化),我想做这样的事情:
namespace A {
{
using T = A1::A2::...::MyClass1;
template <> int C<T>::member1_ = 5;
template <> int C<T>::member2_ = 5;
template <> int C<T>::member3_ = 5;
}
{
using T = B1::B2::...::MyClass2;
template <> int C<T>::member1_ = 6;
template <> int C<T>::member2_ = 6;
template <> int C<T>::member3_ = 6;
}
...
}
编译器发出错误:expected unqualified-id
。有没有办法限制&{34;外部&#34;范围内的using
范围?空间?
答案 0 :(得分:5)
您不能在代码块(即{...}
)之外嵌套函数。
让我们说我们有这个共同点:
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_;
};
}
您可以import the names into namespace A
,通过资格A::
提供这些资讯:
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;
}
但我认为这是不受欢迎的,你认为这是污染。那么你唯一能做的就是use an extra namespace减少::
的数量:
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;
}
这可以使您的namespace A
清除不需要的类型名称,尽管它引入了一个&#34;实现命名空间&#34; T
(这是命名空间的可怕名称!!!)。
第三种选择specializes 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;
};
}
请注意,这需要static const
个数据成员。您也可以取消struct
模板的声明,如下所示:
namespace A {
template<typename T>
struct C;
}
将其使用(在编译时)仅限于您想要的类型。这是我的首选解决方案。
答案 1 :(得分:3)
这是一个难以解决的问题。有几个限制。
{ }
。 namespace detail1 { }
内的本地namespace detail2 { }
和namespace A
。虽然g ++错误地接受了这个解决方案,但是Clang正确地拒绝了这个(注意:这是我今天早些时候被卡住的地方并暂时删除了这个答案)。using
指令和声明会污染包含此标题的所有客户端的命名空间inline
命名空间中的namespace A
为inline
仅在A
和{B
包围时才有效{1}}命名空间序列,这是不可能的。最干净的方法是将namespace aliases libA
和libB
用于冗长的A1::A2::...::AN
和B1::B2::...::BN
嵌套命名空间序列,并从中导出这些别名他们的标题。这简化了客户端代码和实际模板特化。
#include <iostream>
// file C.h
namespace A {
template<class T>
struct C
{
static int member1_, member2_, member3_;
};
} // namespace A
// file A.h
namespace A1 { namespace A2 {
struct MyClass1 {};
}} // namespace A1, A2
// export namespace alias to hide implementation details
namespace libA = A1::A2;
namespace A {
template <> int C<libA::MyClass1>::member1_ = 5;
template <> int C<libA::MyClass1>::member2_ = 5;
template <> int C<libA::MyClass1>::member3_ = 5;
} // namespace A
// file B.h
namespace B1 { namespace B2 {
struct MyClass2 {};
}} // namespace B1, B2
// export namespace alias to hide implementation details
namespace libB = B1::B2;
namespace A {
template <> int C<libB::MyClass2>::member1_ = 6;
template <> int C<libB::MyClass2>::member2_ = 6;
template <> int C<libB::MyClass2>::member3_ = 6;
} // namespace A
// file main.cpp
int main()
{
std::cout << A::C<libA::MyClass1>::member1_ << "\n";
std::cout << A::C<libA::MyClass1>::member2_ << "\n";
std::cout << A::C<libA::MyClass1>::member3_ << "\n";
std::cout << A::C<libB::MyClass2>::member1_ << "\n";
std::cout << A::C<libB::MyClass2>::member2_ << "\n";
std::cout << A::C<libB::MyClass2>::member3_ << "\n";
}
请注意,在重复MyClass1
和MyClass2
时,仍然存在温和的锅炉板块,但代码更加紧凑,并且命名空间别名已经存在。