diff --git a/stl/inc/flat_set b/stl/inc/flat_set index dda412494cd..c231affaad2 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -16,6 +16,13 @@ _EMIT_STL_WARNING(STL4038, "The contents of are available only with C #include #include +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + _STD_BEGIN template @@ -58,10 +65,17 @@ public: static_assert(random_access_iterator, "The C++ Standard forbids containers without random " "access iterators from being adapted. See [flatset.overview]."); - _Base_flat_set() : _My_pair(_Zero_then_variadic_args_t{}, _Keylt()) {} + _Base_flat_set() : _My_pair(_Zero_then_variadic_args_t{}) {} + + template <_Allocator_for _Alloc> + _Base_flat_set(const _Deriv& _Set, const _Alloc& _Al) + : _My_pair(_One_then_variadic_args_t{}, _Set._Get_comp(), _Set._Get_cont(), _Al) {} + template <_Allocator_for _Alloc> + _Base_flat_set(_Deriv&& _Set, const _Alloc& _Al) + : _My_pair(_One_then_variadic_args_t{}, _STD move(_Set._Get_comp()), _STD move(_Set._Get_cont()), _Al) {} explicit _Base_flat_set(container_type _Cont, const key_compare& _Comp = key_compare()) - : _My_pair(_One_then_variadic_args_t{}, _STD move(_Cont), _Comp) { + : _My_pair(_One_then_variadic_args_t{}, _Comp, _STD move(_Cont)) { _Make_invariants_fulfilled(); } template <_Allocator_for _Alloc> @@ -71,7 +85,7 @@ public: : _Base_flat_set(container_type(_Cont, _Al), _Comp) {} _Base_flat_set(_Tsorted, container_type _Cont, const key_compare& _Comp = key_compare()) - : _My_pair(_One_then_variadic_args_t{}, _STD move(_Cont), _Comp) { + : _My_pair(_One_then_variadic_args_t{}, _Comp, _STD move(_Cont)) { _Assert_after_sorted_input(); } template <_Allocator_for _Alloc> @@ -81,11 +95,11 @@ public: _Base_flat_set(_Tsorted _Tsort, const container_type& _Cont, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(_Tsort, container_type(_Cont, _Al), _Comp) {} - explicit _Base_flat_set(const key_compare& _Comp) : _My_pair(_Zero_then_variadic_args_t{}, _Comp) {} + explicit _Base_flat_set(const key_compare& _Comp) : _My_pair(_One_then_variadic_args_t{}, _Comp) {} template <_Allocator_for _Alloc> - _Base_flat_set(const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(_Comp, container_type(_Al)) {} + _Base_flat_set(const key_compare& _Comp, const _Alloc& _Al) : _My_pair(_One_then_variadic_args_t{}, _Comp, _Al) {} template <_Allocator_for _Alloc> - explicit _Base_flat_set(const _Alloc& _Al) : _Base_flat_set(container_type(_Al)) {} + explicit _Base_flat_set(const _Alloc& _Al) : _My_pair(_Zero_then_variadic_args_t{}, _Al) {} template _Base_flat_set(_Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) @@ -97,11 +111,14 @@ public: _Base_flat_set(_Iter _First, _Iter _Last, const _Alloc& _Al) : _Base_flat_set(container_type(_First, _Last, _Al)) {} template <_Container_compatible_range<_Kty> _Rng> - _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp = key_compare()) - : _Base_flat_set(container_type(from_range, _STD forward<_Rng>(_Range)), _Comp) {} + _Base_flat_set(from_range_t, _Rng&& _Range) + : _Base_flat_set(container_type(from_range, _STD forward<_Rng>(_Range))) {} template <_Container_compatible_range<_Kty> _Rng, _Allocator_for _Alloc> _Base_flat_set(from_range_t, _Rng&& _Range, const _Alloc& _Al) : _Base_flat_set(container_type(from_range, _STD forward<_Rng>(_Range), _Al)) {} + template <_Container_compatible_range<_Kty> _Rng> + _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp) + : _Base_flat_set(container_type(from_range, _STD forward<_Rng>(_Range)), _Comp) {} template <_Container_compatible_range<_Kty> _Rng, _Allocator_for _Alloc> _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(container_type(from_range, _STD forward<_Rng>(_Range), _Al), _Comp) {} @@ -117,7 +134,7 @@ public: : _Base_flat_set(_Tsort, container_type(_First, _Last, _Al)) {} _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) - : _Base_flat_set(_Ilist.begin(), _Ilist.end(), _Comp) {} + : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end()), _Comp) {} template <_Allocator_for _Alloc> _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} @@ -126,7 +143,7 @@ public: : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} _Base_flat_set(_Tsorted _Tsort, initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) - : _Base_flat_set(_Tsort, _Ilist.begin(), _Ilist.end(), _Comp) {} + : _Base_flat_set(_Tsort, container_type(_Ilist.begin(), _Ilist.end()), _Comp) {} template <_Allocator_for _Alloc> _Base_flat_set(_Tsorted _Tsort, initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(_Tsort, container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} @@ -135,11 +152,12 @@ public: : _Base_flat_set(_Tsort, container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} _Deriv& operator=(initializer_list<_Kty> _Ilist) { - _Get_cont() = container_type(_Ilist.begin(), _Ilist.end()); + _Get_cont().assign(_Ilist.begin(), _Ilist.end()); _Make_invariants_fulfilled(); return static_cast<_Deriv&>(*this); } + // iterators _NODISCARD iterator begin() noexcept { return _Get_cont().begin(); } @@ -152,6 +170,7 @@ public: _NODISCARD const_iterator end() const noexcept { return _Get_cont().end(); } + _NODISCARD reverse_iterator rbegin() noexcept { return _Get_cont().rbegin(); } @@ -164,6 +183,7 @@ public: _NODISCARD const_reverse_iterator rend() const noexcept { return _Get_cont().rend(); } + _NODISCARD const_iterator cbegin() const noexcept { return _Get_cont().cbegin(); } @@ -177,6 +197,7 @@ public: return _Get_cont().crend(); } + // capacity _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _Get_cont().empty(); } @@ -187,33 +208,36 @@ public: return _Get_cont().max_size(); } + // modifiers template auto emplace(_Args&&... _Vals) { - insert<_Kty>(_Kty{_STD forward<_Args>(_Vals)...}); + constexpr bool _Is_key_type = _In_place_key_extract_set<_Kty, remove_cvref_t<_Args>...>::_Extractable; + if constexpr (_Is_key_type) { + return _Emplace(_STD forward<_Args>(_Vals)...); + } else { + return _Emplace(_Kty{_STD forward<_Args>(_Vals)...}); + } } - template iterator emplace_hint(const_iterator _Hint, _Args&&... _Vals) { - return _Emplace_hint(_Hint, _Kty{_STD forward<_Args>(_Vals)...}); + constexpr bool _Is_key_type = _In_place_key_extract_set<_Kty, remove_cvref_t<_Args>...>::_Extractable; + if constexpr (_Is_key_type) { + return _Emplace_hint(_Hint, _STD forward<_Args>(_Vals)...); + } else { + return _Emplace_hint(_Hint, _Kty{_STD forward<_Args>(_Vals)...}); + } } auto insert(const value_type& _Val) { - return _Insert<_Kty>(_Val); + return _Emplace(_Val); } auto insert(value_type&& _Val) { - return _Insert(_STD move(_Val)); + return _Emplace(_STD move(_Val)); } - template requires (!_Multi && _Keylt_transparent && is_constructible_v<_Kty, _Other>) auto insert(_Other&& _Val) { - return _Insert(_STD forward<_Other>(_Val)); - } - - template - requires (!_Multi && _Keylt_transparent && is_constructible_v<_Kty, _Other>) - iterator insert(const_iterator _Hint, _Other&& _Val) { - return _Emplace_hint(_Hint, _STD forward<_Other>(_Val)); + return _Emplace(_STD forward<_Other>(_Val)); } iterator insert(const_iterator _Hint, const value_type& _Val) { @@ -222,17 +246,20 @@ public: iterator insert(const_iterator _Hint, value_type&& _Val) { return _Emplace_hint(_Hint, _STD move(_Val)); } + template + requires (!_Multi && _Keylt_transparent && is_constructible_v<_Kty, _Other>) + iterator insert(const_iterator _Hint, _Other&& _Val) { + return _Emplace_hint(_Hint, _STD forward<_Other>(_Val)); + } template - void insert(const _Iter& _First, const _Iter& _Last) { + void insert(_Iter _First, _Iter _Last) { _Insert_range(_First, _Last); } - template void insert(_Tsorted, _Iter _First, _Iter _Last) { _Insert_range(_First, _Last); } - template <_Container_compatible_range<_Kty> _Rng> void insert_range(_Rng&& _Range) { const size_type _Old_size = size(); @@ -240,14 +267,18 @@ public: _Restore_invariants_after_insert(_Old_size); } + void insert(initializer_list<_Kty> _Ilist) { + _Insert_range(_Ilist.begin(), _Ilist.end()); + } + void insert(_Tsorted, initializer_list<_Kty> _Ilist) { + _Insert_range(_Ilist.begin(), _Ilist.end()); + } + _NODISCARD container_type extract() && { - container_type& _Cont = _Get_cont(); // always clears the container (N4950 [flat.set.modifiers]/14 and [flat.multiset.modifiers]/10) _Clear_scope_guard<_Base_flat_set> _Guard{this}; - container_type _Temp = _STD move(_Cont); - return _Temp; + return _STD move(_Get_cont()); } - void replace(container_type&& _Cont) { _Get_cont() = _STD move(_Cont); _Assert_after_sorted_input(); @@ -262,13 +293,11 @@ public: size_type erase(const _Kty& _Val) { return _Erase(_Val); } - template requires _Keylt_transparent size_type erase(_Other&& _Val) { return _Erase(_STD forward<_Other>(_Val)); } - iterator erase(const_iterator _First, const_iterator _Last) { return _Get_cont().erase(_First, _Last); } @@ -277,11 +306,11 @@ public: _RANGES swap(_Get_comp(), _Other._Get_comp()); _RANGES swap(_Get_cont(), _Other._Get_cont()); } - void clear() noexcept { _Get_cont().clear(); } + // observers _NODISCARD key_compare key_comp() const { return _Get_comp(); } @@ -289,20 +318,18 @@ public: return _Get_comp(); } + // set operations _NODISCARD iterator find(const _Kty& _Val) { return _Find(_Val); } - _NODISCARD const_iterator find(const _Kty& _Val) const { return _Find(_Val); } - template requires _Keylt_transparent _NODISCARD iterator find(const _Other& _Val) { return _Find(_Val); } - template requires _Keylt_transparent _NODISCARD const_iterator find(const _Other& _Val) const { @@ -313,7 +340,6 @@ public: const auto [_First, _Last] = equal_range(_Val); return _STD distance(_First, _Last); } - template requires _Keylt_transparent _NODISCARD size_type count(const _Other& _Val) const { @@ -322,26 +348,25 @@ public: } _NODISCARD bool contains(const _Kty& _Val) const { - return find(_Val) != end(); + return _STD binary_search(cbegin(), cend(), _Val, _Get_comp()); } template requires _Keylt_transparent _NODISCARD bool contains(const _Other& _Val) const { - return find(_Val) != end(); + return _STD binary_search(cbegin(), cend(), _Val, _Get_comp()); } + _NODISCARD iterator lower_bound(const _Kty& _Val) { return _STD lower_bound(begin(), end(), _Val, _Get_comp()); } _NODISCARD const_iterator lower_bound(const _Kty& _Val) const { return _STD lower_bound(cbegin(), cend(), _Val, _Get_comp()); } - template requires _Keylt_transparent _NODISCARD iterator lower_bound(const _Other& _Val) { return _STD lower_bound(begin(), end(), _Val, _Get_comp()); } - template requires _Keylt_transparent _NODISCARD const_iterator lower_bound(const _Other& _Val) const { @@ -351,17 +376,14 @@ public: _NODISCARD iterator upper_bound(const _Kty& _Val) { return _STD upper_bound(begin(), end(), _Val, _Get_comp()); } - _NODISCARD const_iterator upper_bound(const _Kty& _Val) const { return _STD upper_bound(cbegin(), cend(), _Val, _Get_comp()); } - template requires _Keylt_transparent _NODISCARD iterator upper_bound(const _Other& _Val) { return _STD upper_bound(begin(), end(), _Val, _Get_comp()); } - template requires _Keylt_transparent _NODISCARD const_iterator upper_bound(const _Other& _Val) const { @@ -371,17 +393,14 @@ public: _NODISCARD pair equal_range(const _Kty& _Val) { return _STD equal_range(begin(), end(), _Val, _Get_comp()); } - _NODISCARD pair equal_range(const _Kty& _Val) const { return _STD equal_range(cbegin(), cend(), _Val, _Get_comp()); } - template requires _Keylt_transparent _NODISCARD pair equal_range(const _Other& _Val) { return _STD equal_range(begin(), end(), _Val, _Get_comp()); } - template requires _Keylt_transparent _NODISCARD pair equal_range(const _Other& _Val) const { @@ -389,7 +408,7 @@ public: } _NODISCARD friend bool operator==(const _Deriv& _Lhs, const _Deriv& _Rhs) { - return _RANGES equal(_Lhs, _Rhs); + return _RANGES equal(_Lhs._Get_cont(), _Rhs._Get_cont()); } _NODISCARD friend _Synth_three_way_result<_Kty> operator<=>(const _Deriv& _Lhs, const _Deriv& _Rhs) { @@ -403,9 +422,9 @@ public: private: void _Assert_after_sorted_input() const { - _STL_ASSERT(_STD is_sorted(begin(), end(), _Get_comp()), "Input was not sorted!"); + _STL_ASSERT(_STD is_sorted(cbegin(), cend(), _Get_comp()), "Input was not sorted!"); if constexpr (!_Multi) { - _STL_ASSERT(_Is_unique(), "Input was not unique!"); + _STL_ASSERT(_Is_unique(), "Input was sorted but not unique!"); } } @@ -413,8 +432,8 @@ private: if (empty()) { return true; } - const_iterator _End = cend(); - const_iterator _It = begin(); + const const_iterator _End = cend(); + const_iterator _It = cbegin(); while (++_It != _End) { if (_Keys_equal(*(_It - 1), *_It)) { return false; @@ -424,63 +443,101 @@ private: } template - requires (_Keylt_transparent && is_constructible_v<_Kty, _Ty>) || is_same_v<_Ty, _Kty> - void _Emplace_hint(const_iterator _Where, _Ty&& _Val) { - _Container& _Cont = _Get_cont(); - _Keylt& _Compare = _Get_comp(); - const iterator _Begin = begin(); - const iterator _End = end(); + auto _Emplace(_Ty&& _Val) { + _Container& _Cont = _Get_cont(); + if constexpr (_Multi) { + _STL_INTERNAL_STATIC_ASSERT(is_same_v, _Kty>); + return _Cont.emplace(upper_bound(_Val), _STD forward<_Ty>(_Val)); + } else { + const iterator _End = end(); + const iterator _Where = lower_bound(_Val); + if (_Where != _End && _Keys_equal(*_Where, _Val)) { + return pair{_Where, false}; + } + if constexpr (is_same_v, _Kty>) { + return pair{_Cont.emplace(_Where, _STD forward<_Ty>(_Val)), true}; + } else { + // flat_set::insert(auto&&) + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent && is_constructible_v<_Kty, _Ty>); + _Kty _Keyval{_STD forward<_Ty>(_Val)}; + _STL_ASSERT(lower_bound(_Keyval) == _Where && !_Keys_equal(_Keyval, *_Where), + "find(val) was not equal to find(key_type{forward(val)})"); + return pair{_Cont.emplace(_Where, _STD move(_Keyval)), true}; + } + } + } - if (_Where == _End || !_Compare(*_Where, _Val)) { - // _Val <= *_Where - // Left of _Where - if (_Where == _Begin || !_Compare(_Val, *(_Where - 1))) { - // _Val >= (*_Where - 1) - // Insert before _Where + template + iterator _Emplace_hint(const_iterator _Where, _Ty&& _Val) { + _Container& _Cont = _Get_cont(); + const key_compare& _Compare = _Get_comp(); + const const_iterator _Begin = cbegin(); + const const_iterator _End = cend(); + + if constexpr (_Multi) { + // Find upper_bound for flat_multiset + if (_Where == _End || _Compare(_Val, *_Where)) { + // _Val < *_Where + if (_Where == _Begin || !_Compare(_Val, *(_Where - 1))) { + // _Val >= *(_Where-1) + // upper_bound is _Where + } else { + // _Val < *(_Where-1) + // upper_bound is in [_Begin,_Where-1] + _Where = _STD upper_bound(_Begin, _Where - 1, _Val); + } } else { - // _Val < (*_Where - 1) - _Where = _STD upper_bound(_Begin, _Where, _Val, _Compare); + // _Val >= *_Where + // upper_bound is in [_Where+1,_End] + _Where = _STD upper_bound(_Where + 1, _End, _Val); } } else { - // _Val > *_Where - // Right of _Where - _Where = _STD lower_bound(_Where + 1, _End, _Val, _Compare); + // Find lower_bound for flat_set + if (_Where == _End || !_Compare(*_Where, _Val)) { + // _Val <= *_Where + if (_Where == _Begin || _Compare(*(_Where - 1), _Val)) { + // _Val > *(_Where-1) + // lower_bound is _Where + } else { + // _Val <= *(_Where-1) + // lower_bound is in [_Begin,_Where-1] + _Where = _STD lower_bound(_Begin, _Where - 1, _Val); + } + } else { + // _Val > *_Where + // lower_bound is in [_Where+1,_End] + _Where = _STD lower_bound(_Where + 1, _End, _Val); + } } if constexpr (_Multi) { - return _Cont.insert(_Where, _STD forward<_Ty>(_Val)); + _STL_INTERNAL_STATIC_ASSERT(is_same_v, _Kty>); + return _Cont.emplace(_Where, _STD forward<_Ty>(_Val)); } else { - if (_Where == _End || !_Keys_equal(_Val, *_Where)) { - return _Cont.insert(_Where, _STD forward<_Ty>(_Val)); + if (_Where != _End && _Keys_equal(_Val, *_Where)) { + return _Cont.begin() + (_Where - _Begin); + } + if constexpr (is_same_v, _Kty>) { + return _Cont.emplace(_Where, _STD forward<_Ty>(_Val)); + } else { + // flat_set::insert(hint,auto&&) + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent && is_constructible_v<_Kty, _Ty>); + _Kty _Keyval{_STD forward<_Ty>(_Val)}; + _STL_ASSERT(lower_bound(_Keyval) == _Where && !_Keys_equal(_Keyval, *_Where), + "find(val) was not equal to find(key_type{forward(val)})"); + return _Cont.emplace(_Where, _STD move(_Keyval)); } - return _Where; } } template - void _Insert_range(_Iter _First, _Iter _Last) { + void _Insert_range(const _Iter _First, const _Iter _Last) { const size_type _Old_size = size(); _Container& _Cont = _Get_cont(); _Cont.insert(_Cont.end(), _First, _Last); _Restore_invariants_after_insert<_Presorted>(_Old_size); } - template - requires (!_Multi && _Keylt_transparent && is_constructible_v<_Kty, _Ty>) || is_same_v<_Ty, _Kty> - auto _Insert(_Ty&& _Val) { - _Container& _Cont = _Get_cont(); - const iterator _End = end(); - const iterator _Where = lower_bound(_Val); - if constexpr (_Multi) { - return _Cont.emplace(_Where, _STD forward<_Ty>(_Val)); - } else { - if (_Where != _End && _Keys_equal(*_Where, _Val)) { - return pair{_Where, false}; - } - return pair{_Cont.emplace(_Where, _STD forward<_Ty>(_Val)), true}; - } - } - template requires _Keylt_transparent || is_same_v<_Ty, _Kty> size_type _Erase(_Ty&& _Val) { @@ -506,8 +563,8 @@ private: template requires _Keylt_transparent || is_same_v<_Other, _Kty> _NODISCARD const_iterator _Find(const _Other& _Val) const { - const iterator _End = end(); - const iterator _Where = lower_bound(_Val); + const const_iterator _End = cend(); + const const_iterator _Where = lower_bound(_Val); if (_Where != _End && _Keys_equal(*_Where, _Val)) { return _Where; } else { @@ -522,33 +579,22 @@ private: return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs); } - // O(N) if already sorted. - void _Sort_potentially_sorted(const iterator& _Begin, const iterator& _End) { - key_compare& _Compare = _Get_comp(); - const iterator _Begin_unsorted = _STD is_sorted_until(_Begin, _End, _Compare); - - _STD sort(_Begin_unsorted, _End, _Compare); - - _STD inplace_merge(begin(), _Begin_unsorted, _End, _Compare); - } - void _Erase_dupes_if_needed() { if constexpr (!_Multi) { - iterator _End = end(); - iterator _New_end = + const iterator _End = end(); + const iterator _New_end = _STD unique(begin(), _End, [&](const _Kty& _Lhs, const _Kty& _Rhs) { return _Keys_equal(_Lhs, _Rhs); }); _Get_cont().erase(_New_end, _End); - } - if constexpr (!_Multi) { + _STL_INTERNAL_CHECK(_Is_unique()); } } template - void _Restore_invariants_after_insert(const size_type& _Old_size) { - key_compare& _Compare = _Get_comp(); - const iterator _Old_end = begin() + static_cast(_Old_size); - const iterator _New_end = end(); + void _Restore_invariants_after_insert(const size_type _Old_size) { + const key_compare& _Compare = _Get_comp(); + const iterator _Old_end = begin() + static_cast(_Old_size); + const iterator _New_end = end(); if constexpr (!_Presorted) { _STD sort(_Old_end, _New_end, _Compare); @@ -558,7 +604,7 @@ private: _STD inplace_merge(begin(), _Old_end, _New_end, _Compare); - _STL_INTERNAL_CHECK(_STD is_sorted(begin(), end(), _Get_comp())); + _STL_INTERNAL_CHECK(_STD is_sorted(begin(), end(), _Compare)); _Erase_dupes_if_needed(); } @@ -571,29 +617,35 @@ private: return; } - _Sort_potentially_sorted(_Begin, _End); - _STL_INTERNAL_CHECK(_STD is_sorted(begin(), end(), _Get_comp())); + // O(N) if already sorted. + const key_compare& _Compare = _Get_comp(); + const iterator _Begin_unsorted = _STD is_sorted_until(_Begin, _End, _Compare); + + _STD sort(_Begin_unsorted, _End, _Compare); + _STD inplace_merge(begin(), _Begin_unsorted, _End, _Compare); + + _STL_INTERNAL_CHECK(_STD is_sorted(_Begin, _End, _Compare)); _Erase_dupes_if_needed(); } _NODISCARD const _Container& _Get_cont() const noexcept { - return _My_pair._Get_first(); + return _My_pair._Myval2; } _NODISCARD _Container& _Get_cont() noexcept { - return _My_pair._Get_first(); + return _My_pair._Myval2; } _NODISCARD const key_compare& _Get_comp() const noexcept { - return _My_pair._Myval2; + return _My_pair._Get_first(); } _NODISCARD key_compare& _Get_comp() noexcept { - return _My_pair._Myval2; + return _My_pair._Get_first(); } - _Compressed_pair _My_pair; + _Compressed_pair _My_pair; }; _EXPORT_STD struct sorted_unique_t { @@ -609,15 +661,23 @@ _EXPORT_STD inline constexpr sorted_equivalent_t sorted_equivalent{}; _EXPORT_STD template , class _Container = vector<_Kty>> class flat_set : public _Base_flat_set<_Kty, _Keylt, _Container, false, flat_set<_Kty, _Keylt, _Container>, sorted_unique_t> { +private: + using _Mybase = _Base_flat_set<_Kty, _Keylt, _Container, false, flat_set, sorted_unique_t>; + public: - using _Base_flat_set<_Kty, _Keylt, _Container, false, flat_set, sorted_unique_t>::_Base_flat_set; + using _Mybase::_Mybase; + using _Mybase::operator=; }; _EXPORT_STD template , class _Container = vector<_Kty>> class flat_multiset : public _Base_flat_set<_Kty, _Keylt, _Container, true, flat_multiset<_Kty, _Keylt, _Container>, sorted_equivalent_t> { +private: + using _Mybase = _Base_flat_set<_Kty, _Keylt, _Container, true, flat_multiset, sorted_equivalent_t>; + public: - using _Base_flat_set<_Kty, _Keylt, _Container, true, flat_multiset, sorted_equivalent_t>::_Base_flat_set; + using _Mybase::_Mybase; + using _Mybase::operator=; }; _EXPORT_STD template @@ -719,6 +779,11 @@ flat_multiset(sorted_equivalent_t, initializer_list<_Kty>, _Keylt = _Keylt()) -> _STD_END +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) + #endif // ^^^ supported language mode ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _FLAT_SET_ diff --git a/tests/std/tests/P1222R4_flat_set/test.cpp b/tests/std/tests/P1222R4_flat_set/test.cpp index a7739cc7353..9eae7a98f88 100644 --- a/tests/std/tests/P1222R4_flat_set/test.cpp +++ b/tests/std/tests/P1222R4_flat_set/test.cpp @@ -98,19 +98,6 @@ void assert_all_requirements_and_equals(const T& s, const initializer_list -void assert_basic() { - T s{3, 2, 2, 2, 1}; - assert_all_requirements_and_equals(s, {1, 2, 3}); - - s.insert(43); - assert_all_requirements_and_equals(s, {1, 2, 3, 43}); - - int my_ints[] = {1, 2, 3, 4, 55}; - s.insert_range(my_ints); - assert_all_requirements_and_equals(s, {1, 2, 3, 4, 43, 55}); -} - template void test_constructors() { using lt = std::less; @@ -132,9 +119,97 @@ void test_constructors() { flat_set a{}; a = {1, 7, 7, 7, 2, 100, -1}; assert_all_requirements_and_equals(a, {-1, 1, 2, 7, 100}); + assert_all_requirements_and_equals(flat_set(a, allocator{}), {-1, 1, 2, 7, 100}); + assert_all_requirements_and_equals(flat_set(std::move(a), allocator{}), {-1, 1, 2, 7, 100}); flat_multiset b{}; b = {1, 7, 7, 7, 2, 100, -1}; assert_all_requirements_and_equals(b, {-1, 1, 2, 7, 7, 7, 100}); + assert_all_requirements_and_equals(flat_multiset(b, allocator{}), {-1, 1, 2, 7, 7, 7, 100}); + assert_all_requirements_and_equals(flat_multiset(std::move(b), allocator{}), {-1, 1, 2, 7, 7, 7, 100}); +} + +template +void test_insert_1() { + using lt = std::less; + + const int _dat[]{0, 1, 2}; + const int* volatile _beg = _dat; + const int* volatile _end = std::end(_dat); + { + flat_set a{5, 5}; + assert_all_requirements_and_equals(a, {5}); + a.emplace(); + assert_all_requirements_and_equals(a, {0, 5}); + a.emplace(1); + assert_all_requirements_and_equals(a, {0, 1, 5}); + a.insert(_dat[2]); + assert_all_requirements_and_equals(a, {0, 1, 2, 5}); + a.insert(2); + assert_all_requirements_and_equals(a, {0, 1, 2, 5}); + a.insert(_beg, _end); + assert_all_requirements_and_equals(a, {0, 1, 2, 5}); + a.insert(sorted_unique, _beg, _end); + assert_all_requirements_and_equals(a, {0, 1, 2, 5}); + a.insert_range(_dat); + assert_all_requirements_and_equals(a, {0, 1, 2, 5}); + a.insert({6, 2, 3}); + assert_all_requirements_and_equals(a, {0, 1, 2, 3, 5, 6}); + a.insert(sorted_unique, {4, 5}); + assert_all_requirements_and_equals(a, {0, 1, 2, 3, 4, 5, 6}); + } + { + flat_multiset a{5, 5}; + assert_all_requirements_and_equals(a, {5, 5}); + a.emplace(); + assert_all_requirements_and_equals(a, {0, 5, 5}); + a.emplace(1); + assert_all_requirements_and_equals(a, {0, 1, 5, 5}); + a.insert(_dat[2]); + assert_all_requirements_and_equals(a, {0, 1, 2, 5, 5}); + a.insert(2); + assert_all_requirements_and_equals(a, {0, 1, 2, 2, 5, 5}); + a.insert(_beg, _end); + assert_all_requirements_and_equals(a, {0, 0, 1, 1, 2, 2, 2, 5, 5}); + a.insert(sorted_equivalent, _beg, _end); + assert_all_requirements_and_equals(a, {0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 5, 5}); + a.insert_range(_dat); + assert_all_requirements_and_equals(a, {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 5, 5}); + a.insert({6, 2, 3}); + assert_all_requirements_and_equals(a, {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 5, 5, 6}); + a.insert(sorted_equivalent, {4, 5}); + assert_all_requirements_and_equals(a, {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5, 5, 5, 6}); + } +} + +template +void test_insert_2() { + using lt = std::less; + + const int _dat[]{0, 1, 2}; + { + flat_set a{0, 5}; + assert_all_requirements_and_equals(a, {0, 5}); + a.emplace_hint(a.end()); + assert_all_requirements_and_equals(a, {0, 5}); + a.emplace_hint(a.end(), 0); + assert_all_requirements_and_equals(a, {0, 5}); + a.insert(a.begin(), 6); + assert_all_requirements_and_equals(a, {0, 5, 6}); + a.insert(a.begin(), _dat[1]); + assert_all_requirements_and_equals(a, {0, 1, 5, 6}); + } + { + flat_multiset a{0, 5}; + assert_all_requirements_and_equals(a, {0, 5}); + a.emplace_hint(a.end()); + assert_all_requirements_and_equals(a, {0, 0, 5}); + a.emplace_hint(a.end(), 0); + assert_all_requirements_and_equals(a, {0, 0, 0, 5}); + a.insert(a.begin(), 6); + assert_all_requirements_and_equals(a, {0, 0, 0, 5, 6}); + a.insert(a.begin(), _dat[1]); + assert_all_requirements_and_equals(a, {0, 0, 0, 1, 5, 6}); + } } template @@ -191,6 +266,21 @@ void test_non_static_comparer() { assert_all_requirements_and_equals(a, {9, 7, 5, -1}); } +void test_ebco() { + using vec = vector; + using deq = deque; + + static_assert(sizeof(vec) == sizeof(flat_set, vec>)); + static_assert(sizeof(deq) == sizeof(flat_set, deq>)); + static_assert(sizeof(vec) == sizeof(flat_multiset, vec>)); + static_assert(sizeof(deq) == sizeof(flat_multiset, deq>)); + + static_assert(sizeof(vec) < sizeof(flat_set, vec>)); + static_assert(sizeof(deq) < sizeof(flat_set, deq>)); + static_assert(sizeof(vec) < sizeof(flat_multiset, vec>)); + static_assert(sizeof(deq) < sizeof(flat_multiset, deq>)); +} + template void test_extract() { constexpr int elements[]{1, 2, 3, 4}; @@ -222,6 +312,13 @@ int main() { test_constructors>(); test_constructors>(); + test_ebco(); + + test_insert_1>(); + test_insert_1>(); + test_insert_2>(); + test_insert_2>(); + test_non_static_comparer(); test_extract>(); @@ -229,9 +326,4 @@ int main() { test_erase_if>(); test_erase_if>(); - - assert_basic>(); - assert_basic, deque>>(); - - flat_multiset, deque> d; }