首页 > 解决方案 > 在一个函数中重载多个运算符

问题描述

是否可以在一个运算符重载中重载多个运算符?

我想做这样的事情:

template<operator O>
MyClass operator<O>(const MyClass & other) {
return this.x <O> other.x;
}

其中 x 是类的 int 属性。

这样就可以一次重载所有 int 运算符,这意味着我可以使用一个函数,重载 +、-、*、/ 等。复制粘贴代码一百万次并只更改一行。

在我的具体示例中,我有一个包含两个整数的结构点,以及另一个名为 Pointf 的结构,其中包含两个浮点数,我希望能够将它们彼此相加、相减、相乘和除法,或者使用一个 int 值,目前我用十几个函数来做,但我想只用几个函数来做,我也想覆盖 +=、-=、*- 和 /=。

标签: c++oopoperator-overloading

解决方案


不,您不能在一个运算符重载中重载多个运算符。但是,您可以制作一个用于所有Points 的类模板:

#include <iostream>

template<typename T>
class Point_impl {
public:
    using value_type = T;
    template <typename U>
    friend class Point_impl;

    Point_impl() : x_{}, y_{} {}            // default
    Point_impl(T x, T y) : x_{x}, y_{y} {}  // conversion

    // create one Point_impl<T> from a Point_impl<U> 
    template<typename U>
    Point_impl(const Point_impl<U>& rhs) :
        x_{static_cast<T>(rhs.x_)},
        y_{static_cast<T>(rhs.y_)}
    {}

    T get_x() const { return x_; }
    T get_y() const { return y_; }

    // add a Point_impl<U> to *this
    template<typename U>
    Point_impl<T>& operator+=(const Point_impl<U>& rhs) {
        x_ += static_cast<U>(rhs.x_);
        y_ += static_cast<U>(rhs.y_);
        return *this;
    }

    template<typename U>
    Point_impl<T>& operator-=(const Point_impl<U>& rhs) {
        x_ -= static_cast<U>(rhs.x_);
        y_ -= static_cast<U>(rhs.y_);
        return *this;
    }

    template<typename U>
    Point_impl<T>& operator*=(const Point_impl<U>& rhs) {
        x_ *= static_cast<U>(rhs.x_);
        y_ *= static_cast<U>(rhs.y_);
        return *this;
    }

    template<typename U>
    Point_impl<T>& operator/=(const Point_impl<U>& rhs) {
        x_ /= static_cast<U>(rhs.x_);
        y_ /= static_cast<U>(rhs.y_);
        return *this;
    }

    // for printing a point:
    friend std::ostream& operator<<(std::ostream& os, const Point_impl<T>& p) {
        return os << '(' << p.x_ << ',' << p.y_ << ')';
    }

private:
    T x_, y_;
};

然后可以像这样完成使用不同底层类型操作的自由函数:

template<typename L, typename R>
auto operator+(const Point_impl<L>& lhs, const Point_impl<R>& rhs) {
    // return the properly promoted Point_impl type deduced from if the
    // underlying types were added
    Point_impl<decltype(lhs.get_x() + rhs.get_x())> rv = lhs;
    rv += rhs;
    return rv;
}

template<typename L, typename R>
auto operator-(const Point_impl<L>& lhs, const Point_impl<R>& rhs) {
    Point_impl<decltype(lhs.get_x() - rhs.get_x())> rv = lhs;
    rv -= rhs;
    return rv;
}

template<typename L, typename R>
auto operator*(const Point_impl<L>& lhs, const Point_impl<R>& rhs) {
    Point_impl<decltype(lhs.get_x() * rhs.get_x())> rv = lhs;
    rv *= rhs;
    return rv;
}

template<typename L, typename R>
auto operator/(const Point_impl<L>& lhs, const Point_impl<R>& rhs) {
    Point_impl<decltype(lhs.get_x() / rhs.get_x())> rv = lhs;
    rv /= rhs;
    return rv;
}

为方便起见,您还可以添加别名:

using Point = Point_impl<int>;
using Pointl = Point_impl<long>;
using Pointf = Point_impl<float>;
using Pointd = Point_impl<double>;
using Pointld = Point_impl<long double>;

例子:

#include <type_traits>

int main()
{
    Point x(1,2);             // Point_impl<int>
    Pointf y(3.141f,6.282f);  // Point_impl<float>
    auto z = x + y;           // int + float => Point_impl<float>

    std::cout << std::is_same<decltype(z), Pointf>::value << '\n';  // prints 1
    std::cout << z << '\n';                                         // (4.141,8.282)
}

推荐阅读