我对下面的模板行为感到困惑,它使用空尖括号(没有参数的模板)编译得很好,因为语法上,模板<>保留用于标记显式模板特化。
template <typename T> void add(T a, T b) { }
int main() {
add<>(10, 3); // compiles fine since both parameters are of same data type
add<>(10, 3.2); // Error: no matching function for call to add(int, double)
}
在上面的例子中,模板参数真的是可选的吗?
答案 0 :(得分:11)
template<>
保留用于标记显式模板特化。
根据具体情况,这意味着各种各样的事情。这意味着“使用默认或推断的参数”,就像您只是简单地说add
。
在第一种情况下,两个函数参数具有相同的类型,因此模板参数可以推导为int
。
在第二种情况下,它们具有不同的类型,因此无法推导出模板参数。你必须指定你想要的东西,例如add<double>
,转换一个函数参数以匹配另一个函数参数,或修改模板以分别对每个类型进行参数化。
在上面的例子中,模板参数真的是可选的吗?
是的,如果可以从参数类型中推断出来。
答案 1 :(得分:6)
在第一种情况下,是因为可以通过标准规则推断出来。在第二个,没有因为他们不能 - 你必须写下这样的东西:
add<float>(10, 3.2);
答案 2 :(得分:3)
您有一个模板参数和两个不同类型的函数参数。模板参数推导需要匹配两个参数,但如果提供int和double,则它不起作用。原因是推断的参数必须完全匹配,并且不考虑类型转换。
语法
add<double>(10, 3.2);
会明确强制T
等于double
。在这种情况下,int
常量10
将转换为double
。
您还可以添加另一个重载
template <typename T, typename U> void add(T a, U b) { }
并且可能通过要求is_convertible<T, U>