2017-09-13 25 views
2

考虑下面的例子(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非-template使示例编译。

尽管隐式从int转换为S<T>,但为何不编译此代码?

+0

'T'不能在'S '中推导出来。这可能看起来很奇怪,但考虑只有从“int”到“S ”的转换存在的情况,“T”应该是什么? –

+0

或者'S '没有那个构造函数 –

+0

请注意'f (1,2)'[compiles fine](https://ideone.com/DoOa3F)。 – dasblinkenlight

回答

3

模板函数不是函数。它们是写函数的模板。

template <typename T> 
void f(S<T>, T) {} 

这是一个用于编写给定类型为T的函数的模板。

现在,C++在某些情况下会尝试为您推导出T。它在模式匹配每个参数(一次)。

如果任何参数未能找到匹配,或者推导出的类型不一致或不完整,则扣除失败。未尝试转换或部分匹配。如果找到匹配,则将其添加为考虑过载的候选项(此处有一些规则),然后超载分辨率开始执行。

在重载分辨率时考虑时间转换。在模板类型扣除它不是转换为基地以外。

在你的情况下,S<T>不能从1推断出T的类型。所以扣除只是失败。在考虑转换的情况下,我们从未达到超负荷分辨率

碰巧你可以从扣除期间考虑的块参数:

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) {} 

,现在你的主编译。

相关问题