我在新版本的 gcc (4.9+) 上遇到了这个奇怪的编译错误。
代码如下:
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <map>
using namespace std;
struct ptrwrap
{
unique_ptr<int> foo;
};
template <typename T>
struct holder
{
holder() = default;
holder(const holder& b)
: t(b.t)
{
}
holder(holder&& b)
: t(std::move(b.t))
{
}
holder& operator=(const holder& h)
{
t = h.t;
return *this;
}
holder& operator=(holder&& h)
{
t = std::move(h.t);
return *this;
}
T t;
};
struct y_u_no_elision
{
holder<ptrwrap> elem;
};
typedef map<std::string, y_u_no_elision> mymap;
mymap foo();
int main()
{
auto m = foo();
m = foo();
return 0;
}
Here它在 ideone 上也有实际错误。基本上它归结为使用 ptrwrap 的删除复制构造函数。哪个……不应该发生。 map 按值返回(即移动),因此不能存在拷贝。
现在相同的代码在旧版本的 gcc(我试过 4.2 和 4.3)、我试过的所有 clang 版本以及 Visual Studio 2015 上都没有问题。
奇怪的是,如果我删除 holder 模板的显式复制和移动构造函数,它也会在 gcc 4.9+ 上编译。如果我将 map 更改为 vector 或 unordered_map 它也可以正常编译( here 是代码编译版本的链接使用 unordered_map)
所以...这是 gcc 4.9 错误还是其他编译器允许我看不到的东西?我能做些什么而不涉及更改 holder 类吗?
最佳答案
简短回答:这是 libstdc++ 中的错误。根据标准中 [container.requirements.general] 中的分配器感知容器需求表(自 C++11 以来未更改),容器移动分配:
Requires: If
allocator_traits<allocator_type>::propagate_on_container_move_assignment::valueisfalse,TisMoveInsertableintoXandMoveAssignable. [...]
(X 是容器类型,T 是它的 value_type )
您正在使用默认分配器,它有 using propagate_on_container_move_assignment = true_type; ,所以上述要求不适用; value_type 应该没有特殊要求.
快速修复:如果您无法触摸 holder ,一种解决方案是更改 y_u_no_elision , 添加
y_u_no_elision(const y_u_no_elision&) = delete;
y_u_no_elision(y_u_no_elision&&) = default;
长话短说:该错误主要是由 this line in stl_tree.h 引起的.
_Rb_tree是 std::map 的底层实现并且其移动赋值运算符定义中的那一行基本上执行上面标准引用指定的检查。但是,它使用简单的 if 来实现,这意味着即使满足条件,另一个分支也必须编译,即使它不会在运行时执行。缺少 Shiny 的新 C++17 if constexpr ,这应该使用诸如标签分派(dispatch)之类的东西来实现(对于前两个条件 - 第三个是真正的运行时检查),以避免在所采用的分支之外实例化代码。
然后错误是由this line引起的,它使用 std::move_if_noexcept在 value_type .说来话长。
value_type是std::pair<const std::string, y_u_no_elision> .
在您的初始代码中:
holder具有非删除、非 noexcept 复制和移动构造函数。y_u_no_elision 的相应隐式声明的构造函数也将是非删除和非 noexcept。 value_type 的构造函数.std::move_if_noexcept返回 const value_type&而不是 value_type&& (如果可以,它会回退到复制 - 请参阅 these docs)。y_u_no_elision 的复制构造函数被调用,这将导致 holder<ptrwrap>要实例化的复制构造函数定义,它试图复制 std::unique_ptr .现在,如果您从 holder 中删除用户声明的拷贝并移动构造函数和赋值运算符 :
holder将得到隐式声明的。复制构造函数将被删除,移动构造函数将被默认,不删除和noexcept . value_type , 除了一个与 holder 无关的异常(exception): value_type的移动构造函数将尝试从 const std::string 移动;这不会调用 string的移动构造函数(在本例中为 noexcept),而是它的复制构造函数,如 string&&无法绑定(bind)到 const string 类型的右值. string的复制构造函数不是 noexcept (它可能必须分配内存),所以 value_type的移动构造函数也不会。 std::move_if_noexcept背后的逻辑: 它返回一个右值引用,即使参数的移动构造函数不是 noexcept ,只要参数不是可复制构造的(如果不能回退到复制,它会回退到非 noexcept 移动);和 value_type不是,因为 holder's删除复制构造函数。这是上面快速修复背后的逻辑:你必须做一些事情才能使 value_type有一个有效的移动构造函数和一个删除的复制构造函数,以便从 move_if_noexcept 获得右值引用.这是因为您将无法制作 value_type有一个noexcept由于 const std::string 移动构造函数,如上所述。
关于c++ - 在新版本的 gcc 上返回隐式不可复制结构的 std::map 时出现编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39040609/
我正在用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
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我遵循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