Home > front end >  reduce unnecessary operator overloading in C
reduce unnecessary operator overloading in C

Time:09-03

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...

CodePudding user response:

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

CodePudding user response:

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.

CodePudding user response:

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.

  • Related