将模板嵌套类的方法定义移到声明之外

Move method definition for template nested class outside declaration

本文关键字:声明 定义 方法 嵌套      更新时间:2023-10-16

是否可以将方法定义移到声明之外?

template <typename T1>
class A
{
  template <bool T2>
  class B;
  template<>
  class B<true>
  {
    void f() { /* Do smg */ }
  }
  class B<false>
  {
    void f() { /* Do smg else */ }
  }
}

如果我尝试在类声明之外定义f(),像这样

template <typename T1>
template <>
void A<T1>::B<true>::f() { /* Do smg */ }

编译器给出错误C3855:模板形参T2与声明不兼容

不能显式特化非特化类模板的类成员模板,from [temp.exp .spec]:

在类模板成员或出现的成员模板的显式特化声明中在名称空间范围内,成员模板和它的一些封闭类模板可以保留如果类成员模板是封闭的,则声明不能显式地对其进行特化类模板也没有显式特化

即使A定义内的B的显式特化也是病态的。如果你需要做这样的事情,我不会使用B的成员类模板。

我找到了破解系统的方法。使用部分专门化代替显式专门化,使用假模板参数,如下所示:http://goo.gl/yHRQwV

template <typename T1>
class A
{
public:  
  template <bool T2, typename = void>
  class B;
  template <typename Dummy>
  class B<true, Dummy>
  {
    public:
    void f1();
  };
  template <typename Dummy>
  class B<false, Dummy>
  {
    public:
    void f1();
  };
};
template <typename T1>
template <typename Dummy>
void A<T1>::B<true, Dummy>::f1()
{  
}
template <typename T1>
template <typename Dummy>
void A<T1>::B<false, Dummy>::f1()
{  
}
int main()
{
    A<int>::B<true> b1;
    b1.f1();
    A<int>::B<false> b2;
    b2.f1();
}

不确定这是否合法,但它可以工作。

事实上,这并不能解决我的问题。在这种情况下,我不能添加一般方法f2(), f3()等,类B没有专门化:http://goo.gl/wtIY0e

template <typename T1>
class A
{
public:  
  template <bool T2, typename = void>
  class B  
  {
    public:
    void f2();
    void f3();
  };
  template <typename Dummy>
  class B<true, Dummy>
  {
    public:
    void f1();
  };
  template <typename Dummy>
  class B<false, Dummy>
  {
    public:
    void f1();
  };
};
template <typename T1>
template <typename Dummy>
void A<T1>::B<true, Dummy>::f1()
{  
}
template <typename T1>
template <typename Dummy>
void A<T1>::B<false, Dummy>::f1()
{  
}
template <typename T1>
template <bool T2, typename Dummy>
void A<T1>::B<T2, Dummy>::f2()
{
}
template <typename T1>
template <bool T2, typename Dummy>
void A<T1>::B<T2, Dummy>::f3()
{
}
int main()
{
    A<int>::B<true> b1;
    b1.f1();
    b1.f2(); // error: A<int>::B<true> has no member f2
    b1.f3(); // error: A<int>::B<true> has no member f3
    A<int>::B<false> b2;
    b2.f1();
    b2.f2(); // error: A<int>::B<false> has no member f2
    b2.f3(); // error: A<int>::B<false> has no member f3
}

最后,我找到了一个一整天都在寻找的解决方案:静态多态性 http://goo.gl/7yGZxM

template <typename T1>
struct A
{
  template<typename T2>
  struct BaseB
  {
    void f1();
    void f2();
    void f3();
  };
  struct B_true : BaseB<B_true>
  {
    void f1_impl();
  };
  struct B_false : BaseB<B_false>
  {
    void f1_impl();
  };
};
template <typename T1>
template<typename T2>
void A<T1>::BaseB<T2>::f1()
{
  static_cast<T2*>(this)->f1_impl();
}
template <typename T1>
template<typename T2>
void A<T1>::BaseB<T2>::f2()
{
}
template <typename T1>
template<typename T2>
void A<T1>::BaseB<T2>::f3()
{
}
template <typename T1>
void A<T1>::B_true::f1_impl()
{
}
template <typename T1>
void A<T1>::B_false::f1_impl()
{
}
int main()
{
  A<char>::B_true b_true;
  b_true.f1();
  b_true.f2();
  b_true.f3();
  A<char>::B_false b_false;
  b_false.f1();
  b_false.f2();
  b_false.f3();
}