首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >‘M C++11 operator+(M&&,M&&)’的过载

‘M C++11 operator+(M&&,M&&)’的过载
EN

Stack Overflow用户
提问于 2011-08-24 09:55:17
回答 2查看 903关注 0票数 3

更新:澄清、更清晰的焦点和缩短的示例:

  • 我能避免M op+(M&&,M&&) 的超载吗?假设,我想要处理好RValues?我想其他三个过载是必需的。

首先,我有(&&,&&)重载的原因:

  • 通常,我不会提供M op+(&&,&&),但我似乎需要它:当为(&&,&)(&,&&)提供重载时,编译器会陷入歧义。是否有更好的方法来解决这个问题然后添加另一个实现变体?

您还可以查看完成代码。

代码语言:javascript
复制
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;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-29 12:05:05

下面的助手函数如果是rvalue,则返回第一个值,否则返回第二个值(可能是rvalue,但可能不是)。

代码语言:javascript
复制
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); }     

下面的助手函数返回上面未返回的另一个值。

代码语言:javascript
复制
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。

代码语言:javascript
复制
template <class T1, class T2>
struct is_same_decay : public std::is_same<
  typename std::decay<T1>::type, 
  typename std::decay<T2>::type
> {};

然后,我们只需对每个函数执行一次重载(使用模板),如下所示:

代码语言:javascript
复制
// 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; 
}

注意,如果M1M2是rvalue,则get_rvalue(a, b)将返回rvalue,因此在本例中Matrix x将由移动填充,而不是副本。命名返回值优化可能会确保返回值不需要复制(甚至移动),因为x将在返回值的位置构建。

完整代码是这里

票数 2
EN

Stack Overflow用户

发布于 2011-08-24 10:33:43

代码语言:javascript
复制
Matrix& operator=(Matrix&& o) { swap(*this,o); };

首先,矩阵类(到目前为止)还没有任何需要移动的东西,因此您不应该费心编写一个。就像复制构造函数一样,只有在需要时才定义一个。让编译器来处理它,除非您有合法的需求(比如存储一个裸指针)。

第二,你的功能不动;它交换。一个基于“惯用”交换的操作涉及一个临时的,如:

代码语言:javascript
复制
Matrix temp;
swap(o, temp);
swap(temp, *this);
代码语言:javascript
复制
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); }

你在这里想做什么?同样,您的对象没有任何被移动的东西;这样做没有任何意义。仅仅因为你能移动一些东西并不意味着你应该。如果你真的想减少代码复制,你可以正常地做一些事情:

代码语言:javascript
复制
friend Matrix operator+(const Matrix &a, const Matrix &b) { Matrix temp = a + b; return temp; }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7173498

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档