0

When overloading comparison operators for a type that can be ordered linearly, I typically end up with something like this (example is of comparing poker hand types):

enum class HandType : char {
    HIGH_CARD = 0,
    PAIR = 1,
    TWO_PAIR = 2,
    SET = 3,
    STRAIGHT = 4,
    FLUSH = 5,
    FULL_HOUSE = 6,
    QUADS = 7,
    STRAIGHT_FLUSH = 8,
    ROYAL_FLUSH = 9
};

bool operator<(HandType hero, HandType vill) {
    return static_cast<int>(hero) < static_cast<int>(vill);
}

bool operator>(HandType hero, HandType vill) {
    return vill < hero;
}

bool operator==(HandType hero, HandType vill) {
    return !(hero < vill) && !(hero > vill);
}

bool operator!=(HandType hero, HandType vill) {
    return !(hero == vill);
}

bool operator>=(HandType hero, HandType vill) {
    return hero > vill || hero == vill;
}

bool operator<=(HandType hero, HandType vill) {
    return hero < vill || hero == vill;
}

Yet the only operator that really contains information is the less than operator, and the remaining are identical and copy-pasted for every enum class that I do not want to declare as a plain enum for the sake of type safety.

Is there any way to implicitly define the remaining 5 operators that are always defined in terms of the less than operator, or any other way to make this less verbose, especially with many different enum classes that each need comparison operators?

J. Grohmann
  • 391
  • 1
  • 6
  • 15
  • 2
    If you have C++20, you can use the spaceship operator and then you only need to define `operator==` and `operator<=>`. – Nathan Pierson Apr 16 '21 at 00:15
  • 1
    As Nathan mentioned, C++20 solved the problem. Mean while, you could check [Base enum class inheritance](https://stackoverflow.com/questions/644629/base-enum-class-inheritance), and define the enums as separated classes, and all inherit from a single comparable class. – Ranoiaetep Apr 16 '21 at 00:25
  • To only write the functions once, since C++11 an option that doesn't rely on C++20 is to make them a template and constrain them to only work with enumerated types, such as `template::value>::type> bool operator>(E left, E right) {return right < left;}`. Be certain that you want *every* enumerated type to be comparable this way though. – Peter Apr 16 '21 at 00:44
  • Also note that most of the overloads can be implemented with just a few operators. See Comparison operators in [this answer](https://stackoverflow.com/a/4421719/4342498) – NathanOliver Apr 16 '21 at 01:09

0 Answers0