自定义先决条件对移动分配运算符有效吗
Are custom preconditions valid for a move assignment operator?
在移动分配运算符中对移动目标的状态设置自定义先决条件是否有效?特别是,只允许移动到以前未完全初始化的对象是否有效?
考虑:
struct Foo {
private:
std::unique_ptr<int> value;
public:
Foo(std::unique_ptr<int> value) : value{std::move(value)} {}
Foo(Foo&&) noexcept = default;
Foo &operator =(Foo&& other) noexcept {
assert(!value);
value = std::move(other.value);
return *this;
}
};
例如,我想知道这个类是否可以在不影响断言的情况下与容器一起使用。例如,如果您这样做:
std::vector<Foo> foo;
foo.emplace_back(std::make_unique<int>(42));
foo.emplace_back(std::make_unique<int>(17));
Foo removed = std::move(foo[0]);
foo.erase(foo.begin());
这是否保证与类一起工作,还是依赖于std::vector
的实现细节?
在移动分配运算符中对移动目标的状态设置自定义先决条件有效吗?
是的,但是。。。
特别是,只允许移动到以前未完全初始化的对象是否有效?
当然,但是。。。
考虑:
到目前为止没有问题,但是。。。
std::vector<Foo> foo;
// ...
你可以对你的类做任何你想做的事情,直到你将它与std代码(或其他人的代码(一起使用,这会对你的类型提出要求。
例如,标准中关于vector::erase
:
对于
vector
和deque
,T
是Cpp17MoveAssignable。
此处定义了Cpp17MoveAssignable。
t = rv
rv
的状态未指定。[注意:无论t
和rv
是否引用同一对象,rv
都必须满足正在使用它的库组件的要求。无论rv
是否已从中移动,这些要求中列出的操作都必须按指定操作。--结束注意]
Foo
未完全满足Cpp17MoveAssignable要求。只要您不希望Foo
使用需要Cpp17MoveAssignable的代码,这就没问题。
免责声明:未来的标准可能会放宽对vector::erase
的要求,以允许Foo
。但今天的情况并非如此。
请注意,std::remove_if
也需要Cpp17MoveAssignable:
http://eel.is/c++草稿/算法删除#2
这个对你的程序的轻微修改实际上会断言:
#include <algorithm>
#include <cassert>
#include <memory>
#include <vector>
struct Foo {
private:
std::unique_ptr<int> value;
public:
Foo(std::unique_ptr<int> value) : value{std::move(value)} {}
Foo(Foo&&) noexcept = default;
Foo &operator =(Foo&& other) noexcept {
assert(!value);
value = std::move(other.value);
return *this;
}
bool operator==(int i) const {return *value == i;}
};
int
main()
{
std::vector<Foo> foo;
foo.push_back(std::make_unique<int>(1));
foo.push_back(std::make_unique<int>(2));
foo.push_back(std::make_unique<int>(3));
std::remove_if(foo.begin(), foo.end(),
[](auto const& f) {return f == 1;});
}
相关文章:
- 为什么比较运算符如此快速
- 自定义先决条件对移动分配运算符有效吗
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 我的运算符重载是否有效<<(流插入)左操作数不是 ostream
- 自定义类型转换运算符在转发引用上调用时不起作用(当对象按值传递时有效)
- 重载"+="运算符:c+=a_times_b 有效,但 c+=a*b 不起作用?
- 用于删除复制/移动分配运算符的有效签名
- 没有类减法运算符重载,但仍然有效
- C++ 运算符重载 += 有效,但<<不起作用
- “A a = A()”有效吗?下面调用了哪些运算符/方法
- 为什么在三元运算符的分支之间返回 lambda 对某些 lambda 有效?
- 三向比较运算符是否始终有效
- 如何有效地使用结构定义,包括来自另一个源文件的运算符
- 转换运算符在这种情况下有效吗
- ("!")运算符不是在任何地方都有效吗?
- 为什么重载运算符<<有时有效,但有时不起作用
- 后递增和预递增运算符是否比普通"+"运算符更有效?
- 实现用于<<的有界字符串格式运算符的有效方法?
- C++中的有效向量运算符/对临时对象的引用
- 为什么C++ 'new'运算符的这种实现有效?