为什么要使用模板专业化?

时间:2012-08-01 11:23:00

标签: c++ templates template-function

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

以下事项是否相同?

模板专业化:

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

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

非模板功能而非专业化:

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

我相信这些是相同的,因为非模板功能永远是首选。

4 个答案:

答案 0 :(得分:4)

这是我提出的答案:

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

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

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

在这种情况下定义:

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

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

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

答案 1 :(得分:3)

如果你坚持像f<int>(42)一样调用它,那么你声明函数的方式就很重要了。这将找到专业化,但不会过载。

如果通话看起来总是f(42),则其他选项都可以使用。

答案 2 :(得分:3)

问题归结为确定何时将使用超载无法实现的专业化。在不同的情况下,虽然这种情况并不常见,但是很容易犯错误,一般建议更倾向于过载到专业化。

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

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

    模板 T f();

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

  • 如果要对参数组合设置特殊约束并禁止隐式转换:

    模板 void f(T,T); //两个参数必须属于同一类型

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

一般情况下,对于大多数情况,上述情况都不适用,因此应首选过载。


可能会有更多,但这些是我可以回想起的那些

答案 3 :(得分:0)

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