更新:澄清、更清晰的焦点和缩短的示例:
M op+(M&&,M&&) 的超载吗?假设,我想要处理好RValues?我想其他三个过载是必需的。首先,我有(&&,&&)重载的原因:
M op+(&&,&&),但我似乎需要它:当为(&&,&)和(&,&&)提供重载时,编译器会陷入歧义。是否有更好的方法来解决这个问题然后添加另一个实现变体?您还可以查看完成代码。
struct Matrix {
...
// 2ary ops
friend Matrix operator+(const Matrix &a, Matrix &&b ) { b+=a; return move(b); }
friend Matrix operator+(Matrix &&a, const Matrix &b) { a+=b; return move(a); }
friend Matrix operator+(const Matrix &a, Matrix v) { v+=a; return v; }
friend Matrix operator+(Matrix &&a, Matrix &&b) { a+=b; return move(a); }
// ... same for operator*
// ... assume impl of operator+=,*= and move semantics
};
int main() {
Matrix a{2},b{3},c{4},d{5};
Matrix x = a*b + c*d; // reuires &&,&& overload
std::cout << x << std::endl;
}发布于 2011-08-29 12:05:05
下面的助手函数如果是rvalue,则返回第一个值,否则返回第二个值(可能是rvalue,但可能不是)。
template <class T1, class T2>
typename std::enable_if<! std::is_reference<T1>::value, T1&&>::type
get_rvalue(T1&& t1, T2&& t2) { return std::forward<T1>(t1); }
template <class T1, class T2>
typename std::enable_if<std::is_reference<T1>::value, T2&&>::type
get_rvalue(T1&& t1, T2&& t2) { return std::forward<T2>(t2); } 下面的助手函数返回上面未返回的另一个值。
template <class T1, class T2>
typename std::enable_if<! std::is_reference<T1>::value, T1&&>::type
get_non_rvalue(T1&& t1, T2&& t2) { return std::forward<T2>(t2); }
template <class T1, class T2>
typename std::enable_if<std::is_reference<T1>::value, T2&&>::type
get_non_rvalue(T1&& t1, T2&& t2) { return std::forward<T1>(t1); }这只是比较如果两种类型是相同的,忽略引用和const。
template <class T1, class T2>
struct is_same_decay : public std::is_same<
typename std::decay<T1>::type,
typename std::decay<T2>::type
> {};然后,我们只需对每个函数执行一次重载(使用模板),如下所示:
// 2ary ops
template <class M1, class M2>
friend typename std::enable_if<
is_same_decay<M1, Matrix>::value &&
is_same_decay<M2, Matrix>::value,
Matrix>::type
operator+(M1&& a, M2&& b)
{
Matrix x = get_rvalue(std::forward<M1>(a), std::forward<M2>(b));
x += get_non_rvalue(std::forward<M1>(a), std::forward<M2>(b));
return x;
}
template <class M1, class M2>
friend typename std::enable_if<
is_same_decay<M1, Matrix>::value &&
is_same_decay<M2, Matrix>::value,
Matrix>::type
operator*(M1&& a, M2&& b)
{
Matrix x = get_rvalue(std::forward<M1>(a), std::forward<M1>(b));
x *= get_non_rvalue(std::forward<M1>(a), std::forward<M1>(b));
return x;
}注意,如果M1或M2是rvalue,则get_rvalue(a, b)将返回rvalue,因此在本例中Matrix x将由移动填充,而不是副本。命名返回值优化可能会确保返回值不需要复制(甚至移动),因为x将在返回值的位置构建。
完整代码是这里。
发布于 2011-08-24 10:33:43
Matrix& operator=(Matrix&& o) { swap(*this,o); };首先,矩阵类(到目前为止)还没有任何需要移动的东西,因此您不应该费心编写一个。就像复制构造函数一样,只有在需要时才定义一个。让编译器来处理它,除非您有合法的需求(比如存储一个裸指针)。
第二,你的功能不动;它交换。一个基于“惯用”交换的操作涉及一个临时的,如:
Matrix temp;
swap(o, temp);
swap(temp, *this);friend Matrix operator+(const Matrix &a, Matrix &&b ) { b+=a; return move(b); }
friend Matrix operator+(Matrix &&a, const Matrix &b) { a+=b; return move(a); }
friend Matrix operator+(const Matrix &a, Matrix v) { v+=a; return v; }
friend Matrix operator+(Matrix &&a, Matrix &&b) { a+=b; return move(a); }你在这里想做什么?同样,您的对象没有任何被移动的东西;这样做没有任何意义。仅仅因为你能移动一些东西并不意味着你应该。如果你真的想减少代码复制,你可以正常地做一些事情:
friend Matrix operator+(const Matrix &a, const Matrix &b) { Matrix temp = a + b; return temp; }https://stackoverflow.com/questions/7173498
复制相似问题