在 C++ 中,有什么方法可以减少具有移动语义的成员函数的数量吗?

In C++, is there any way to reduce the number of member functions with move semantics?

我正在尝试编写我的 vec class。为了效率,我使用移动语义。

Vec<int> v1;
Vec<int> v2;
Vec<int> v3;
Vec<int> v4;
v4 = v1 + v2;                   // Line 1
v4 = v1 + v2 + v3;              // Line 2
v4 = v1 + (v2 + v3);            // Line 3

但是,为了让上面的每一行只调用一次复制构造函数,我必须用一个运算符重载四个函数。喜欢下面的代码。

Vec(Myself&& v) 
{    // move consturctor
    dim = v.dim;
    value = std::move(v.value);
}

Myself& operator+= (const Myself& v)
{
    for (size_type i = 0; i < dim; ++i) (*this)[i] += v[i];
    return *this;
}

template<typename std::enable_if<!std::is_reference<Myself>::value>::type* = nullptr>   // SFINAE
friend Myself& operator+ (Myself&& a, const Myself& b)
{
    return a += b;
}

Myself& operator+ (Myself&& v) const
{
    return v += *this;
}

Myself operator+ (const Myself& v) const
{
    Myself ansV(*this);
    ansV += v;
    return ansV;
}

感谢Lightness Races in Orbit的提醒。我在上面的代码中添加了移动构造函数。

1.有什么办法可以少写一个算子的函数吗?

2。为什么在 friend Myself& operator+ (Myself&& a, const Myself& b) 函数中添加 SFINAE,而不是 Myself& operator+ (Myself&& v) const?用于修复v4 = v1 + (v2 + v3);.

的混淆

当我为算术 class T 编写运算符时,我通常会执行以下操作:

(a) 如果操作是可交换的(a+b 等于 b+a):

+=的实现放入T:

T & T::operator+=(T const& other) {
    // [Perform the actual operation (add other to *this)]
    x += other.x; // or something similar
    return *this;
}

在class之外提供以下两个函数:

T operator+(T a, T const& b) {
    a += b;
    return a;
}

T operator+(T const& a, T && b) {
    MyInt temp(std::move(b));
    temp += a;
    return temp;
}

(b) 如果操作不可交换(a-b 不同于 b-a):

-= 的实现放入 T 并提供第二个函数,该函数作用于第二个操作数而不是第一个:

T & T::operator-=(T const& other) {
    // [Perform the actual operation of (subtract other from *this)]
    x -= other.x; // or something similar
    return *this;
}

void T::operatorMinus(T & other) const {
    // [Perform the actual operation, but work on other instead of *this]
    other.x = x - other.x; // or something similar
}

在class之外提供以下两个函数:

T operator-(T a, T const& b) {
    a -= b;
    return a;
}

T operator-(T const& a, T && b) {
    MyInt temp(std::move(b));
    a.operatorMinus(temp);
    return temp;
}

结果:

在以下示例中,gcc 和 clang 现在只需要一个复制构造函数,使用 -O3(与 operator- 相同):

T a1, a2, a3, x;
x = a1 + a2;
x = a1 + a2 + a3;
x = (a1 + a2) + a3;
x = a1 + (a2 + a3);

即使两个操作数都是右值的情况也可以毫无歧义地处理。以下编译正常,即使需要两份(a1+a2 一份,a3+a4 一份):

T a1, a2, a3, a4, x;
x = (a1 + a2) + (a3 + a4);