在C ++中,有没有办法通过移动语义减少成员函数的数量?

时间:2017-02-20 12:55:52

标签: c++ move-semantics sfinae

我正在尝试写我的vec课程。为了提高效率,我使用移动语义。

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;
}

感谢轨道中的轻盈竞赛提醒。我将移动构造函数添加到上面的代码中。

1。有没有办法为一个操作员编写较少的函数?

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

的混淆

1 个答案:

答案 0 :(得分:2)

当我为算术类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;
}

在课堂外提供以下两个功能:

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
}

在课堂外提供以下两个功能:

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现在只需要使用-O3operator-相同)中的单个复制构造函数:

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

即使两个操作数都是rvalues的情况也是在没有歧义的情况下处理的。以下编译正常,即使需要两份副本(a1+a2一份和a3+a4一份):

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