我有一个 C++ 类,我需要为其定义一个比较器,该比较器应考虑几种可能代价高昂的方法的结果。我不想为我的集合中的所有对象缓存这些方法的结果,因为具有最高优先级的条件更便宜,而且我希望底部非常昂贵的条件仅在极少数情况下触发。
如果我有一个 cmp() 函数,当第一个参数小于、等于或大于第二个参数时分别返回 -1、0 或 1,并且使用保留整数的快捷逻辑运算符,我可以轻松编写
int compare(const Class &rhs) const {
return cmp(expensive_method_a(), rhs.expensive_method_b()) ||
cmp(expensive_method_b(), rhs.expensive_method_b()) ||
...
}
不幸的是,我需要使用 <>
bool operator<(const Class &rhs) const {
return expensive_method_a() < rhs.expensive_method_a() ||
(expensive_method_a() == rhs.expensive_method_a() &&
(expensive_method_b() < rhs.expensive_method_b() ||
(expensive_method_b() == rhs.expensive_method_b() &&
(...
))))
}
或者,成本较低但仍然很丑陋:
bool operator<(const Class &rhs) const {
auto al = expensive_method_a(), ar = rhs.expensive_method_a();
if (al != ar) return al < ar;
auto bl = expensive_method_b(), br = rhs.expensive_method_b();
if (bl != br) return bl < br;
我在 This 上读到过关于 std::tie 的信息另一个问题,但如果我理解正确,平局会在开始比较之前评估我所有的方法,我希望这些参数被延迟评估。
我考虑过定义这样的预处理器宏:
#define CUT_COMPARE(a,b) { auto _x = (a); auto _y = (b); if (_x != _y) return (_x < _y); }
我会这样使用:
bool operator<(const Class &rhs) const {
CUT_COMPARE(expensive_method_a(), rhs.expensive_method_a());
CUT_COMPARE(expensive_method_b(), rhs.expensive_method_b());
...
}
希望大括号将我的 _x 和 _y 包含在私有(private)范围内,但是,clang++ 提示 的多个定义>_x 和 _y。
有没有更好的方法解决这个问题?
最佳答案
您可以将所有要调用的成员函数转发给一个辅助模板,该模板会根据需要遍历它们:
bool operator<(const Class& rhs) const {
return lazy_compare(*this, rhs, &Class::expensive_1,
&Class::expensive_2,
&Class::expensive_3);
}
lazy_compare 可变参数函数将根据需要一次一个地遍历那些指向成员的指针函数。基本情况只是 true:
template <typename T, typename... MFs>
bool lazy_compare(const T&, const T&, MFs...) {
return true;
}
递归的情况是弹出第一个指向成员的指针,看看我们是否可以在那个指针处停止:
template <typename T, typename R, typename... MFs>
bool lazy_compare(const T& left, const T& right, R (T::*mf)() const, MFs... rest) {
R vleft = (left.*mf)(), vright = (right.*mf)();
if (vleft != vright) {
return vleft < vright;
}
else {
return lazy_compare(left, right, rest...);
}
}
关于C++ 深度懒惰与优雅语法的比较?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30104640/
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
在Ruby类中,我重写了三个方法,并且在每个方法中,我基本上做同样的事情:classExampleClassdefconfirmation_required?is_allowed&&superenddefpostpone_email_change?is_allowed&&superenddefreconfirmation_required?is_allowed&&superendend有更简洁的语法吗?如何缩短代码? 最佳答案 如何使用别名?classExampleClassdefconfirmation_required?is_a
可能已经问过了,但我找不到它。这里有2个常见的情况(对我来说,在编程Rails时......)用ruby编写是令人沮丧的:"astring".match(/abc(.+)abc/)[1]在这种情况下,我得到一个错误,因为字符串不匹配,因此在nil上调用[]运算符。我想找到的是比以下内容更好的替代方法:temp="astring".match(/abc(.+)abc/);temp.nil??nil:temp[1]简而言之,如果不匹配,则简单地返回nil而不会出错第二种情况是这样的:var=something.very.long.and.tedious.to.writevar=some
我正在学习Ruby的基础知识(刚刚开始),我遇到了Hash.[]method.它被引入a=["foo",1,"bar",2]=>["foo",1,"bar",2]Hash[*a]=>{"foo"=>1,"bar"=>2}稍加思索,我发现Hash[*a]等同于Hash.[](*a)或Hash.[]*一个。我的问题是为什么会这样。是什么让您将*a放在方括号内,是否有某种规则可以在何时何地使用“it”?编辑:我的措辞似乎造成了一些困惑。我不是在问数组扩展。我明白了。我的问题基本上是:如果[]是方法名称,为什么可以将参数放在括号内?这看起来几乎——但不完全是——就像说如果你有一个方法Foo.d
如何将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.你能做的最好的事情是:
深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal
我正在尝试使用ruby编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?