考虑一个带有重载加法运算符 += 和 + 的遗留类模板>
template<class T>
class X
{
public:
X() = default;
/* implicict */ X(T v): val(v) {}
X<T>& operator+=(X<T> const& rhs) { val += rhs.val; return *this; }
X<T> operator+ (X<T> const& rhs) const { return X<T>(*this) += rhs; }
private:
T val;
};
在代码审查中,观察到 + 可以根据 += 实现,所以为什么不将其设为非成员(并保证左对称)和正确的论点)?
template<class T>
class X
{
public:
X() = default;
/* implicit */ X(T v): val(v) {}
X<T>& operator+=(X<T> const& rhs) { val += rhs.val; return *this; }
private:
T val;
};
template<class T>
X<T> operator+(X<T> const& lhs, X<T> const& rhs)
{
return X<T>(lhs) += rhs;
}
它看起来足够安全,因为所有使用 + 和 += 的有效表达式都保留了它们的原始语义。
问题:将operator+ 从成员函数重构为非成员函数是否会破坏任何代码?
破损的定义(从最差到最好)
operator+(来自基类或通过 ADL 拖入的关联命名空间)最佳答案
答案是肯定的,总会有破损的。基本要素是函数模板参数推导不考虑隐式转换。我们考虑三种情况,涵盖重载运算符可以采用的三种语法形式。
这里我们在 X<T> 中使用了一个隐式构造函数本身。但即使我们创建了构造函数 explicit , 用户可以添加到 X<T> 的命名空间一类C<T>包含 operator X<T>() const 形式的隐式转换.在这种情况下,以下情况将继续成立。
从某种意义上说,非成员友元函数破坏最少,因为它允许 lhs 参数隐式转换,而这种转换不会为类模板的成员函数编译。非成员函数模板破坏了 rhs 参数的隐式转换。
template<class T>
class X
{
public:
/* implicit */ X(T val) { /* bla */ }
//...
X<T> operator+(X<T> const& rhs) { /* bla */ }
//...
};
这段代码将允许像这样的表达
T t;
X<T> x;
x + t; // OK, implicit conversion on non-deduced rhs
t + x; // ERROR, no implicit conversion on deduced this pointer
template<class T>
class X
{
public:
/* implicit */ X(T val) { /* bla */ }
//...
friend
X<T> operator+(X<T> const& lhs, X<T> const& rhs) { /* bla */ }
//...
};
自 friend函数不是模板,不会进行参数推导,并且 lhs 和 rhs 参数都考虑隐式转换
T t;
X<T> x;
x + t; // OK, implicit conversion on rhs
t + x; // OK, implicit conversion on lhs
template<class T>
class X
{
public:
/* implicit */ X(T val) { /* bla */ }
//...
};
template<class T>
X<T> operator+(X<T> const& lhs, X<T> const& rhs) { /* bla */ }
在这种情况下,lhs 和 rhs 参数都进行参数推导,并且都不考虑隐式转换:
T t;
X<T> x;
x + t; // ERROR, no implicit conversion on rhs
t + x; // ERROR, no implicit conversion on lhs
关于c++ - 将重载运算符重构为非成员函数是否会破坏任何代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26089156/
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
请帮助我理解范围运算符...和..之间的区别,作为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)是
我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article
我正在尝试用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
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru