我想知道为什么模板专业化有意义?
下面的东西不是等价的吗?
模板专业化:
template <typename T>
void f(T t) {
something(t);
}
template <>
void f<int>(int t) {
somethingelse(t);
}
非模板函数而不是特化:
void f(int t) {
somethingelse(t);
}
我相信这些是相同的,因为非模板函数将始终是首选。
我想知道为什么模板专业化有意义?
下面的东西不是等价的吗?
模板专业化:
template <typename T>
void f(T t) {
something(t);
}
template <>
void f<int>(int t) {
somethingelse(t);
}
非模板函数而不是特化:
void f(int t) {
somethingelse(t);
}
我相信这些是相同的,因为非模板函数将始终是首选。
这是我想出的答案:
如果模板参数不是正在定义的函数的参数,则不同:
template <typename T>
void f() {
T t;
something(t);
}
template <>
void f<int>() {
int t;
somethingelse(t);
}
在这种情况下定义:
void f() {
int t;
somethingelse(t);
}
会使所有模板版本无法使用。
也许其他人有更好的想法。:)
如果您坚持将其称为f<int>(42)
. 这将找到专业化,但不会找到重载。
如果呼叫总是看起来像f(42)
,则任何一种替代方法都可以。
问题归结为确定何时使用重载不能使用的专业化。在不同的情况下会出现这种情况,尽管它们并不常见,而且很容易犯错误,因此一般建议是更喜欢重载而不是特化。
当调用者明确请求使用模板时。在您提供的代码示例中,如果调用是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 )
, 但是专业不会。
一般来说,对于大多数情况,上述情况都不是真正适用的,因此应该首选重载。
可能还有更多,但那些是我能从脑海中回想起的
函数模板特化已被弃用,取而代之的是函数重载,但有一个例外:您可以将函数模板特化添加到 std 命名空间,但不允许添加新函数。因此,如果您需要为 std 命名空间中的某些内容提供特定版本,则必须使用模板专业化。例如,要支持使用用户定义的类作为键创建 unordered_map,您必须为您的类专门化 std::hash。