简体   繁体   中英

reduce unnecessary operator overloading in C++

After I overloaded < , == , + , - , * ... in a class named Fraction :

class Fraction:
public:
    // constructor, operator= ... defined before
    bool operator<(const Fraction& A) const;
    bool operator==(const Fraction& A) const;
    Fraction operator+(const Fraction& A) const;
    Fraction operator-(const Fraction& A) const;
    Fraction operator*(const Fraction& A) const;
    Fraction operator/(const Fraction& A) const;

I could use these above 'basic' operators to overload > , += , ++ and + from left...

class Fraction:
public:
    bool operator>(const Fraction& A) const {
        return A < *this;
    }
    bool operator!=(const Fraction& A) const {
        return !(*this == A);
    }
    Fraction &operator+=(const Fraction& A) const {
        return *this = *this + A;
    }
    Fraction operator++() const {
        return *this += 1;
    }
    friend Fraction &operator+(const int& a, const Fraction& A) const {
        return A + a;
    }

However, I also have classes like RealNumber , Complex ... They also need overloading, but only overloading < , == , + , - , * ... differs, while overloading > , += , ++ ... is similar. (just a typename difference)

So I'm curious about an elegant way to reduce the similar part, I've learnt the CRTP that possible helps, but it only overloads comparison...

Use a CRTP base class like boost::operators to define the boring bits. You just define the methods below, and it automatically adds all the other operators for you.

class Fraction {
    : boost::operators<Fraction>
public:
    bool operator<(const Fraction& x) const {...}
    bool operator==(const Fraction& x) const {...}
    Fraction& operator+=(const Fraction& x) {...}
    Fraction& operator-=(const Fraction& x) {...}
    Fraction& operator*=(const Fraction& x) {...}
    Fraction& operator/=(const Fraction& x) {...}
    Fraction& operator%=(const Fraction& x) {...}
    Fraction& operator|=(const Fraction& x) {...}
    Fraction& operator&=(const Fraction& x) {...}
    Fraction& operator^=(const Fraction& x) {...}
    Fraction& operator++() {...}
    Fraction& operator--() {...}
}

https://www.boost.org/doc/libs/1_41_0/libs/utility/operators.htm

You may be interested in the three-way comparison operator (Also known as the space ship operator):

It does however require C++20

It won't reduce all the operators you will have to write. But at least the comparison operators you have to write are reduced.

If we are talking about C++20, then

/* some type traits */
namespace detail {
    template <typename T> struct is_number_helper : public std::false_type {};
    template <> struct is_number_helper<Fraction> : public std::true_type  {};
    /* do for every number class */
}

template <typename T>
inline constexpr bool is_number = detail::is_number_helper<std::remove_cv_t<T>>::value;

/* concept */
template <typename T>
concept Number = is_number<T>;

/* generic operator (for all Number types) */

template <Number N>
constexpr N operator + (const N& lhs, const N& rhs) { /*...*/ }
/* ... */

/* specialized operator */

constexpr Complex operator + (const Complex& lhs, const Complex& rhs) { /*...*/ }
/* ... */

If you don't specialize an operator, the generic one will be used, if there is a specialized operator, then that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM