0

A在类层次结构中使用了一个模板类,B::C_#其专门方法create()A

template <typename T>
class A
  : public std::map<std::string, double (T::*)() const>
{
  ...

  void create();

  ...
};

template <typename T>
void A<T>::create()
{ assert(false); }

这些子类之一C_#(比方说C_0)直到最近都很棒。一切都很顺利,直到C_0决定成为一个模板。create()除了这个专业,他什么都做。它试图通过create()以下方式专门化:

template<class N1, class N2>
class C_0: public B<N1, N2>
{
  ...
}

...

template<class N1, class N2>
some_namespace::A< some_namespace::C_0<N1, N2> >
  some_namespace::C_0<N1, N2>::A_;

template <>
void some_namespace::A< C_0<N1, N2> >::create() // line 1151
{
  blah_(&C_0<N1, N2>::get_stuff);
}

C_0迄今为止的尝试都失败了:

C_0.h:1151:45: error: 'N1' was not declared in this scope
C_0.h:1151:49: error: 'N2' was not declared in this scope
C_0.h:1151:51: error: template argument 1 is invalid
C_0.h:1151:51: error: template argument 2 is invalid
C_0.h:1151:53: error: template argument 1 is invalid
C_0.h:1151:63: error: 'create' is not a template function

请帮助可怜的生物克服他的麻烦。

还尝试在 special 中进行模板方法专业化C_0

namespace some_namespace
{
  class C_0_specialized: public C_0<double_t, size_t>
  {};

  template <>
  void A<C_0_specialized>::create()
  {
    blah_(&C_0_specialized::get_stuff);
  }
}

这次它编译了,但是调用了原来的方法,也就是void A<T>::create() { assert(false); }

解决方案

好的,所以我最终AC_0模板级别使用C_0参数列表对整个模板类进行了部分专业化:

template<class N1, class N2>
class A< C_0<N1, N2> >
{

  ...

  void create()
  {
    blah_(&C_0<N1, N2>::get_stuff);
  }

  ...

}

原因是:1)模板方法的部分特化是不允许的,所以不能只特化void create(),当类被部分特化时,所有的方法和变量都必须在特化中重新定义;2) 模板方法的显式特化void create()在级别内是不可能的,C_0因为A依赖于C_0模板参数列表;3) 将特化移动void create()C_0_specialized,因为在C_0_specialized模板参数列表被解析,它可以被显式特化,这是不可能的,因为(在上面的代码中A实例化)的实例在模板中使用,因此不会看到at 的特化A_C_0A_AC_0等级。这就是为什么在那个级别它调用void create(). 由于开销太大,也无法移动A_到 的级别。C_0_specialized

好在班级A不大,但还是最好只专攻void create()

我发现这个资源对于解释模板的显式和部分专业化之间的差异非常有用。

4

1 回答 1

2

首先,你忘了告诉编译器N1andN2是类型

template<class N1, class N2>
void some_namespace::A< C_0<N1, N2> >::create() // line 1151
{
  blah_(&C_0<N1, N2>::get_stuff);
}

这仍然不起作用,因为没有A<C_0<N1,N2>>定义类。先声明一下。 注意:您确实定义A<T>了,但这是一般情况,而不是您不想为其定义成员的专业化。

顺便说一句,以下三行绝对没有任何意义。

template<class N1, class N2>
some_namespace::A< some_namespace::C_0<N1, N2> >
  some_namespace::C_0<N1, N2>::A_;
于 2013-10-16T17:25:54.223 回答