【问题标题】:Template specialization from a template class来自模板类的模板特化
【发布时间】:2013-10-16 17:22:30
【问题描述】:

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

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&lt;T&gt;::create() { assert(false); }

解决方案

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

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_ 不会在C_0 级别看到A 的特化。这就是为什么在那个级别它调用void create() 的基本版本。由于开销太大,也无法将A_ 移动到C_0_specialized 的级别。

好在A 的类不大,但最好只专注于void create()

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

【问题讨论】:

  • 编译器是对的。您需要传递实际类型而不是N1N2。这是你的选择。
  • @stefan 有没有办法在模板 C_0 中获得正确的语法,而不是将其移至 C_0 的具体实例?

标签: c++ templates


【解决方案1】:

首先,你忘了告诉编译器 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&lt;C_0&lt;N1,N2&gt;&gt;。先声明一下。 注意:您确实定义了A&lt;T&gt;,但这是一般情况,而不是您不想为其定义成员的专业化。

顺便说一句,以下三行完全没有意义。

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

【讨论】:

  • @stefan 为什么?这是指导方针吗? (如果是这样,我在哪里可以找到它?)顺便说一句,最好的 Gruesse nach HD。
  • 是的,我试过了,但是得到了invalid use of incomplete type 'class some_namespace::A&lt;some_namespace::C_0&lt;N1, N2&gt; &gt;'
  • @Walter:它没有解释 为什么 它解决了问题。 (Gruß zurück, wohin auch immer ;-))
  • @Stefan Ich hab ein paar schoene Jahr dort verbracht。巴黎的 Gerade,英国的 aber normalerweise。
  • @Dimon 你从未定义过专门的类模板A&lt;C_0&lt;N1,N2&gt;&gt;。你必须先定义它,然后再定义它的成员。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-10
  • 1970-01-01
  • 2018-11-26
相关资源
最近更新 更多