考虑以下示例 ( godbolt ):
template <typename T>
struct S {
S(int) {}
};
template <typename T>
void f(S<T>, T) {}
int main() {
f(1, 2);
}
编译出现如下错误:
<source>: In function 'int main()':
10 : <source>:10:11: error: no matching function for call to 'f(int, int)'
f(1, 2);
^
7 : <source>:7:6: note: candidate: template<class T> void f(S<T>, T)
void f(S<T>, T) {}
^
7 : <source>:7:6: note: template argument deduction/substitution failed:
10 : <source>:10:11: note: mismatched types 'S<T>' and 'int'
f(1, 2);
^
制作S
非模板使示例编译。
为什么尽管从 int
进行了隐式转换,但此代码仍无法编译?至 S<T>
?
最佳答案
模板函数不是函数。它们是编写函数的模板。
template <typename T>
void f(S<T>, T) {}
这是一个模板,用于编写给定类型 T
的函数.
现在,C++ 在某些情况下会尝试推导 T
为你。它所做的是对每个参数进行模式匹配(一次)。
如果任何参数找不到匹配项,或者推导的类型不一致或不完整,则推导失败。不尝试转换或部分匹配。如果找到匹配项,它们将作为候选者添加到正在考虑的重载中(这里有一些规则),然后重载解析开始。
在重载决议时间转换被考虑。在模板类型推导中,它不是除了转换为基础。
在你的例子中,S<T>
无法推断类型 T
来自 1
.所以推论根本失败了。在考虑转换的情况下,我们永远不会达到过载解决方案。
碰巧你可以在演绎过程中阻止一个论点被考虑:
template<class T>struct tag_t{using type=T;}:
template<class T>using block_deduction=typename tag_t<T>::type;
template <typename T>
void f(block_deduction<S<T>>, T) {}
现在你的主要编译。
关于c++ - 使用可隐式转换为模板类对象的参数调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46187748/