Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 7 additions & 38 deletions libcxx/include/map
Original file line number Diff line number Diff line change
Expand Up @@ -972,31 +972,15 @@ public:

_LIBCPP_HIDE_FROM_ABI map(const map& __m) : __tree_(__m.__tree_) { insert(__m.begin(), __m.end()); }

_LIBCPP_HIDE_FROM_ABI map& operator=(const map& __m) {
# ifndef _LIBCPP_CXX03_LANG
__tree_ = __m.__tree_;
# else
if (this != std::addressof(__m)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me that before/after are equivalent in non-C++03 mode -- can you explain why they are?

Also, I had played around this area in https://reviews.llvm.org/D121485 (which never landed), can you take a look and ensure that concerns back then don't apply to this? Finally, can you benchmark before/after? In principle, we shouldn't see a difference IIUC?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me that before/after are equivalent in non-C++03 mode -- can you explain why they are?

__tree_ is the only member of map, so the compiler-generated code just calls the assignment operator of __tree_.

Also, I had played around this area in https://reviews.llvm.org/D121485 (which never landed), can you take a look and ensure that concerns back then don't apply to this?

I guess Mark's comment in map, line 1902, is relevant here, but I don't think the concern is correct. We're calling __tree::clear() if we assign a new allocator and reuse the old nodes oterwise.

Finally, can you benchmark before/after?

I haven't benchmarked, but I have looked at the code gen before landing the patch, which was identical (even at -O0). Is that good enough?

In principle, we shouldn't see a difference IIUC?

Correct.

__tree_.clear();
__tree_.value_comp() = __m.__tree_.value_comp();
__tree_.__copy_assign_alloc(__m.__tree_);
insert(__m.begin(), __m.end());
}
# endif
return *this;
}
_LIBCPP_HIDE_FROM_ABI map& operator=(const map& __m) = default;

# ifndef _LIBCPP_CXX03_LANG

_LIBCPP_HIDE_FROM_ABI map(map&& __m) noexcept(is_nothrow_move_constructible<__base>::value)
: __tree_(std::move(__m.__tree_)) {}
_LIBCPP_HIDE_FROM_ABI map(map&& __m) noexcept(is_nothrow_move_constructible<__base>::value) = default;

_LIBCPP_HIDE_FROM_ABI map(map&& __m, const allocator_type& __a);

_LIBCPP_HIDE_FROM_ABI map& operator=(map&& __m) noexcept(is_nothrow_move_assignable<__base>::value) {
__tree_ = std::move(__m.__tree_);
return *this;
}
_LIBCPP_HIDE_FROM_ABI map& operator=(map&& __m) noexcept(is_nothrow_move_assignable<__base>::value) = default;

_LIBCPP_HIDE_FROM_ABI map(initializer_list<value_type> __il, const key_compare& __comp = key_compare())
: __tree_(__vc(__comp)) {
Expand Down Expand Up @@ -1659,31 +1643,16 @@ public:
insert(__m.begin(), __m.end());
}

_LIBCPP_HIDE_FROM_ABI multimap& operator=(const multimap& __m) {
# ifndef _LIBCPP_CXX03_LANG
__tree_ = __m.__tree_;
# else
if (this != std::addressof(__m)) {
__tree_.clear();
__tree_.value_comp() = __m.__tree_.value_comp();
__tree_.__copy_assign_alloc(__m.__tree_);
insert(__m.begin(), __m.end());
}
# endif
return *this;
}
_LIBCPP_HIDE_FROM_ABI multimap& operator=(const multimap& __m) = default;

# ifndef _LIBCPP_CXX03_LANG

_LIBCPP_HIDE_FROM_ABI multimap(multimap&& __m) noexcept(is_nothrow_move_constructible<__base>::value)
: __tree_(std::move(__m.__tree_)) {}
_LIBCPP_HIDE_FROM_ABI multimap(multimap&& __m) noexcept(is_nothrow_move_constructible<__base>::value) = default;

_LIBCPP_HIDE_FROM_ABI multimap(multimap&& __m, const allocator_type& __a);

_LIBCPP_HIDE_FROM_ABI multimap& operator=(multimap&& __m) noexcept(is_nothrow_move_assignable<__base>::value) {
__tree_ = std::move(__m.__tree_);
return *this;
}
_LIBCPP_HIDE_FROM_ABI multimap&
operator=(multimap&& __m) noexcept(is_nothrow_move_assignable<__base>::value) = default;

_LIBCPP_HIDE_FROM_ABI multimap(initializer_list<value_type> __il, const key_compare& __comp = key_compare())
: __tree_(__vc(__comp)) {
Expand Down
16 changes: 4 additions & 12 deletions libcxx/include/set
Original file line number Diff line number Diff line change
Expand Up @@ -662,14 +662,10 @@ public:

_LIBCPP_HIDE_FROM_ABI set(const set& __s) : __tree_(__s.__tree_) { insert(__s.begin(), __s.end()); }

_LIBCPP_HIDE_FROM_ABI set& operator=(const set& __s) {
__tree_ = __s.__tree_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI set& operator=(const set& __s) = default;

# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI set(set&& __s) noexcept(is_nothrow_move_constructible<__base>::value)
: __tree_(std::move(__s.__tree_)) {}
_LIBCPP_HIDE_FROM_ABI set(set&& __s) noexcept(is_nothrow_move_constructible<__base>::value) = default;
# endif // _LIBCPP_CXX03_LANG

_LIBCPP_HIDE_FROM_ABI explicit set(const allocator_type& __a) : __tree_(__a) {}
Expand Down Expand Up @@ -1129,14 +1125,10 @@ public:
insert(__s.begin(), __s.end());
}

_LIBCPP_HIDE_FROM_ABI multiset& operator=(const multiset& __s) {
__tree_ = __s.__tree_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI multiset& operator=(const multiset& __s) = default;

# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI multiset(multiset&& __s) noexcept(is_nothrow_move_constructible<__base>::value)
: __tree_(std::move(__s.__tree_)) {}
_LIBCPP_HIDE_FROM_ABI multiset(multiset&& __s) noexcept(is_nothrow_move_constructible<__base>::value) = default;

_LIBCPP_HIDE_FROM_ABI multiset(multiset&& __s, const allocator_type& __a);
# endif // _LIBCPP_CXX03_LANG
Expand Down
Loading