为什么在直接初始化和赋值中传递 lambda 而不是复制初始化时会编译?
Why does this compile when passing a lambda in direct initialization and assignment but not with copy initialization?
为什么赋值运算符在声明对象的同一行中不允许使用 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([]() {
});
}
您的第一个案例涉及两个隐式转换,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{ [](){} };
Func f1 = []() {};
是 copy initialization, which requires two user-defined implicit conversion to construct f1
, the 1st one is from the lambda to the function pointer, the 2nd one is from the function pointer to Func
. Only one user-defined implicit conversion is allowed in one conversion sequence 所以它失败了。
(强调我的)
If T is a class type, and the cv-unqualified version of the type of other is not T or derived from T, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution.
和
Implicit conversion sequence consists of the following, in this order:
1) zero or one standard conversion sequence;
2) zero or one user-defined conversion;
3) zero or one standard conversion sequence.
对于 f2 = []() {};
尝试调用适当的赋值运算符,Func
有一个并且它期望函数指针作为参数;只需要一次从 lambda 到函数指针的隐式转换,然后就可以正常工作了。
Func f3([]() {});
是 direct initialization,尝试调用适当的构造函数,Func
有一个,它需要函数指针作为参数。那么就和f2
.
一样
复制初始化和直接初始化的区别,你可能明白了。
In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor.
为什么赋值运算符在声明对象的同一行中不允许使用 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([]() {
});
}
您的第一个案例涉及两个隐式转换,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{ [](){} };
Func f1 = []() {};
是 copy initialization, which requires two user-defined implicit conversion to construct f1
, the 1st one is from the lambda to the function pointer, the 2nd one is from the function pointer to Func
. Only one user-defined implicit conversion is allowed in one conversion sequence 所以它失败了。
(强调我的)
If T is a class type, and the cv-unqualified version of the type of other is not T or derived from T, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution.
和
Implicit conversion sequence consists of the following, in this order:
1) zero or one standard conversion sequence;
2) zero or one user-defined conversion;
3) zero or one standard conversion sequence.
对于 f2 = []() {};
尝试调用适当的赋值运算符,Func
有一个并且它期望函数指针作为参数;只需要一次从 lambda 到函数指针的隐式转换,然后就可以正常工作了。
Func f3([]() {});
是 direct initialization,尝试调用适当的构造函数,Func
有一个,它需要函数指针作为参数。那么就和f2
.
复制初始化和直接初始化的区别,你可能明白了。
In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor.