草庐IT

c++ - 实现比较运算符的模板类

coder 2024-02-04 原文

将所有重载的比较运算符写入一个类是我的一项常见任务,因此我编写了一个模板类,如果派生类实现了 == 和 <,则该模板类实现了><><=,>=,!= .它正在工作,但具有很多转换和不那么明显的“奇怪的重复模板模式”,所以我想知道是否有更简单的解决方案?

template <class Derived>
class Comparable
{
public:

    bool operator!=(const Comparable<Derived>& other) {
        return !(static_cast<Derived*>(this)->operator==
                     (*static_cast<const Derived*>(&other)));
    }

    bool operator<=(const Comparable<Derived>& other) {
        return (static_cast<Derived*>(this)->operator==
                    (*static_cast<const Derived*>(&other)))
                || (static_cast<Derived*>(this)->operator<
                    (*static_cast<const Derived*>(&other)));
    }

    bool operator>(const Comparable<Derived>& other) {
        return !(static_cast<Derived*>(this)->operator==
                    (*static_cast<const Derived*>(&other)))
                && !(static_cast<Derived*>(this)->operator<
                    (*static_cast<const Derived*>(&other)));
    }

    bool operator>=(const Comparable<Derived>& other) {
        return !(static_cast<Derived*>(this)->operator<
                    (*static_cast<const Derived*>(&other)));
    }
};

最佳答案

如果从评论中的描述看不明显:

template <typename T>
struct Comparable {
   friend bool operator!=(T const & lhs, T const & rhs) { return !(lhs == rhs); }
   friend bool operator> (T const & lhs, T const & rhs) { return   rhs <  lhs;  }
// ...
};
class MyType : Comparable<MyType> {
   int data;
   friend bool operator==(MyType const & lhs, MyType const & rhs) {
      return lhs.data == rhs.data;
   }
   friend bool operator< (MyType const & lhs, MyType const & rhs) {
      return lhs.data <  rhs.data;
   }
  public:
// ...
};

当编译器遇到MyType a, b; a > b;对运算符的查找最终将执行 ADL,它将在内部查找 MyTypeComparable<MyType> (因为这是一个基础),它将在其中找到您需要的实现:bool operator>(MyType const&, MyType const&) .

作为自由函数的运算符允许定义在被比较的类型之外(在本例中为基类),同时使这些运算符只能通过 ADL 可用(两个参数之一必须是 Comparable<MyType> ) .自由函数的使用还提供了类型对称性,编译器将允许在两侧进行隐式转换,而在成员函数的情况下,它只允许在运算符的右侧进行转换。


为了完整起见,可以采用另一种技巧,即在命名空间中将运算符作为模板提供,并提供一个标签,该标签可用于将该命名空间引入 ADL 目的:

namespace operators {
   template <typename T> 
   bool operator>(T const & lhs, T const & rhs) {
       return rhs < lhs;     
   }
// rest of the operators come here
   struct tag {};
}
class MyType : operators::tag {
   int data;
   friend bool operator<(T const & lhs, T const & rhs) {
      return lhs.data < rhs.data;
   }
//...
};

技巧基本相同,只是在这种情况下运算符不是在基类中找到的,而是在与其关联的 namespace 中找到的。这个解决方案不如前一个好,因为它容易受到不同形式的滥用,包括 using namespace operators;这将使模板化运算符可用于所有类型。

关于c++ - 实现比较运算符的模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30458629/

有关c++ - 实现比较运算符的模板类的更多相关文章

  1. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的: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?并散列所有无济于事。

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  4. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为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)是

  5. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  6. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  7. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将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.你能做的最好的事情是:

  8. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  9. ruby-on-rails - Mandrill API 模板 - 2

    我正在使用Mandrill的RubyAPIGem并使用以下简单的测试模板:testastic按照Heroku指南中的示例,我有以下Ruby代码:require'mandrill'm=Mandrill::API.newrendered=m.templates.render'test-template',[{:header=>'someheadertext',:main_section=>'Themaincontentblock',:footer=>'asdf'}]mail(:to=>"JaysonLane",:subject=>"TestEmail")do|format|format.h

  10. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

随机推荐