我有以下 API:
old_operation(stream, format, varArgs);
我想写一个适配器来编写调用如下:
stream << operation(format, varArgs);
为此,我使用了一个临时对象,它存储对 varArgs 的引用并重载 operator<<申请old_operation()如下:
template<typename ...T>
decltype(auto) storage(T&& ...t) {
return [&](auto&& f) ->decltype(auto) {
return std::forward<decltype(f)>(f)(t...);
};
}
template<typename ...T>
class Operation
{
using Storage = decltype(storage(std::declval<T>()...));
public:
template<typename ...Args>
explicit Operation(Args&& ...args) :
mArgs(storage(std::forward<Args>(args)...)) {};
template<class StreamType>
StreamType& Apply(StreamType& stream)
{
auto f = [&](auto&& ...xs)
{
old_operation(stream, std::forward<decltype(xs)>(xs)...);
}
mArgs(f);
return stream;
}
private:
Storage mArgs;
};
template<typename ...Args>
Operation<Args...> MakeOperation(Args&&... args)
{
return Operation<Args...>(std::forward<Args>(args)...);
}
template<class StreamType, typename ...Args>
StreamType& operator<<(StreamType& stream, Operation<Args...>&& operation)
{
return operation.Apply(stream);
}
效果很好,但现在我需要添加一些 using namespace嵌入到操作调用中的声明:
假设我有
namespace X {namespace Y { namespace Z { int formater(double x) { return std::round(x); }}}
而且我不想为这个调用添加所有命名空间,所以我正在做类似的事情:
#define OPERATION(...) \
[&]() { \
using namespace ::X:Y:Z; \
return Operation("" __VA_ARGS__); }() \
这允许我做:
stream << OPERATION(format, formater(2.3));
lambda 的问题是临时对象是在与 Apply() 不同的范围内创建的调用,即 UB。
我不知道通过向 mArgs 添加 const 限定符是否会延长捕获引用的生命周期,如前所述 here .我不确定这是否适用,我假设它们是基于堆栈的引用,并且通过将 const 限定符添加到 mArgs,该限定符将应用于捕获的引用。
最佳答案
template<typename ...T>
decltype(auto) storage(T&& ...t) {
return [&](auto&& f) ->decltype(auto) {
return std::forward<decltype(f)>(f)(t...);
};
}
这是一个 haskell 风格的仿函数(好吧,一个可变的仿函数,它不是很 haskell)。它需要 Ts... 并返回类型为 ((Ts...)->U)->U 的函数,即知道如何计算函数你传递给它的参数。这使得 (Ts...)->( ((Ts...)->U)->U ) 类型的 storage 有点代数的乐趣。
我怀疑你的问题是你有你不存储的临时文件。通常不存储传递给函数的临时变量,返回值取决于这些临时变量的生命周期,导致代码脆弱。
如果你有 C++1z experimental::apply 我们可以这样做:
template<class... Ts>
decltype(auto) storage(Ts&&... ts) {
return
[tup=std::tuple<Ts...>(std::forward<Ts>(ts)...)]
(auto&& f)
->decltype(auto) mutable
{
return std::experimental::apply(decltype(f)(f), std::move(tup));
};
}
返回对 std::apply 的一次性延迟调用。 Apply 接受一个函数和一个元组,并将元组的参数传递给函数。它正确处理引用和 r/lvalue-ness。同时,元组的容器使捕获更简单,让我们可以轻松地有条件地存储右值,同时将左值保留为引用。
我认为这解决了您的问题,因为临时对象被移入元组而不是通过引用捕获,而非临时对象通过引用存储。
应该有 std::experimental::apply 实现,它比我在这里可以轻松绘制的任何东西都要好。
关于c++ - lambda 的生命周期在 const lambda 中捕获引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37545555/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我正在尝试使用ruby编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?
我在使用自定义RailsFormBuilder时遇到了问题,从昨天晚上开始我就发疯了。基本上我想对我的构建器方法之一有一个可选block,以便我可以在我的主要content_tag中显示其他内容。:defform_field(method,&block)content_tag(:div,class:'field')doconcatlabel(method,"Label#{method}")concattext_field(method)capture(&block)ifblock_given?endend当我在我的一个Slim模板中调用该方法时,如下所示:=f.form_field:e
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我想从rubyrake脚本运行一个可执行文件,比如foo.exe我希望将foo.exe的STDOUT和STDERR输出直接写入我正在运行rake任务的控制台.当进程完成时,我想将退出代码捕获到一个变量中。我如何实现这一目标?我一直在玩backticks、process.spawn、system但我无法获得我想要的所有行为,只有部分更新:我在Windows上,在标准命令提示符下,而不是cygwin 最佳答案 system获取您想要的STDOUT行为。它还返回true作为零退出代码,这可能很有用。$?填充了有关最后一次system调
我正在尝试将一个资源属性的默认值设置为另一个属性的值。我正在为我正在构建的tomcat说明书定义一个资源,其中包含以下定义。我想要可以独立设置的“名称”和“服务名称”属性。当未设置服务名称时,我希望它默认为为“名称”提供的任何内容。以下不符合我的预期:attribute:name,:kind_of=>String,:required=>true,:name_attribute=>trueattribute:service_name,:kind_of=>String,:default=>:name注意第二行末尾的“:default=>:name”。当我在Recipe的新block中引用我
我有一个像这样的ruby类:require'logger'classTdefdo_somethinglog=Logger.new(STDERR)log.info("Hereisaninfomessage")endend测试脚本行如下:#!/usr/bin/envrubygem"minitest"require'minitest/autorun'require_relative't'classTestMailProcessorClasses当我运行这个测试时,out和err都是空字符串。我看到消息打印在stderr上(在终端上)。有没有办法让Logger和capture_io一起玩得
关于SSHkit-Github它说:Allbackendssupporttheexecute(*args),test(*args)&capture(*args)来自SSHkit-Rubydoc,我明白execute实际上是test的别名?test之间有什么区别?,execute,capture在Capistrano/SSHKit中我应该什么时候使用? 最佳答案 执行只是执行命令。使用非0退出引发错误。测试方法的行为与execute完全相同,但是它返回bool值(true如果命令以0退出,而false否则)。它通常用于控制任务中的流程