如何在C++中限制函数之外的`using`语句的范围?

aby*_*s.7 6 c++ templates namespaces template-specialization c++11

我想定义一些模板特化的静态成员,如下所示:

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;

...

}
Run Code Online (Sandbox Code Playgroud)

但是为了简化代码(并使其看起来更结构化),我想做这样的事情:

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;
}

...

}
Run Code Online (Sandbox Code Playgroud)

编译器给出错误:expected unqualified-id.有没有办法限制using"外部"空间的范围?

rub*_*nvb 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_;
};
}
Run Code Online (Sandbox Code Playgroud)

您可以将名称导入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;
}
Run Code Online (Sandbox Code Playgroud)

但我认为这是不需要的,你认为这是污染.那么你唯一能做的就是使用额外的命名空间来减少数量:::

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;
}
Run Code Online (Sandbox Code Playgroud)

这可以让你namespace A清除不需要的类型名称,虽然它引入了一个"实现名称空间" T(这是名称空间的可怕名称!!!).

第三种替代方法专门为您想要的类型struct模板C:

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;
};
}
Run Code Online (Sandbox Code Playgroud)

请注意,这需要static const数据成员.您也可以取消struct模板的声明,如下所示:

namespace A {
template<typename T>
struct C;
}
Run Code Online (Sandbox Code Playgroud)

限制其使用(在编译时)仅限于您想要的类型.这是我的首选解决方案.