5

我很惊讶地发现以下编译:

#include <iostream>

using namespace std;

template<typename T>
class SomeCls {
public:
  void UseT(T t) {
    cout << "UseT" << endl;
  }
};

template<>
class SomeCls<int> {
  // No UseT? WTF?!??!?!
};

int main(int argc, char * argv[]) {
  SomeCls<double> d;
  SomeCls<int> i;

  d.UseT(3.14);
  // Uncommenting the next line makes this program uncompilable.
  // i.UseT(100);

  return 0;
}

为什么允许这样做?class SomeCls<int>不需要方法似乎是错误的void UseT(T t)。我确定我在这里错过了专业化的重点(我不是 C++ 专家)。有人可以启发我吗?

4

4 回答 4

11

因为SomeCls<double>是完全不同的类型SomeCls<int>或任何其他类型SomeCls<T>。他们没有任何关系,所以他们可以拥有任何他们想要的成员。只要确保不要调用i.UseT(),这当然是编译器开始抱怨的地方。

于 2011-06-14T07:07:27.150 回答
7

专业化可以以您认为合适的任何方式进行专业化。如果您想省略所有方法,添加或删除基类,添加或删除数据成员,那很好。

template <class T>
class Foo {};

template <>
class Foo<int> { void extrafunc(); }; //fine

template <>
class Foo<bool> : public ExtraBase {}; // fine

template <>
class Foo<double> { int extradata; }; // fine

当特化函数时,唯一的限制是参数保持不变(相对于主模板),尽管您可以重载到您的心脏内容。

template <class T>
void foo(const T&);

template <>
void foo<int>(int); // not fine, must be const int&

void foo(int); // fine, this is an overload, not a specialisation

template <class T>
void foo(T*); // fine, again this is an overload, not a specialisation
于 2011-06-14T07:02:44.740 回答
0

我已将答案标记为“正确”,但我并不十分满意。我不是在问它是如何工作的。我在问为什么它是这样设计的。它的工作方式并没有让我觉得与 OO 一致。它甚至看起来是一致的。为什么函数模板特化有接口必须一致的限制,而类模板特化没有?

如果这是你的问题,你可能应该一开始就这么说。

我将从最后一点开始:为什么函数需要相同的签名。很简单,函数已经有办法通过重载重用名称。

int f(int);
double f(double); //no templates needed

允许专门化更改函数的签名将不必要地使已经很困难的名称解析过程复杂化,而实际上并没有提供任何额外的功能。

对于类类型,模板要复杂得多。您不仅要考虑成员函数,还有成员对象、typedef、嵌套类型等等。专业化专门化所有这些。如果SomeTemplatedObject<double>需要一个通常不需要的特定私人成员,SomeTemplatedObject<T>你怎么能SomeTemplatedObjectdouble不改变“接口”的情况下专攻呢?或者对于某些类型没有意义的方法是什么?还是需要修改嵌套类型以保持接口一致?这甚至没有涉及到更大的模板元编程问题。

对于一般情况,您甚至不需要完整的类型。

template<typename T>
struct Object;

template<>
struct Object<int> { //what interface does this need?
  typedef int type;
};

如果您觉得有必要坚持一些纯粹的 OO 定义,那么您总是可以自由地在不精确匹配原始布局的情况下不专门化模板。

于 2011-06-15T10:43:33.537 回答
0

您的代码从不调用intUseT 的版本,因此您不需要提供它。

于 2011-06-14T07:03:47.110 回答