C++ 为什么要使用模板专门化?
我想知道为什么模板专门化有意义 下面的事情不是等价的吗 模板专门化:C++ 为什么要使用模板专门化?,c++,templates,template-function,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); } 我相信这些都是一样的,因为非模板功能将永远是首选。这是我得出的答案: 如果模板参数不是所定义函
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);
}
将使所有模板版本无法使用
也许其他人有更好的想法。:) 如果您坚持像
f(42)
那样调用函数,那么声明函数的方式确实很重要。这将找到专门化,而不是重载
如果调用看起来总是像
f(42)
,则两种方法都可以使用。问题归结为确定何时使用重载无法使用的专门化。在不同的情况下会出现这种情况,尽管它们非常罕见,而且很容易犯错误,一般的建议是更喜欢重载而不是专门化
- 当调用方显式请求使用模板时。在您提供的代码示例中,如果调用是
或甚至是f(42)
,则不会使用重载f()
- 当您无法提供所需的重载,或者无法在调用位置解决重载时。例如,如果类型不是函数参数之一(它要么根本不存在于签名中,要么仅存在于返回类型中): 模板 tf()
intf();
和double f();
但是您可以根据需要提供尽可能多的模板专门化,用户可以强制选择其中一个。请注意,这可能被视为前一种情况的子类:因为模板参数不参与函数参数,所以用户需要提供模板参数,所以调用是显式地添加到模板的
- 如果要对参数组合设置特殊约束并禁止隐式转换,请执行以下操作: 模板 void f(T,T);//两个参数必须是相同的类型
void f(int,int)
,则该重载可用于隐式转换为int的任何类型组合,如f(5,3.0)
,但专业化不会
一般来说,在大多数情况下,上述情况都不适用,因此应首选重载
可能还有更多,但这些都是我可以从头回忆起的功能模板专门化被弃用于支持函数重载,但有一个例外:您可以向std命名空间添加函数模板专门化,但不允许添加新函数。因此,如果您需要提供特定的版本对于std命名空间中的某些内容,您必须使用模板专门化。例如,要支持创建以用户定义的类作为键的无序映射,您必须专门化类的std::hash。您专门讨论的是函数模板专门化。这些被认为是不推荐的和糟糕的样式。专门化类模板的内联很有意义。哦,这很有趣。你能提供一个链接吗?快速搜索没有找到任何结果。@interjay你是想告诉我该内联专门化吗?你要求提供一个关于为什么不应该使用函数模板专门化的链接,所以我提供了一个。我和链接页面都没有说任何内容关于需要内联的函数。这基本上也是我的推理。如果你在模板中使用函数,并且需要得到正确的函数,你将调用它
f()
。这不会发现重载。f()编码方式基本上与其他方法相同。如果您喜欢尖括号,则会对您产生影响。由于函数模板无法使用部分专门化,我也认为应该使用重载,而不是显式专门化。我们最近讨论了这个主题,请参阅对该问题答案的评论:@Gorpik:我刚刚阅读了它们(粗略阅读评论),你想提出什么?部分讨论涉及到使用专业化作为为调用者提供更干净界面的一种方式是否有效。这与你提出的理由类似。并非所有人都同意:有些人非常坚决地不使用函数模板专业化。
void f() {
int t;
somethingelse(t);
}