我有一些现有的 C++98 代码,它们使用 boost::function 和 boost:bind 进行异步回调。一些相关的简化代码片段包括:
typedef boost::function<void (boost::system::error_code, size_t)> WriteHandler;
struct WriteOperation
{
WriteOperation(const boost::shared_ptr<IDevice>& device,
const std::string& data, const WriteHandler& handler)
: m_Device(device), m_Data(data), m_Handler(handler) {}
private:
boost::shared_ptr<IDevice> m_Device;
std::string m_Data;
WriteHandler m_Handler;
void Complete()
{
boost::system::error_code ec;
size_t len;
...
Async::Post(boost::bind(m_Handler, ec, len));
}
};
struct Device : public IDevice
{
void Write(const std::string& data, const WriteHandler& callback)
{
...
Async::Start(new WriteOperation(shared_from_this(), data,
boost::bind(&Device::HandleWrite, this, handler, _1, _2)));
}
private:
void HandleWrite(const WriteHandler& callback,
boost::system::error_code ec, size_t len)
{
...
callback(ec, len);
}
};
在构造 WriteOperation 时需要一个拷贝,但除此之外我尽量避免拷贝,因为它们可能非常昂贵。
我正在考虑如何在 C++11 世界中最好地编写它。显而易见的容易实现的成果是 WriteOperation 构造函数在内部将其参数复制到其字段,因此应该使用自动复制习惯用法:
WriteOperation(boost::shared_ptr<IDevice> device,
std::string data, WriteHandler handler)
: m_Device(std::move(device)), m_Data(std::move(data)), m_Handler(std::move(handler))
{}
(当然,裸露的 new 应该替换为 unique_ptr,但这是一个附带问题。)
但是,鉴于当前 Device::Write 的实现,我不认为这实际上有任何好处,所以这也应该改变。我的问题是我真的没有看到一个好的方法来做到这一点。根据this advice ,我有三个选择:
声明多个重载(一个使用 const&,一个使用 &&)——但是因为它有两个参数,这两个参数都可以从 move 语义中获益,这将需要四次重载——对于具有更多参数的方法,情况会呈指数级恶化。此外,这会导致代码重复或将代码散布在其他方法上,从而影响可读性。
按值传递并 move (类似于WriteOperation 构造函数)。这可能是当正文总是制作拷贝时最干净的选项,如果实际调用了 WriteOperation 构造函数,这是正确的,但是如果省略的部分包含可能返回而不构造 WriteOperation 的逻辑怎么办?在这种情况下有一个浪费的拷贝。
模板和完美转发。这需要一个丑陋的 SFINAE hack,它会混淆 Intellisense 并削弱可读性(或者更糟,使参数类型不受约束),并且需要将实现放入 header 中,这有时是不可取的。 并且它会干扰类型转换,例如。寻找 std::string 的 SFINAE enable_if is_same 将不接受 const char * 文字,而原始的const& 版本会。
我错过了什么吗?有更好的解决方案吗?或者这只是 move 语义没有任何区别的情况?
相关案例:
typedef boost::function<void (boost::system::error_code, const std::string&)> ReadHandler;
void Read(const ReadHandler& callback)
{
... boost::bind(&Device::HandleRead, this, callback, _1, _2) ...
}
void HandleRead(const ReadHandler& callback,
boost::system::error_code ec, const std::string& data)
{
...
callback(ec, data);
}
这一切看起来应该没问题,没有复制也不需要 move 语义。我再次不确定传递给 Read 的 ReadHandler。
最佳答案
大致顺序:
如果复制和 move 一样昂贵,请用 const& .
如果您可靠地保留一份拷贝,并且搬家很便宜,请按值(value)获取。
如果做不到这一点,您可以将其填充到标题中,并且可以使用 sfinae 或不受约束的模板,使用转发引用。
否则,如果参数数量有限,请编写每个重载。这是 2^n在参数的数量上,所以最好不要太多。在内部转发到基于转发引用的实现。
否则,您真的需要效率吗?
否则,输入 erase 到“T 的创建者”。
template<class T, using Base=std::function<T()>>
struct creator_of: Base
{
template<class U,
std::enable_if_t<std::is_constructible<T, U&&>{},int> =0
>
creator_of(U&&u):
Base([&]()->T{ return std::forward<U>(u); })
{}
template<class U,
std::enable_if_t<std::is_constructible<T, std::result_of_t<std::decay_t<U>()>{},int> =0
>
creator_of(U&&u):
Base(std::forward<U>(u))
{}
creator_of(creator_of&&)=default;
creator_of():
Base([]()->T{return {};}}
{}
};
根据需要增加。 creator_of<std::string>可以由可以构建 std::string 的事物构建,或来自返回 std::string 的函数对象.
内部您可以调用()一次就可以了。
(代码未编译,但设计合理。)
关于c++ - 将 C++11 move 语义应用于绑定(bind)函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39950667/
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin