使用无捕获lambda表达式作为条件运算符的第二和第三个操作数时的MSVC错误 [英] MSVC error when using capture-less lambda expressions as second and third operand of conditional operator

查看:198
本文介绍了使用无捕获lambda表达式作为条件运算符的第二和第三个操作数时的MSVC错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码很高兴地被GCC和Clang用 -std = c ++ 14 接受,但是会导致Visual Studio 2013出现编译错误。

The code below is happily accepted by both GCC and Clang with -std=c++14 but causes a compile error with Visual Studio 2013.

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
    auto increasing = [](int lhs, int rhs){return lhs < rhs;};
    auto decreasing = [](int lhs, int rhs){return lhs > rhs;};
    std::vector<int> v(0, 10);
    bool increase = true;
    std::sort(v.begin(), v.end(), increase ? increasing : decreasing);
    return 0;
}

错误是:

main.cpp(11):error C2446:':':没有从'main ::< lambda_0228ee097b83254cfd8aa5f4015a245b>'到'main ::< lambda_bbb1616d067baa9d4462132ee332363c& .cpp(11):注意:没有可以执行此转换的用户定义转换运算符,或者不能调用运算符

我想我的问题是哪个编译器符合这里,我猜,它不是MSVC,并有标准的一部分,明确地处理这种情况吗?

I guess my question is which compiler is compliant here, I am guessing that it is not MSVC, and is there a part of the standard which explicitly deals with this situation?

推荐答案

由于没有lambda捕获,他们可以转换为具有兼容签名的函数指针,因此 gcc clang 在这里是正确的。

Since neither lambda capture they can be converted to function pointers with compatible signatures, so gcc and clang are correct here.

有一个gcc错误报告,它很好地总结了这个主题: [c ++ lambda]错误在分配lambda expr时通过operator ?:捕获,并说:

There is a gcc bug report which summarizes this topic well: [c++ lambda] error in assigning lambda expr though "operator?:" while capturing that covers this and says:


编译器的行为对我来说是正确的。 bar和 foo3 中的
lambda表达式与其他两个的区别是
这些是无捕获lambdas,因此具有转换函数到
函数指针。

The compiler behaviour looks correct to me. The difference of the lambda expressions in bar and foo3 compared to the other two is that these are capture-free lambdas and thus have a conversion function to function pointer.

每个lambda表达式对应一个唯一的类类型,所以我们
foo1 code> foo2
可以与以下
类别范例比较:

Each lambda expression corresponds to a unique class type, so what we have in foo1 and foo2 can be compared with the following class-example:

struct A{}; struct B{};
void f() { false ? A() : B(); }

此表达式对条件运算符没有通用类型,而是
不成形。

This expression has no common type for the conditional operator and is ill-formed.

我们在 bar foo3 与下面的
类例子比较:

What we have in bar and foo3 can be compared with the following class-example :

struct A
{
    typedef void (*F)();
    operator F();
};

struct B
{
    typedef void (*F)();
    operator F();
};

void f() { false ? A() : B(); }

这是完美的,因为在条件
操作符转换的最后一步尝试(5.16p5),更一般的转换是
尝试,并且这些找到了函数的公共指针。

This is well-formed, because in the last step of the conditional operator conversion attempts (5.16p5), more general conversions are attempted and these find the common pointer to function.

5.16p5 说:


否则结果是prvalue。如果第二和第三操作数
不具有相同的类型,并且具有(可能是cv限定的)
类类型,则使用重载分辨率来确定转换
(如果有)应用于操作数(13.3.1.2,13.6)。如果
重载解析失败,程序是不成形的。否则,应用由此确定的$​​ b $ b转换,并且使用转换的操作数
代替该
部分的剩余部分的原始操作数。

Otherwise, the result is a prvalue. If the second and third operands do not have the same type, and either has (possibly cv-qualified) class type, overload resolution is used to determine the conversions (if any) to be applied to the operands (13.3.1.2, 13.6). If the overload resolution fails, the program is ill-formed. Otherwise, the conversions thus determined are applied, and the converted operands are used in place of the original operands for the remainder of this section.

如果我们改变你的代码如下:

If we change your code as follows:

int x = 20 ;
auto increasing = [&x](int lhs, int rhs){return lhs < rhs;};
auto decreasing = [&x](int lhs, int rhs){return lhs > rhs;};

两者 gcc clang 产生错误, clang 说( see it live

both gcc and clang generate an error, clang says (see it live):

error: incompatible operand types ('(lambda at prog.cc:8:23)' and '(lambda at prog.cc:9:23)')
std::sort(v.begin(), v.end(), increase ? increasing : decreasing);
                                      ^ ~~~~~~~~~~   ~~~~~~~~~~

有关草稿C ++ 11标准 5.1.2 [expr.prim.lambda] 说:


没有lambda捕获的lambda表达式的闭包类型有一个
public非虚拟非显式const转换函数到指针
到具有相同参数和返回类型作为闭包
类型的函数调用操作符。这个转换返回的值
函数应该是一个函数的地址,当调用它时,
的效果与调用闭包类型的函数调用操作符相同。

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.

在C ++ 14标准草案中修改了该措辞,但不改变此属性。

The wording is modified in the draft C++14 standard but does not alter this property.

更新

提交了错误报告

这篇关于使用无捕获lambda表达式作为条件运算符的第二和第三个操作数时的MSVC错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆