Перезагрузка операторов сравнения

Нужно было перезагрузить операторы сравнения и я это сделал как знал. Так как типы были разные получилось вот это:

///Реляционные операторы
//-----------------Money and Money----------------------------------------    
friend bool operator== (const Money& first, const Money& second) noexcept;
friend bool operator!= (const Money& first, const Money& second) noexcept;
friend bool operator> (const Money& first, const Money& second) noexcept;
friend bool operator< (const Money& first, const Money& second) noexcept;
friend bool operator>= (const Money& first, const Money& second) noexcept;
friend bool operator<= (const Money& first, const Money& second) noexcept;
//-----------------double and Money---------------------------------------
friend bool operator== (const double first, const Money& second) noexcept;
...
friend bool operator<= (const double first, const Money& second) noexcept;
//------------------Money and double--------------------------------------
friend bool operator== (const Money& first, const double second) noexcept;
...
friend bool operator<= (const Money& first, const double second) noexcept;

В итоге получилось 18 операторов. Хотел узнать можно ли это как-то сократить?

Класс Money используется другим классом Goods. Поле цены в Goods является Money. В методах Goods идет сравнение цен с типами double, int. Пример:

//_cost - типа Money
if (_cost < 0)
        throw string("ERR - " + to_string(_cost.MoneyToDouble()) + " < 0");
    this->cost = _cost;

Ответы (1 шт):

Автор решения: HolyBlackCat

double - сомнительный тип для хранения денег. Лучше возьмите целочисленный тип, и храните в целых копейках/центах/...


можно ли это как-то сократить?

Можно! Но нужен spaceship operator из C++20: <=>

Если у Money есть не-explicit конструктор от double, то так:

#include <compare>

class Money
{
    double value = 0;
    
  public:
    Money(double value) : value(value) {}

    friend auto operator<=>(const Money &a, const Money &b) = default;
};

Это дает вам все операторы сравнения: ==,!=,<,<=,>,>= - между Money-Money, и Money-double.

Если нужна кастомная логика сравнения полей, а не дефолтная, тогда так:

#include <compare>

class Money
{
    double value = 0;
    
  public:
    Money(double value) : value(value) {}

    friend auto operator<=>(const Money &a, const Money &b)
    {
        return a.value <=> b.value;
    }

    friend bool operator==(const Money &a, const Money &b)
    {
        return a.value == b.value;
    }
};

Заметьте, что если <=> не default, то он дает только <,<=,>,>=. Чтобы получить == и !=, нужно руками написать ==.

Если у Money нет не-explicit конструктора от double, то нужен второй <=> между Money и double:

#include <compare>

class Money
{
    double value = 0;
    
  public:
    explicit Money(double value) : value(value) {}

    friend auto operator<=>(const Money &a, const Money &b) = default;

    friend auto operator<=>(const Money &a, double b)
    {
        return a.value <=> b;
    }

    friend bool operator==(const Money &a, double b)
    {
        return a.value == b;
    }
};

Несмотря на кажущуюся несимметричность ==, он (и !=) работают независимо от порядка операндов.

→ Ссылка