适用于不同lambdas的三元操作员会产生不一致的结果
考虑以下使用三元运算符获取两个 lambda 的公共函数指针类型
int main() {
true ? [](auto) noexcept {} : [](int) {};
}
GCC-trunk 仅在 C++14 中接受它,但在 C++17/20 中拒绝它 (Demo):
<source>:2:8: error: operands to '?:' have different types 'main()::<lambda(auto:1)>' and 'main()::<lambda(int)>'
2 | true ? [](auto) noexcept {} : [](int) {};
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Clang-trunk 在所有 C++14/17/20 模式下接受它 (演示)。
MSVC-trunk 仅在 C++20 中接受它,但在 C++14/17 中拒绝它(Demo):
<source>(2): error C2446: ':': no conversion from 'main::<lambda_01e5bb79b5a210014fb78333f6af80f9>' to 'main::<lambda_57cf6f5767bc1bee4c1e1d9859a585d2>'
<source>(2): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
哪个编译器是正确的?
Consider the following which uses the ternary operator to get the common function pointer type of the two lambdas
int main() {
true ? [](auto) noexcept {} : [](int) {};
}
GCC-trunk only accepts it in C++14 but rejects it in C++17/20 with (Demo):
<source>:2:8: error: operands to '?:' have different types 'main()::<lambda(auto:1)>' and 'main()::<lambda(int)>'
2 | true ? [](auto) noexcept {} : [](int) {};
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Clang-trunk accepts it in all C++14/17/20 mode (Demo).
MSVC-trunk only accepts it in C++20 but rejects it in C++14/17 with (Demo):
<source>(2): error C2446: ':': no conversion from 'main::<lambda_01e5bb79b5a210014fb78333f6af80f9>' to 'main::<lambda_57cf6f5767bc1bee4c1e1d9859a585d2>'
<source>(2): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
Which compiler is right?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于每个lambda表达式都有唯一的类型,并且lambda表达式都不可转换到另一个类型, [expr.cond]/6 适用。
候选人是( [over.built]/25 ):
我相信过载分辨率应该应该解决。在这种情况下,成功,因此,两个操作数都应转换为
void(*)(int)
。也就是说,IMO Clang是正确的。
编辑:我相信
[](auto)noexcept {}
可转换为void(*)(int)
,因为它具有转换功能模板code> template&lt; T&GT级操作员fp()
,其中fp
是void(*)(t)(t)
( [expr.prim.lambda.closure]/9 )。而且我相信模板参数扣除应该使此转换模板可作为转换为
void(*)(int)
( [temp.deduct.conv]/5 )。Since each lambda expression has a unique type, and neither lambda expression is convertible to the other, [expr.cond]/6 applies.
The candidates are ([over.built]/25):
I believe that overload resolution should succeed in this case, and as a result, both operands should be converted to
void(*)(int)
.That is, IMO clang is correct.
Edit: I believe that
[](auto) noexcept {}
is convertible tovoid(*)(int)
, because it has a conversion function templatetemplate<class T> operator FP()
, whereFP
isvoid(*)(T)
([expr.prim.lambda.closure]/9).And I believe that template argument deduction should make this conversion template usable as a conversion to
void(*)(int)
([temp.deduct.conv]/5).