下面的代码被 GCC 和 Clang 欣然接受 -std=c++14但会导致 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: ':': no conversion from 'main::<lambda_0228ee097b83254cfd8aa5f4015a245b>' to 'main::<lambda_cb3b816d067baa9d4462132ee332363c>'
main.cpp(11): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
我想我的问题是哪个编译器兼容,我猜它不是 MSVC,标准中是否有明确处理这种情况的部分?
最佳答案
由于 lambda 捕获都不能将它们转换为具有兼容签名的函数指针,因此 gcc 和 clang 在这里是正确的。
有一个 gcc 错误报告很好地总结了这个主题: [c++ lambda] error in assigning lambda expr though "operator?:" while capturing 涵盖了这一点并说:
The compiler behaviour looks correct to me. The difference of the lambda expressions in bar and
foo3compared to the other two is that these are capture-free lambdas and thus have a conversion function to function pointer.Each lambda expression corresponds to a unique class type, so what we have in
foo1andfoo2can 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.
What we have in
barandfoo3can 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(); }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 说:
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.
如果我们按如下方式更改您的代码:
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 ):
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);
^ ~~~~~~~~~~ ~~~~~~~~~~
供引用draft C++11 standard 5.1.2 [expr.prim.lambda] 说:
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 标准草案中有所修改,但不会改变此属性。
更新
提交了 bug report .
关于c++ - 使用无捕获 lambda 表达式作为条件运算符的第二个和第三个操作数时出现 MSVC 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27989031/
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee