-
Notifications
You must be signed in to change notification settings - Fork 1.6k
<flat_set>: the copy/move functions should be user-defined
#4079
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6251a9e
7d0255f
6ea7610
69efd7e
fe69fe0
dacb461
3ce3399
55ce5a0
0f13dcb
ffcbd64
dce6c91
8bb7bc0
a6659c9
8de2226
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,12 +67,12 @@ public: | |
|
|
||
| _Base_flat_set() : _Mycont(), _Mycomp() {} | ||
|
|
||
| // TRANSITION, "_Mycomp" may need to be copied, even in move construction / assignment. | ||
| template <_Allocator_for<container_type> _Alloc> | ||
| _Base_flat_set(const _Deriv& _Set, const _Alloc& _Al) : _Mycont(_Set._Mycont, _Al), _Mycomp(_Set._Mycomp) {} | ||
| template <_Allocator_for<container_type> _Alloc> | ||
| _Base_flat_set(_Deriv&& _Set, const _Alloc& _Al) | ||
| : _Mycont(_STD move(_Set._Mycont), _Al), _Mycomp(_STD move(_Set._Mycomp)) {} | ||
| : _Mycont(_STD move(_Set).extract(), _Al), _Mycomp(_Set._Mycomp) // intentionally copy comparator, see LWG-2227 | ||
| {} | ||
|
|
||
| explicit _Base_flat_set(container_type _Cont, const key_compare& _Comp = key_compare()) | ||
| : _Mycont(_STD move(_Cont)), _Mycomp(_Comp) { | ||
|
|
@@ -153,6 +153,32 @@ public: | |
| _Base_flat_set(_Tsorted _Tsort, initializer_list<_Kty> _Ilist, const _Alloc& _Al) | ||
| : _Base_flat_set(_Tsort, container_type(_Ilist, _Al)) {} | ||
|
|
||
| _Base_flat_set(const _Base_flat_set&) = default; | ||
| _Base_flat_set(_Base_flat_set&& _Other) noexcept( | ||
| is_nothrow_move_constructible_v<container_type>&& is_nothrow_copy_constructible_v<key_compare>) // strengthened | ||
| : _Mycont(_STD move(_Other).extract()), _Mycomp(_Other._Mycomp) // intentionally copy comparator, see LWG-2227 | ||
|
achabense marked this conversation as resolved.
|
||
| {} | ||
|
|
||
| _Base_flat_set& operator=(const _Base_flat_set& _Other) { | ||
| _Clear_guard<_Base_flat_set> _Guard{this}; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Though not necessary, I think it looks strange that move-assignment has address checking, while this doesn't have :| |
||
| _Mycont = _Other._Mycont; | ||
| _Mycomp = _Other._Mycomp; | ||
| _Guard._Target = nullptr; | ||
| return *this; | ||
| } | ||
| _Base_flat_set& operator=(_Base_flat_set&& _Other) noexcept( | ||
| is_nothrow_move_assignable_v<container_type>&& is_nothrow_copy_assignable_v<key_compare>) // strengthened | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, added. (I'm adding
I think there is no need to introduce a copy wrapper, as they are solely for defaulting the functions, but the defaulted functions are not capable to deal with a lot of invariant-breaking cases.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think sometimes exposition only non-static data members are considered completely specifying the behavior of the implicitly declared or explicitly defaulted special member functions, e.g. for many However, it's unfortunately underspecified whether non-static data members are considered complete. It seems permitted for implementations to add "evil" subobjects that weaken defaulted exception specifications. Per [functions.within.classes], I think the standard currently implicitly requires that the copy/move operations are effectively defaulted and are able to break invariants. We should report an LWG issue that makes copy/move functions explicitly specified. I believe we should say |
||
| { | ||
| if (this != _STD addressof(_Other)) { | ||
| _Clear_guard<_Base_flat_set> _Guard{this}; | ||
| _Clear_guard<_Base_flat_set> _Always_clear{_STD addressof(_Other)}; | ||
| _Mycont = _STD move(_Other._Mycont); | ||
| _Mycomp = _Other._Mycomp; // intentionally copy comparator, see LWG-2227 | ||
| _Guard._Target = nullptr; | ||
| } | ||
| return *this; | ||
| } | ||
|
|
||
| _Deriv& operator=(initializer_list<_Kty> _Ilist) { | ||
| _Clear_guard<_Base_flat_set> _Guard{this}; | ||
| _Mycont.assign(_Ilist); | ||
|
|
@@ -288,7 +314,7 @@ public: | |
| _NODISCARD container_type extract() && noexcept( | ||
| is_nothrow_move_constructible_v<container_type>) /* strengthened */ { | ||
| // always clears the container (N4950 [flat.set.modifiers]/14 and [flat.multiset.modifiers]/10) | ||
| _Clear_guard<_Base_flat_set> _Guard{this}; | ||
| _Clear_guard<_Base_flat_set> _Always_clear{this}; | ||
| return _STD move(_Mycont); | ||
| } | ||
| void replace(container_type&& _Cont) { | ||
|
|
@@ -711,7 +737,12 @@ private: | |
|
|
||
| public: | ||
| using _Mybase::_Mybase; | ||
| flat_set(const flat_set&) = default; | ||
| flat_set(flat_set&&) = default; | ||
|
|
||
| using _Mybase::operator=; | ||
| flat_set& operator=(const flat_set&) = default; | ||
| flat_set& operator=(flat_set&&) = default; | ||
| }; | ||
|
|
||
| _EXPORT_STD template <class _Kty, class _Keylt = less<_Kty>, class _Container = vector<_Kty>> | ||
|
|
@@ -722,7 +753,12 @@ private: | |
|
|
||
| public: | ||
| using _Mybase::_Mybase; | ||
| flat_multiset(const flat_multiset&) = default; | ||
| flat_multiset(flat_multiset&&) = default; | ||
|
|
||
| using _Mybase::operator=; | ||
| flat_multiset& operator=(const flat_multiset&) = default; | ||
| flat_multiset& operator=(flat_multiset&&) = default; | ||
| }; | ||
|
|
||
| _EXPORT_STD template <class _Kty, class _Keylt, class _Container, class _Pred> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unlike
_Base_flat_set(_Base_flat_set&& _Other), thisextract()might cause unwanted materialization...