4

我想知道为什么模板专业化有意义?

下面的东西不是等价的吗?

模板专业化:

template <typename T>
void f(T t) {
  something(t);
}

template <>
void f<int>(int t) {
  somethingelse(t);
}

非模板函数而不是特化:

void f(int t) {
  somethingelse(t);
}

我相信这些是相同的,因为非模板函数将始终是首选。

4

4 回答 4

4

这是我想出的答案:

如果模板参数不是正在定义的函数的参数,则不同:

template <typename T>
void f() {
  T t;
  something(t);
}

template <>
void f<int>() {
  int t;
  somethingelse(t);
}

在这种情况下定义:

void f() {
  int t;
  somethingelse(t);
}

会使所有模板版本无法使用。

也许其他人有更好的想法。:)

于 2012-08-01T11:22:59.543 回答
3

如果您坚持将其称为f<int>(42). 这将找到专业化,但不会找到重载。

如果呼叫总是看起来像f(42),则任何一种替代方法都可以。

于 2012-08-01T12:17:24.407 回答
3

问题归结为确定何时使用重载不能使用的专业化。在不同的情况下会出现这种情况,尽管它们并不常见,而且很容易犯错误,因此一般建议是更喜欢重载而不是特化。

  • 当调用者明确请求使用模板时。在您提供的代码示例中,如果调用是f<int>(42)or even f<42>(),则不会使用重载。

  • 当您无法提供所需的重载,或无法在呼叫地点解决重载时。例如,如果类型不是函数参数之一(它根本不存在于签名中或仅存在于返回类型中:

    模板 T f();

在这种情况下,您不能提供重载int f();double f();但您可以根据需要提供尽可能多的模板特化,并且由用户来强制选择其中一个。请注意,这可以被认为是前一种情况的子情况:因为模板参数不参与函数参数,用户需要提供模板参数,所以调用是显式的模板。

  • 当您想对参数组合设置特殊约束并禁止隐式转换时:

    模板无效 f( T, T ); // 两个参数必须是相同的类型

因为模板参数推导只执行完美匹配,所以这个模板只能在两个参数的类型完全相同时使用,如果你添加一个重载void f(int,int),那么重载可以与任何可隐式转换为 int 的类型组合一起使用,比如f( 5, 3.0 ), 但是专业不会。

一般来说,对于大多数情况,上述情况都不是真正适用的,因此应该首选重载。


可能还有更多,但那些是我能从脑海中回想起的

于 2012-08-01T12:47:38.690 回答
0

函数模板特化已被弃用,取而代之的是函数重载,但有一个例外:您可以将函数模板特化添加到 std 命名空间,但不允许添加新函数。因此,如果您需要为 std 命名空间中的某些内容提供特定版本,则必须使用模板专业化。例如,要支持使用用户定义的类作为键创建 unordered_map,您必须为您的类专门化 std::hash。

于 2012-08-13T16:49:58.613 回答