调用带有参数的函数可以隐式转换为模板类的对象

时间:2017-09-13 02:04:46

标签: c++ templates compiler-errors

考虑以下示例(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>,为什么此代码无法编译?

1 个答案:

答案 0 :(得分:4)

模板功能不是功能。它们是用于编写函数的模板。

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

现在你的主要编译。