C ++ - 模板中的复制赋值运算符

时间:2016-02-09 02:18:01

标签: c++ templates

我试图在模板结构xpair

中重载复制赋值运算符
template <typename First, typename Second>
struct xpair {
   First first{};
   Second second{};

   xpair(){}
   xpair (const First& first, const Second& second):
           first(first), second(second) {}


   xpair& operator= (const xpair& that) {
      cout << "*this = " << *this << "      " << "that = " << that << endl;
      cout << "use operator = " << endl;
      *this = that;
      return *this;
   }
};

但是当我用

测试这段代码时
using commend = string;
using str_str_pair = xpair<string, string>;
using commend_pair = xpair<commend, str_str_pair>;

commend_pair cmd_pair;
str_str_pair str_pair("a", "1");
commend cmd("comment");

cmd_pair.first = cmd;
cmd_pair.second = str_pair;

它给了我无限的输出

use operator = 
*this = {,}      that = {a,1}
use operator = 
*this = {,}      that = {a,1}
use operator = 
*this = {,}      that = {a,1}
use operator = 
*this = {,}      that = {a,1}

为什么?

3 个答案:

答案 0 :(得分:3)

  

它给了我无限的输出   
  那是为什么?

因为您已根据自身定义了该功能,请参阅以下代码注释。

xpair& operator= (const xpair& that)
{
    cout << "*this = " << *this << "      " << "that = " << that << endl;
    cout << "use operator = " << endl;

    // Here you're asking for `this` (i.e., an `xpair` type) to be assigned
    // a `that` (i.e., another `xpair` type) using the `operator=` which is
    // the function currently being implemented/defined. A function calling
    // itself is recursion and there is no stopping condition so it will
    // continue infinitely.
    *this = that;
    return *this;
}

相反,您的操作应使用this实例的数据成员设置that实例的数据成员。

xpair& operator= (const xpair& that)
{
    cout << "*this = " << *this << "      " << "that = " << that << endl;
    cout << "use operator = " << endl;

    first = that.first;
    second = that.second;
    return *this;
}

答案 1 :(得分:2)

你的行

  *this = that;

也是一个赋值,带有两个参数。两者都是xpair<First,Second>,因此它再次调用相同的运算符。

您可能想要做的是:

this->first = that.first;
this->second = that.second;

调用FirstSecond的赋值运算符。

答案 2 :(得分:2)

正如其他人所说,您的问题是operator=致电您的operator=。这会导致无限递归。

但是,我会争论不同的实现:

添加:

template<class Self,
  class=std::enable_if_t<std::is_same<std::decay_t<Self>, xpair>{}>
>
friend auto tieme(Self&& self) {
  return std::forward_as_tuple(
    std::forward<Self>(self).first,
    std::forward<Self>(self).second
  );
}

你身体的一部分。 enable_if_t的东西有点模糊,但它确保只在真正的xpairs上调用这个自由函数。

现在你的operator =只是:

xpair& operator= (const xpair& that) {
  tieme(*this)=tieme(that);
  return *this;
}

这很好,因为你不必重复两次元素的顺序。

但它并不止于此。

friend bool operator<(const xpair& lhs, const xpair& rhs) {
  return tieme(lhs) < tieme(rhs);
}

同样的技术可以让你编写一堆其他运算符。任何曾经在<样板中遇到错误的人都会明白上述情况很好。

移动分配?

xpair& operator= (xpair&& that) {
  tieme(*this)=tieme(std::move(that));
  return *this;
}

交换?

friend void swap(xpair& lhs, xpair& rhs) {
  std::swap( tieme(lhs), tieme(rhs) );
}

它会扩展 - 向tieme添加更多内容,并由所有其他方法自动处理。