Перезагрузка операторов сравнения
Нужно было перезагрузить операторы сравнения и я это сделал как знал. Так как типы были разные получилось вот это:
///Реляционные операторы
//-----------------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 шт):
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;
}
};
Несмотря на кажущуюся несимметричность ==, он (и !=) работают независимо от порядка операндов.