[英]C++ template: no matching function for call
我无法理解为什么这个程序无法用g ++ 7.3或clang ++ 5.0使用-std = c ++ 14进行编译。
可以从const int
初始化A
,如图所示。 甲常量引用A
也可以从一个创建const int
但来电f(const A &)
与const int
失败。 为什么?
#include <iostream>
struct V {
int i;
template <class T>
V(const T &t) : i{t} {}
};
struct A {
int i;
A(V v) : i{v.i} {}
};
void f(const A &) {}
int main() {
const auto i = 42;
const A a1{i}; // OK
std::cout << a1.i << '\n'; // 42
const A &a2 = A{i}; // OK
std::cout << a2.i << '\n'; // 42
f(i); // no matching function for call to 'f'
return 0;
}
出于函数调用的目的将i
转换为A
将需要两个用户定义的转换( int -> V -> A
)。 该标准对每个隐式转换序列设置单个用户定义转换的硬限制。
如果您尝试将a2
“直接”绑定到i
也会发生同样的情况。 因此,在为f
赋予参数时,您还需要执行函数样式转换( A{i}
)。
鉴于f(i);
,应用复制初始化 。 并且i
(使用类型const int
)需要转换为A
,需要两个用户定义的转换; 从const int
到V
,从V
到A
但在一个隐式转换序列中只允许一个用户定义的转换。
Bot const A a1{i};
和const A &a2 = A{i};
是直接初始化 ,只需要从i
(使用类型const int
)到A
的构造函数(即V
)的参数进行一次隐式转换,因此它们可以正常工作。
注意复制初始化和直接初始化之间的区别,
此外,复制初始化中的隐式转换必须直接从初始化器生成T,而例如,直接初始化需要从初始化器到T的构造函数的参数的隐式转换。
作为一种变通方法,您可以在将其传递给f()
之前对i
执行显式转换。
这里你需要两个连续的隐式类型转换,但是C ++可以为你做单个转换implicitley。 如果您想让编译器为您生成正确的类型代码,请使用template
作为函数f
,如下所示。
template <typename T>
void f(const T & x) { std::cout << x << std::endl;}
你需要两个类型转换的原因是因为只有一个构造函数在结构中采用了类型V
如果你想摆脱两种类型转换作为第二种解决方案,你可以添加另一个构造函数,它将int
作为参数,如下所示
struct A {
int i;
A(V v) : i{v.i} {}
A(int theI) : i{theI} { }
};
复制初始化不支持两个用户定义的转换。 解决这个问题的简单方法是用A包裹我,同时用f(A(i))
传递给f
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.