重载加法运算符时的代码重复

Code duplication when overloading addition operator

本文关键字:代码 运算符 重载      更新时间:2023-10-16

让我们以一个表示间隔的简单类为例。我希望它支持以下操作:

int main()
{
    Interval<double> i1(1, 2);
    Interval<double> i2(3, 4);
    i1   + 1.0;
    1.0  + i1;
    i1   + 1.0f;
    1.0f + i1;
    i1   + 1;
    1    + i1;
    i1   + i2;
}

一个可能的实现是

template<typename Real>
class Interval
{
public:
    Interval(Real value)
        : lower(value), upper(value)
    { }
    template<typename Real2>
    Interval(Real2 value)
        : lower(value), upper(value)
    { }
    template<typename Real2>
    Interval(Real2 l, Real2 u)
        : lower(l), upper(u)
    { }
    Interval<Real>& operator += (Interval<Real> rhs)
    {
        lower += rhs.lower;
        upper += rhs.upper;
        return *this;
    }
private:
    Real lower, upper;
};
template<typename Real>
const Interval<Real> operator + (Interval<Real> i1, const Interval<Real>& i2)
{
    i1 += i2;
    return i1;
}
template<typename Real1, typename Real2>
const Interval<Real1> operator + (Interval<Real1> i1, const Real2& r2)
{
    i1 += r2;
    return i1;
}
template<typename Real1, typename Real2>
const Interval<Real2> operator + (const Real1& r1, Interval<Real2> i2)
{
    i2 += r1;
    return i2;
}

这有一些代码重复。有没有更"经济"的实施方法?什么是最佳实践?

您可以通过在Interval中提供一个构造函数来减少重载函数的数量,该构造函数只接受Real类型的一个参数。

那么,你所需要实现的就是:

template <typename Real>
Interval<Real> operator+(Interval<Real> const& lhs, Interval<Real> const& rhs)

如果有一个成员函数:

Interval operator + (const Interval& i2)
{
   Interval<Real> i1 = *this; 
   i1 += i2;
   return i1;
}

,然后,我可以编译:

Interval<double> i1(1, 2);
Interval<double> i2(3, 4);
std::cout << (i1 + i2) << std::endl;
std::cout << (i1 + 1.0) << std::endl;
std::cout << (i1 + 1.0f) << std::endl;
std::cout << (i1 + 1) << std::endl;

但是如果我有一个自由函数:

template<typename Real>
Interval<Real> operator + (Interval<Real> i1, const Interval<Real>& i2)
{
    i1 += i2;
    return i1;
}
然后,我得到编译器错误:
std::cout << (i1 + 1.0) << std::endl;
std::cout << (i1 + 1.0f) << std::endl;
std::cout << (i1 + 1) << std::endl;

我不知道为什么会这样。

更新2

多亏了@MooingDuck,很清楚为什么自由函数不起作用,而成员函数可以工作。

作为成员函数,没有模板演绎,因此需要转换。作为一个自由函数,有模板扣除,它禁止用户转换。