tuk*_*ket 23 c++ lambda initialization variable-assignment c++11
为什么赋值运算符在声明对象的同一行中完成时不允许使用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([]() {
});
}
Run Code Online (Sandbox Code Playgroud)
son*_*yao 22
Func f1 = []() {};是复制初始化,它需要两个用户定义的隐式转换来构造f1,第一个是从lambda到函数指针,第二个是从函数指针到Func.在一个转换序列中只允许一个用户定义的隐式转换,因此它会失败.
(强调我的)
如果T是类类型,并且其他类型的cv-nonqualified版本不是T或从T派生,或者如果T是非类型类型,但是other的类型是类类型,则是用户定义的转换序列可以检查从其他类型转换为T(或从T派生的类型,如果T是类类型并且转换函数可用),并通过重载决策选择最佳的类型.
和
隐式转换序列按以下顺序包含以下内容:
1)零个或一个标准转换序列;
2)零或一个用户定义的转换;
3)零个或一个标准转换序列.
对于f2 = []() {};适当的赋值操作符,尝试调用,Func有一个并且它期望函数指针作为参数; 只需要从lambda到函数指针的一个隐式转换,然后它就可以正常工作.
Func f3([]() {});是直接初始化,尝试调用适当的构造函数,Func有一个并且它期望函数指针作为参数.那就像是一样的f2.
您可以从复制初始化和直接初始化之间的区别中获得重点.
此外,复制初始化中的隐式转换必须直接从初始化器生成T,而例如,直接初始化需要从初始化器到T的构造函数的参数的隐式转换.
你的第一个案件涉及到两个隐式转换,lambda来void(*)(),然后void(*)()到Func.最多可以有1个隐式转换.
如果你可以消除其中一个隐式转换,它应该可以正常工作.以下是您可以尝试的一些潜在解决方案:
// Explicit cast to a function pointer
Func f1 = static_cast<void(*)()>([]() {});
// func_ptr is already a function pointer
// eliminating one of the implcit conversions
void (*func_ptr)() = [](){};
Func f2 = func_ptr;
// The conversion from `void(*)()` is no longer implicit
Func f3{ [](){} };
Run Code Online (Sandbox Code Playgroud)