Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将无捕获lambda表达式用作条件运算符的第二个和第三个操作数时发生MSVC错误_C++_Visual C++_C++11_Visual Studio 2013_Language Lawyer - Fatal编程技术网

C++ 将无捕获lambda表达式用作条件运算符的第二个和第三个操作数时发生MSVC错误

C++ 将无捕获lambda表达式用作条件运算符的第二个和第三个操作数时发生MSVC错误,c++,visual-c++,c++11,visual-studio-2013,language-lawyer,C++,Visual C++,C++11,Visual Studio 2013,Language Lawyer,下面的代码被GCC和Clang愉快地接受,但在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 = [

下面的代码被GCC和Clang愉快地接受,但在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;
}
#包括
#包括
#包括
使用名称空间std;
int main(){
自动递增=[](int-lhs,int-rhs){返回lhsrhs;};
std::向量v(0,10);
布尔增加=真;
排序(v.begin(),v.end(),增加?增加:减少);
返回0;
}
错误是:

main.cpp(11):错误C2446:':':没有从'main::'转换为'main:'
main.cpp(11):注意:没有可执行此转换的用户定义的转换运算符,或者无法调用该运算符


我想我的问题是哪个编译器在这里是兼容的,我猜它不是MSVC,标准中是否有一部分明确地处理了这种情况?

因为两个lambda捕获都不能转换为具有兼容签名的函数指针,所以
gcc
clang
在这里是正确的

有一份gcc错误报告很好地总结了这个主题:它涵盖了这一点,并说:

编译器的行为在我看来是正确的。差异 bar和
foo3
中的lambda表达式与其他两个表达式相比 这些是无捕获的lambda,因此具有到的转换功能 函数指针

每个lambda表达式对应一个唯一的类类型,所以我们 可以将
foo1
foo2
中的have与以下内容进行比较 课堂示例:

struct A{}; struct B{};
void f() { false ? A() : B(); }
此表达式没有条件运算符的通用类型,因此是 格式不正确

我们在
bar
foo3
中的内容可以与以下内容进行比较 课堂示例:

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

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

void f() { false ? A() : B(); }
这是格式良好的,因为在条件 运算符转换尝试(5.16p5),更一般的转换是 已尝试并找到指向函数的公共指针

5.16p5
说:

否则,结果是一个pr值。如果第二个和第三个操作数 不具有相同的类型,并且其中一个具有(可能符合cv条件) 类类型,重载解析用于确定转换 (如果有)应用于操作数(13.3.1.2、13.6)。如果 重载解析失败,程序格式不正确。否则 应用由此确定的转换,并转换操作数 用于替换此操作的其余部分的原始操作数 节

如果我们按以下方式更改您的代码:

int x = 20 ;
auto increasing = [&x](int lhs, int rhs){return lhs < rhs;};
auto decreasing = [&x](int lhs, int rhs){return lhs > rhs;};
作为参考,
5.1.2
[expr.prim.lambda]说:

没有lambda捕获的lambda表达式的闭包类型具有 公共非虚非显式常量到指针的转换函数 具有与闭包相同的参数和返回类型的函数 类型的函数调用运算符。此转换返回的值 函数应为调用时具有 与调用闭包类型的函数调用操作符的效果相同

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

更新


归档了。

即使使用“-std=c++11”,Clang也会接受代码,这有点奇怪。我认为不应该这样做,因为将没有捕获到函数指针的lambda转换为C++14标准。@Windoze来自C++11“国际标准”文档:“没有捕获到lambda的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,将其转换为指向函数[…]的指针。”@Windoze我在我的答案中添加了此转换的标准参考。当我试图获得“您无权提交此连接的反馈”时,请确保提交一个。@ShafikYaghmour。因此,我想我不允许报告错误。嗯,这是不久前我创建连接帐户时,我不认为我必须做任何特殊的事情才能报告错误。我为此提交了一份错误报告,希望我能用更新版本的Visual Studio进行确认。我有Visual Studio Community 2017,它显示了一个错误(操作员有多个定义可用),但运行正常。
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);
                                      ^ ~~~~~~~~~~   ~~~~~~~~~~