我想知道为什么模板专业化有意义?
以下事项是否相同?
模板专业化:
template <typename T>
void f(T t) {
something(t);
}
template <>
void f<int>(int t) {
somethingelse(t);
}
非模板功能而非专业化:
void f(int t) {
somethingelse(t);
}
我相信这些是相同的,因为非模板功能永远是首选。
答案 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。