模板类的模板特化

时间:2013-10-16 17:22:30

标签: c++ templates

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

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

还尝试在专门的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); }

解决方案

好的,所以我最终在A模板级别内使用C_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的实例(实例化)是不可能的上面代码中的A_已在模板C_0中使用,因此A_无法在A级别看到C_0的专业化。这就是为什么在那个级别它调用void create()的基本版本。由于开销太大,也无法将A_移至C_0_specialized级别。

好的是,A课程并不大,但仍然最好只专注void create()

我发现this resource对于解释模板的显式和部分特化之间的差异非常有用。

1 个答案:

答案 0 :(得分:2)

首先,您忘了告诉编译器N1N2是类型

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