【问题标题】:Move method definition for template nested class outside declaration将模板嵌套类的方法定义移到声明之外
【发布时间】:2015-09-30 10:45:35
【问题描述】:

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

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与声明不兼容。

【问题讨论】:

  • 在 gcc 4.7.2 上,由于error: explicit specialization in non-namespace scope ‘class A&lt;T1&gt;’,我无法编译您的顶级块。它应该是一个有效的例子吗?我从这个问题中理解...
  • VS2013 编译顶块没有错误。
  • 不是 VS 方面的专家,但众所周知,它是一个不太合规的编译器。我的猜测是这两个块在技术上都是非法的。 g++ 的错误对我来说很有意义。在任何情况下,我都会在您的问题中添加一个 VS 标签。

标签: c++ visual-studio templates nested


【解决方案1】:

我找到了破解系统的方法。使用部分特化而不是显式特化,使用伪模板参数,例如: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();
}

【讨论】:

    【解决方案2】:

    您不能显式特化非特化类模板的类成员模板,来自 [temp.expl.spec]:

    在类模板或成员模板的成员的显式特化声明中出现 在命名空间范围内,成员模板和它的一些封闭类模板可能会保留 非特化,除非声明 不应明确特化类成员模板,如果它包含 类模板也没有明确专门化

    即使在 A 的定义中明确的特化 B 也是不正确的。如果你需要做这样的事情,我根本不会使用B的成员类模板。

    【讨论】:

      猜你喜欢
      • 2021-11-21
      • 2019-03-23
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多