C++ - 在模板中复制赋值运算符
C++ - Copy Assignment Operator in Template
我正在尝试重载模板结构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}
为什么?
它给了我无限的输出
为什么?
由于已根据函数本身定义了函数,因此请参阅以下代码注释。
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;
}
你的行
*this = that;
也是一个赋值,需要两个参数。并且两者都是xpair<First,Second>
,所以它再次调用同一个运算符。
您可能想做的是:
this->first = that.first;
this->second = that.second;
它调用 First
和 Second
的赋值运算符。
正如其他人所指出的,您的问题是您的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的东西有点晦涩难懂,但它确保这个免费函数只会在真正的 xpair 上调用。
现在您的运算符 = 只是:
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
添加更多内容,并且它由所有其他方法自动处理。
相关文章:
- CRTP 中的复制赋值运算符 - gcc vs clang 和 msvc
- 为什么基类中的复制和交换会导致派生类中的复制赋值运算符被隐式删除?
- 在c++中重载复制赋值运算符
- 复制构造函数和复制赋值运算符是否应具有相同的语句?
- 移动赋值运算符与复制赋值运算符
- Gcc 使用 memcpy 作为隐式复制赋值运算符,而不是成员复制
- 如何在没有复制赋值运算符的情况下交换两个对象
- 模拟 C++ 中 lambda 的复制赋值运算符
- 重载复制赋值运算符
- 为什么C++编译器会创建复制构造函数和复制赋值运算符
- 默认的复制构造函数和复制赋值运算符给出奇怪的错误
- 重载运算符 = 返回 void 是否不可能成为复制赋值运算符
- 了解复制构造函数和复制赋值运算符
- 重载全常量类型的复制赋值运算符的正确方法是什么?
- 是具有复制和交换习惯用法的复制赋值运算符,建议进行自赋值检查
- 删除复制构造函数或复制赋值运算符算"user declared"吗?
- 为什么我们需要删除复制赋值运算符中的指针
- 重载非类型模板结构的成员结构的复制赋值运算符
- clang-libc++错误:重载解析选择了隐式删除的复制赋值运算符
- C++移动语义:为什么调用复制赋值运算符=(&)而不是移动赋值运算符=(&&)?