模板类成员函数只能特化

38

我正在阅读《模板完全指南》,它提到:

在谈论类模板特化时:

虽然可以对类模板的单个成员函数进行特化,但一旦这样做了,您将无法再对包含该专门成员的整个类模板实例进行特化。

我在想这是怎么回事,因为你可以没有任何成员函数的特化。 它是否意味着您不能有只带有一个成员函数的特化,然后另一个带有所有成员函数的特化?

有人能请澄清一下吗?

3个回答

42

我认为它指的是以下情况:

template <typename T>
struct base {
   void foo() { std::cout << "generic" << std::endl; }
   void bar() { std::cout << "bar" << std::endl; }
};
template <>
void base<int>::foo() // specialize only one member
{ 
   std::cout << "int" << std::endl; 
}
int main() {
   base<int> i;
   i.foo();         // int
   i.bar();         // bar
}

完成此操作后,您不能将完整的模板专门用于任何其他事物,因此

template <>
struct base<int> {};  // error

1
你可能应该注意,如果你不仅仅专门化成员而是使用你上面的完整模板专门化,那么这个专门化仍然是有效的 - 依赖于 foobar 存在的调用代码不再存在。也就是说,你发布的相同代码,修改为不专门化成员并且不调用 foobar 将工作正常 - 参见 http://ideone.com/3kHa3 。 - rlc
1
所以我猜这个成员专业化创建了一个实例,因此您不能再有另一个专业化了? - Tony The Lion
12
@Tony - 没错,但你当然可以为另一种类型拥有另一个专业化,如 base<float> - Bo Persson

4
我认为指的是您可以选择以下两种方式之一:
  • 对整个类进行特化,所有成员(数据和函数,静态或非静态,虚拟或非虚拟)都必须声明和定义,即使它们与非特化版本相同。

  • 特化某些函数成员,但是这样就不能特化整个类(即所有成员的声明方式与非特化情况相同,您只需为某些函数成员提供实现即可)。


0

显式和隐式实例化,以及下面这种情况可以牢记在心。

当一个类被显式实例化(template class Class_Template<Explicit_Type>;)时,所有泛型类的成员都会出现在实例化的类中。然而,假设通过提及类体来描述一个类特化。只有在专门定义的类中明确定义的成员(无论是已经存在于泛型类中的成员还是新成员),才会出现在实例化的类中。

假设通过特定作用域的类特化来定义泛型类的成员函数,那么将隐式实例化一个专门的类,该类将具有这些函数以及泛型类中的所有其他成员,以适当的特殊方式。

在第二种情况下,由于已经隐式实例化了一个专门的类,我们不能再通过显式实例化或提及类体来定义具有相同特化的类。之后可能需要进行后者的原因是为该特化添加一个特定的成员。在这种情况下是不可能的,因为编译器已经实例化了一个专门的类。

无论以哪种方式实例化类特化,用户始终可以根据其他模板参数实例化其他特化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接