C++ 将无捕获lambda表达式用作条件运算符的第二个和第三个操作数时发生MSVC错误
下面的代码被GCC和Clang愉快地接受,但在Visual Studio 2013中导致编译错误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 = [
#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);
^ ~~~~~~~~~~ ~~~~~~~~~~