Search code examples
c++classinheritanceoperator-overloadingvirtual

How to implement "less" on derived types without dynamic_cast?


I want to implement a "less"-type operation on the following classes:

class Base {
  public:
    virtual int type() const = 0;
  private:
    int b;
};

class Derived1 : public Base{
  public:
    virtual int type() const { return 1; }
  private:
    int d1; 
};

class Derived2 : public Base{
  public:
    virtual int type() const { return 2; }
  private:
    int d2;
};

where o1 < o2 if its type is smaller and if the types are equal then the elements are compared (first b then d1 or d2).

Note that there are other operations (eg. equals) with similar problem structure.

How can I do this without using dynamic_cast?


Solution

  • You don't need dynamic_cast nor type. For that matter, no public members at all, either.

    class Base {
      virtual bool less( Base const & rhs ) const {
        return false;
      }
    
      int b;
    
      friend bool operator < ( Base const & lhs, Base const & rhs ) {
        std::type_info const & ltype = typeid (lhs);
        std::type_info const & rtype = typeid (rhs);
        if ( ltype == rtype ) {
          if ( lhs.b < rhs.b ) return true;
          if ( rhs.b < lhs.b ) return false;
          return lhs.less( rhs ); // Dynamic types of lhs and rhs already match.
        }
        return ltype.before( rtype );
      }
    };
    
    class Derived1 : public Base{
      virtual bool less( Base const & rhs_base ) const {
        // Since rhs_base is known to be of this type, use static_cast.
        Derived1 const & rhs = static_cast< Derived1 const & >( rhs_base );
        return d1 < rhs.d1;
      }
    
      int d1; 
    };
    
    // Same for Derived2
    

    http://coliru.stacked-crooked.com/a/af1aae28630878f5 (Includes tests)