为什么在声明对象的同一行中完成赋值运算符不允许使用lambda表达式?
它似乎在MSVC中工作。
测试代码:https : //godbolt.org/g/n2Tih1
class Func
{
typedef void(*func_type)();
func_type m_f;
public:
Func() {}
Func(func_type f) : m_f(f) {}
Func operator=(func_type f) {
m_f = f;
return *this;
}
};
int main()
{
// doesn't compile in GCC and clang, it does in MSVC
Func f1 = []() {
};
// compiles!
Func f2;
f2 = []() {
};
// compiles!
Func f3([]() {
});
}
Func f1 = []() {};
是副本初始化,需要两个用户定义的隐式转换来构造f1
,第一个是从lambda到函数指针,第二个是从函数指针到Func
。一个转换序列中仅允许一个用户定义的隐式转换,因此它将失败。
(强调我的)
如果T是类类型,并且other的cv不合格版本不是T或不是从T派生的,或者T是非类类型,但是other的类型是类类型,则用户定义的转换序列可以将其他类型转换为T(如果T是类类型并且可以使用转换函数,则可以转换为从T派生的类型),然后通过重载分辨率选择最佳的。
和
隐式转换顺序按以下顺序组成:
1)零个或一个标准转换序列;
2)零个或一个用户定义的转换;
3)零或一标准转换序列。
对于f2 = []() {};
试图调用适当的赋值运算符Func
,它有一个,并且期望函数指针作为参数;仅需要一次从lambda到函数指针的隐式转换,然后它可以很好地工作。
Func f3([]() {});
是直接初始化,尝试调用适当的构造函数,该构造函数Func
有一个,并且期望函数指针作为参数。然后与相同f2
。
您可能会从复制初始化和直接初始化之间的区别中得到启发。
另外,复制初始化中的隐式转换必须直接从初始值设定项产生T,而直接初始化期望从初始值设定项到T的构造函数的参数进行隐式转换。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句