From 8f5b0dcca2c43e12d51ec1293ed17e51d3640838 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 22 Jan 2024 07:33:27 +0800 Subject: [PATCH 01/11] Name cleanups for `` - Consistently use `_UglyCamelCase` for template arguments. - Consistently use `_Ugly_snake_case` for other stuffs. - Consistently use `_Meow_provider` for SCARY & ADL-proof layers. - Replace `_X`, `_K` etc. and a non-_Uglified `R`. - Replace `_Paring_meow` with `_Pairing_meow` --- stl/inc/flat_map | 742 ++++++++++++++++++++++++----------------------- 1 file changed, 375 insertions(+), 367 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index facdd5474e5..6eef90d0655 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -29,11 +29,11 @@ _STL_DISABLE_CLANG_WARNINGS _STD_BEGIN -template - requires same_as<_FlatMap_Key, typename _FlatMap_KeyContainer::value_type> - && same_as<_FlatMap_T, typename _FlatMap_MappedContainer::value_type> -class _Flat_Map_Base; +template + requires same_as<_Key, typename _KeyContainer::value_type> + && same_as<_Mapped, typename _MappedContainer::value_type> +class _Flat_map_base; template , class _KeyContainer = vector<_Key>, class _MappedContainer = vector<_Mapped>> @@ -54,33 +54,33 @@ struct sorted_equivalent_t { inline constexpr sorted_equivalent_t sorted_equivalent{}; template -concept _Valid_Allocator_for_flat_map = +concept _Valid_allocator_for_flat_map = uses_allocator_v<_Key_container, _Alloc> && uses_allocator_v<_Mapped_container, _Alloc>; template -concept _Valid_Compare_for_container = is_invocable_v; -template -struct _Flat_value_compare { +template +struct _Flat_map_value_compare_provider { struct value_compare { public: - bool operator()(pair _X, pair _Y) const { - return _Key_compare_for_val(_X.first, _Y.first); + bool operator()(pair _Left, pair _Right) const { + return _Key_comparator(_Left.first, _Right.first); } - value_compare(_Key_compare _Comp) : _Key_compare_for_val(_Comp) {} + value_compare(_KeyCompare _Comp) : _Key_comparator(_Comp) {} private: - _Key_compare _Key_compare_for_val; + _KeyCompare _Key_comparator; }; }; -template -struct _Flat_Container { - struct container { - _Key_container keys; - _Mapped_container values; +template +struct _Flat_map_container_provider { + struct containers { + _KeyContainer keys; + _MappedContainer values; }; }; @@ -98,26 +98,26 @@ struct _NODISCARD _Clear_flat_map_scope_guard { // Implementation -enum class _Paring_iterator_kind : unsigned char { +enum class _Pairing_iterator_kind : unsigned char { _Sort, _Mutable, _Const, }; -template -struct _Paring_iterator_provider { - using _Key_iterator_t = conditional_t<_Kind == _Paring_iterator_kind::_Sort, typename _KeyContainer::iterator, +template +struct _Pairing_iterator_provider { + using _Key_iterator_t = conditional_t<_Kind == _Pairing_iterator_kind::_Sort, typename _KeyContainer::iterator, typename _KeyContainer::const_iterator>; - using _Mapped_iterator_t = conditional_t<_Kind == _Paring_iterator_kind::_Const, + using _Mapped_iterator_t = conditional_t<_Kind == _Pairing_iterator_kind::_Const, typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>; class _Iterator { public: - template - requires same_as<_FlatMap_Key, typename _FlatMap_KeyContainer::value_type> - && same_as<_FlatMap_T, typename _FlatMap_MappedContainer::value_type> - friend class _Flat_Map_Base; + template + requires same_as<_Key, typename _KeyContainer::value_type> + && same_as<_Mapped, typename _MappedContainer::value_type> + friend class _Flat_map_base; _Iterator() = default; _Iterator(_Key_iterator_t _Key_it, _Mapped_iterator_t _Mapped_it) : _Key_it(_Key_it), _Mapped_it(_Mapped_it) {} @@ -219,12 +219,15 @@ struct _Paring_iterator_provider { return _Right + _Off; } - operator typename _Paring_iterator_provider<_KeyContainer, _MappedContainer, - _Paring_iterator_kind::_Const>::_Iterator() const - requires (_Kind == _Paring_iterator_kind::_Mutable) + private: + using _Const_iterator = + _Pairing_iterator_provider<_KeyContainer, _MappedContainer, _Pairing_iterator_kind::_Const>::_Iterator; + + public: + operator _Const_iterator() const + requires (_Kind == _Pairing_iterator_kind::_Mutable) { - return typename _Paring_iterator_provider<_KeyContainer, _MappedContainer, - _Paring_iterator_kind::_Const>::_Iterator{_Key_it, _Mapped_it}; + return _Const_iterator{_Key_it, _Mapped_it}; } private: @@ -236,93 +239,93 @@ struct _Paring_iterator_provider { }; _EXPORT_STD -template - requires same_as<_FlatMap_Key, typename _FlatMap_KeyContainer::value_type> - && same_as<_FlatMap_T, typename _FlatMap_MappedContainer::value_type> -class _Flat_Map_Base { +template + requires same_as<_Key, typename _KeyContainer::value_type> + && same_as<_Mapped, typename _MappedContainer::value_type> +class _Flat_map_base { private: - using _Sorted_t = conditional_t<_Is_Multi, sorted_equivalent_t, sorted_unique_t>; + using _Sorted_t = conditional_t<_IsMulti, sorted_equivalent_t, sorted_unique_t>; public: - using key_type = _FlatMap_Key; - using mapped_type = _FlatMap_T; - using value_type = pair; - using key_compare = _FlatMap_Compare; - using reference = pair; - using const_reference = pair; - using size_type = size_t; - using difference_type = ptrdiff_t; - using key_container_type = _FlatMap_KeyContainer; - using mapped_container_type = _FlatMap_MappedContainer; - using iterator = _Paring_iterator_provider::_Iterator; - using const_iterator = - _Paring_iterator_provider::_Iterator; + using key_type = _Key; + using mapped_type = _Mapped; + using value_type = pair; + using key_compare = _Compare; + using reference = pair; + using const_reference = pair; + using size_type = size_t; + using difference_type = ptrdiff_t; + using key_container_type = _KeyContainer; + using mapped_container_type = _MappedContainer; + using iterator = _Pairing_iterator_provider::_Iterator; + using const_iterator = _Pairing_iterator_provider::_Iterator; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; _STL_INTERNAL_STATIC_ASSERT(random_access_iterator); _STL_INTERNAL_STATIC_ASSERT(convertible_to); - using value_compare = _Flat_value_compare::value_compare; - using containers = _Flat_Container::container; + using value_compare = _Flat_map_value_compare_provider::value_compare; + using containers = _Flat_map_container_provider::containers; public: // [flat.map.cons] Constructors - explicit _Flat_Map_Base(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} - _Flat_Map_Base() : _Flat_Map_Base(key_compare()) {} + explicit _Flat_map_base(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} + _Flat_map_base() : _Flat_map_base(key_compare()) {} - template <_Valid_Allocator_for_flat_map Allocator> - explicit _Flat_Map_Base(const Allocator& _Alloc) : _Flat_Map_Base(key_compare(), _Alloc) {} + template <_Valid_allocator_for_flat_map Allocator> + explicit _Flat_map_base(const Allocator& _Alloc) : _Flat_map_base(key_compare(), _Alloc) {} - template <_Valid_Allocator_for_flat_map Allocator> - explicit _Flat_Map_Base(const key_compare& _Comp, const Allocator& _Alloc) + template <_Valid_allocator_for_flat_map Allocator> + explicit _Flat_map_base(const key_compare& _Comp, const Allocator& _Alloc) : _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc), .values = _STD make_obj_using_allocator(_Alloc)} {} - _Flat_Map_Base( + _Flat_map_base( key_container_type _Key_cont, mapped_container_type _Mapped_cont, const key_compare& _Comp = key_compare()) - : _Flat_Map_Base(_Sorted_t(), _Key_cont, _Mapped_cont, _Comp) { + : _Flat_map_base(_Sorted_t(), _Key_cont, _Mapped_cont, _Comp) { _Sort(); - if constexpr (!_Is_Multi) { + if constexpr (!_IsMulti) { _Dedup(); } } - template <_Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base( + template <_Valid_allocator_for_flat_map Allocator> + _Flat_map_base( const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) - : _Flat_Map_Base(_Sorted_t(), _Key_cont, _Mapped_cont, _Alloc) { + : _Flat_map_base(_Sorted_t(), _Key_cont, _Mapped_cont, _Alloc) { _Sort(); - if constexpr (!_Is_Multi) { + if constexpr (!_IsMulti) { _Dedup(); } } - template <_Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, + template <_Valid_allocator_for_flat_map Allocator> + _Flat_map_base(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const key_compare& _Comp, const Allocator& _Alloc) - : _Flat_Map_Base(_Sorted_t(), _Key_cont, _Mapped_cont, _Comp, _Alloc) { + : _Flat_map_base(_Sorted_t(), _Key_cont, _Mapped_cont, _Comp, _Alloc) { _Sort(); - if constexpr (!_Is_Multi) { + if constexpr (!_IsMulti) { _Dedup(); } } - _Flat_Map_Base(_Sorted_t, key_container_type _Key_cont, mapped_container_type _Mapped_cont, + _Flat_map_base(_Sorted_t, key_container_type _Key_cont, mapped_container_type _Mapped_cont, const key_compare& _Comp = key_compare()) : _Key_compare(_Comp), _Data{.keys = _STD move(_Key_cont), .values = _STD move(_Mapped_cont)} {} - template <_Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base(_Sorted_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, + template <_Valid_allocator_for_flat_map Allocator> + _Flat_map_base(_Sorted_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) : _Key_compare(key_compare()), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} - template <_Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base(_Sorted_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, + template <_Valid_allocator_for_flat_map Allocator> + _Flat_map_base(_Sorted_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const key_compare& _Comp, const Allocator& _Alloc) : _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), @@ -330,107 +333,109 @@ public: template requires _Is_iterator_v<_InputIterator> - _Flat_Map_Base(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) - : _Flat_Map_Base(_Comp) { + _Flat_map_base(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) + : _Flat_map_base(_Comp) { insert(_First, _Last); } - template Allocator> + template Allocator> requires _Is_iterator_v<_InputIterator> - _Flat_Map_Base(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) - : _Flat_Map_Base(_Comp, _Alloc) { + _Flat_map_base(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_map_base(_Comp, _Alloc) { insert(_First, _Last); } - template <_Container_compatible_range R> - _Flat_Map_Base(from_range_t _From_range, R&& _Range) - : _Flat_Map_Base(_From_range, _STD forward(_Range), key_compare()) {} + template <_Container_compatible_range _Rng> + _Flat_map_base(from_range_t _From_range, _Rng&& _Range) + : _Flat_map_base(_From_range, _STD forward<_Rng>(_Range), key_compare()) {} - template <_Container_compatible_range R, - _Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base(from_range_t _From_range, R&& _Range, const Allocator& _Alloc) - : _Flat_Map_Base(_From_range, _STD forward(_Range), key_compare(), _Alloc) {} + template <_Container_compatible_range _Rng, + _Valid_allocator_for_flat_map Allocator> + _Flat_map_base(from_range_t _From_range, _Rng&& _Range, const Allocator& _Alloc) + : _Flat_map_base(_From_range, _STD forward<_Rng>(_Range), key_compare(), _Alloc) {} - template <_Container_compatible_range R> - _Flat_Map_Base(from_range_t, R&& _Range, const key_compare& _Comp) : _Flat_Map_Base(_Comp) { - insert_range(_STD forward(_Range)); + template <_Container_compatible_range _Rng> + _Flat_map_base(from_range_t, _Rng&& _Range, const key_compare& _Comp) : _Flat_map_base(_Comp) { + insert_range(_STD forward<_Rng>(_Range)); } - template <_Container_compatible_range R, - _Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base(from_range_t, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc) - : _Flat_Map_Base(_Comp, _Alloc) { - insert_range(_STD forward(_Range)); + template <_Container_compatible_range _Rng, + _Valid_allocator_for_flat_map Allocator> + _Flat_map_base(from_range_t, _Rng&& _Range, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_map_base(_Comp, _Alloc) { + insert_range(_STD forward<_Rng>(_Range)); } template requires _Is_iterator_v<_InputIterator> - _Flat_Map_Base(_Sorted_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) - : _Flat_Map_Base(_Comp) { - insert(_S, _First, _Last); + _Flat_map_base( + _Sorted_t _Tag, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) + : _Flat_map_base(_Comp) { + insert(_Tag, _First, _Last); } - template Allocator> + template Allocator> requires _Is_iterator_v<_InputIterator> - _Flat_Map_Base( - _Sorted_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) - : _Flat_Map_Base(_Comp, _Alloc) { - insert(_S, _First, _Last); + _Flat_map_base( + _Sorted_t _Tag, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_map_base(_Comp, _Alloc) { + insert(_Tag, _First, _Last); } - template Allocator> + template Allocator> requires _Is_iterator_v<_InputIterator> - _Flat_Map_Base(_Sorted_t _S, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc) - : _Flat_Map_Base(_S, _First, _Last, key_compare(), _Alloc) {} + _Flat_map_base(_Sorted_t _Tag, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc) + : _Flat_map_base(_Tag, _First, _Last, key_compare(), _Alloc) {} - _Flat_Map_Base(initializer_list _I, const key_compare& _Comp = key_compare()) - : _Flat_Map_Base(_I.begin(), _I.end(), _Comp) {} + _Flat_map_base(initializer_list _Ilist, const key_compare& _Comp = key_compare()) + : _Flat_map_base(_Ilist.begin(), _Ilist.end(), _Comp) {} - template <_Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base(initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc) - : _Flat_Map_Base(_I.begin(), _I.end(), _Comp, _Alloc) {} + template <_Valid_allocator_for_flat_map Allocator> + _Flat_map_base(initializer_list _Ilist, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_map_base(_Ilist.begin(), _Ilist.end(), _Comp, _Alloc) {} - template <_Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base(initializer_list _I, const Allocator& _Alloc) - : _Flat_Map_Base(_I, key_compare(), _Alloc) {} + template <_Valid_allocator_for_flat_map Allocator> + _Flat_map_base(initializer_list _Ilist, const Allocator& _Alloc) + : _Flat_map_base(_Ilist, key_compare(), _Alloc) {} - _Flat_Map_Base(_Sorted_t _S, initializer_list _I, const key_compare& _Comp = key_compare()) - : _Flat_Map_Base(_S, _I.begin(), _I.end(), _Comp) {} + _Flat_map_base(_Sorted_t _Tag, initializer_list _Ilist, const key_compare& _Comp = key_compare()) + : _Flat_map_base(_Tag, _Ilist.begin(), _Ilist.end(), _Comp) {} - template <_Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base(_Sorted_t _S, initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc) - : _Flat_Map_Base(_S, _I.begin(), _I.end(), _Comp, _Alloc) {} + template <_Valid_allocator_for_flat_map Allocator> + _Flat_map_base( + _Sorted_t _Tag, initializer_list _Ilist, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_map_base(_Tag, _Ilist.begin(), _Ilist.end(), _Comp, _Alloc) {} - template <_Valid_Allocator_for_flat_map Allocator> - _Flat_Map_Base(_Sorted_t _S, initializer_list _I, const Allocator& _Alloc) - : _Flat_Map_Base(_S, _I, key_compare(), _Alloc) {} + template <_Valid_allocator_for_flat_map Allocator> + _Flat_map_base(_Sorted_t _Tag, initializer_list _Ilist, const Allocator& _Alloc) + : _Flat_map_base(_Tag, _Ilist, key_compare(), _Alloc) {} // Copy constructors - _Flat_Map_Base(const _Derived& _Other) : _Key_compare(_Other._Key_compare), _Data(_Other._Data) {} + _Flat_map_base(const _Derived& _Other) : _Key_compare(_Other._Key_compare), _Data(_Other._Data) {} - template <_Valid_Allocator_for_flat_map _Allocator> - _Flat_Map_Base(const _Derived& _Other, const _Allocator& _Alloc) + template <_Valid_allocator_for_flat_map _Allocator> + _Flat_map_base(const _Derived& _Other, const _Allocator& _Alloc) : _Key_compare(_Other._Key_compare), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Other._Data.keys), .values = _STD make_obj_using_allocator(_Alloc, _Other._Data.values)} {} // Move constructors - _Flat_Map_Base(_Derived&& _Other) noexcept(is_nothrow_move_constructible_v + _Flat_map_base(_Derived&& _Other) noexcept(is_nothrow_move_constructible_v && is_nothrow_move_constructible_v && is_nothrow_move_constructible_v) : _Key_compare(move(_Other._Key_compare)), _Data(move(_Other).extract()) {} - template <_Valid_Allocator_for_flat_map _Allocator> - _Flat_Map_Base(_Derived&& _Other, const _Allocator& _Alloc) noexcept( + template <_Valid_allocator_for_flat_map _Allocator> + _Flat_map_base(_Derived&& _Other, const _Allocator& _Alloc) noexcept( is_nothrow_move_constructible_v && is_nothrow_move_constructible_v && is_nothrow_move_constructible_v) : _Key_compare(move(_Other._Key_compare)), _Data{.keys = _STD make_obj_using_allocator(_Alloc, move(_Other._Data.keys)), .values = _STD make_obj_using_allocator(_Alloc, move(_Other._Data.values))} {} - _Derived& operator=(initializer_list _I) { + _Derived& operator=(initializer_list _Ilist) { clear(); - insert(_I.begin(), _I.end()); + insert(_Ilist.begin(), _Ilist.end()); return static_cast<_Derived&>(*this); // Use "deducing this" when it is supported } @@ -509,137 +514,137 @@ public: } // [flat.map.access] Access - template - _NODISCARD mapped_type& operator[](_K&& _Key_val) - requires same_as, key_type> - || (_Is_transparent_v && constructible_from) + template + _NODISCARD mapped_type& operator[](_OtherKey&& _Key_val) + requires same_as, key_type> + || (_Is_transparent_v && constructible_from) { - return try_emplace(_STD forward<_K>(_Key_val)).first->second; + return try_emplace(_STD forward<_OtherKey>(_Key_val)).first->second; } _NODISCARD mapped_type& at(const key_type& _Key_val) { return _At(_Key_val); } - template - _NODISCARD const mapped_type& at(const _K& _Key_val) const + template + _NODISCARD const mapped_type& at(const _OtherKey& _Key_val) const requires _Is_transparent_v { return _At(_Key_val); } // [flat.map.modifiers] Modifiers - template - pair emplace(_Args_t&&... _Args) - requires is_constructible_v + template + pair emplace(_MappedArgTypes&&... _Args) + requires is_constructible_v { - value_type _Val(_STD forward<_Args_t>(_Args)...); + value_type _Val(_STD forward<_MappedArgTypes>(_Args)...); return try_emplace(_STD move(_Val.first), _STD move(_Val.second)); } - template - iterator emplace_hint(const_iterator _Position, _Args_t&&... _Args) - requires is_constructible_v + template + iterator emplace_hint(const_iterator _Position, _MappedArgTypes&&... _Args) + requires is_constructible_v { - value_type _Val(_STD forward<_Args_t>(_Args)...); + value_type _Val(_STD forward<_MappedArgTypes>(_Args)...); return _Emplace_hint(_Position, _STD move(_Val.first), _STD move(_Val.second)); } - template - pair insert(_V&& _X) - requires (same_as, value_type> || constructible_from) + template + pair insert(_MappedTy&& _Mapped_val) + requires (same_as, value_type> || constructible_from) { - return emplace(_STD forward<_V>(_X)); + return emplace(_STD forward<_MappedTy>(_Mapped_val)); } - template - iterator insert(const_iterator _Position, _V&& _X) - requires (same_as, value_type> || constructible_from) + template + iterator insert(const_iterator _Position, _MappedTy&& _Mapped_val) + requires (same_as, value_type> || constructible_from) { - return emplace_hint(_Position, _STD forward<_V>(_X)); + return emplace_hint(_Position, _STD forward<_MappedTy>(_Mapped_val)); } template requires _Is_iterator_v<_InputIterator> void insert(_InputIterator _First, _InputIterator _Last) { - _Insert_range(_First, _Last); + _Insert_range(_First, _Last); } template requires _Is_iterator_v<_InputIterator> void insert(_Sorted_t, _InputIterator _First, _InputIterator _Last) { - _Insert_range(_First, _Last); + _Insert_range(_First, _Last); } - template <_Container_compatible_range R> - void insert_range(R&& _Range) { + template <_Container_compatible_range _Rng> + void insert_range(_Rng&& _Range) { insert(_RANGES begin(_Range), _RANGES end(_Range)); } - void insert(initializer_list _I) { - insert(_I.begin(), _I.end()); + void insert(initializer_list _Ilist) { + insert(_Ilist.begin(), _Ilist.end()); } - void insert(_Sorted_t _S, initializer_list _I) { - insert(_S, _I.begin(), _I.end()); + void insert(_Sorted_t _Tag, initializer_list _Ilist) { + insert(_Tag, _Ilist.begin(), _Ilist.end()); } - template - pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) - requires constructible_from - && (same_as, key_type> - || (constructible_from && _Is_transparent_v - && !convertible_to<_Key_constructible_t &&, const_iterator> - && !convertible_to<_Key_constructible_t &&, iterator>) ) + template + pair try_emplace(_OtherKey&& _Key_val, _MappedArgTypes&&... _Mapped_args) + requires constructible_from + && (same_as, key_type> + || (constructible_from && _Is_transparent_v + && !convertible_to<_OtherKey &&, const_iterator> && !convertible_to<_OtherKey &&, iterator>) ) { - auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key_constructible, _Key_compare); - if (_Key_It != _Data.keys.end() - && _Key_equal(*_Key_It, _STD forward<_Key_constructible_t>(_Key_constructible))) { + auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key_val, _Key_compare); + if (_Key_it != _Data.keys.end() && _Key_equal(*_Key_it, _STD forward<_OtherKey>(_Key_val))) { // Already exists - return {begin() + _STD distance(_Data.keys.begin(), _Key_It), false}; + return {begin() + _STD distance(_Data.keys.begin(), _Key_it), false}; } else { // Need to insert - auto _Index = _STD distance(_Data.keys.begin(), _Key_It); - _Insert_exact(cbegin() + _Index, key_type{_STD forward<_Key_constructible_t>(_Key_constructible)}, - mapped_type{_STD forward<_Args_t>(_Args)...}); + auto _Index = _STD distance(_Data.keys.begin(), _Key_it); + _Insert_exact(cbegin() + _Index, key_type{_STD forward<_OtherKey>(_Key_val)}, + mapped_type{_STD forward<_MappedArgTypes>(_Mapped_args)...}); return {begin() + _Index, true}; } } - template - iterator try_emplace(const_iterator _Position, _K&& _Key_val, _Args_t&&... _Args) - requires constructible_from - && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) + template + iterator try_emplace(const_iterator _Position, _OtherKey&& _Key_val, _MappedArgTypes&&... _Mapped_args) + requires constructible_from + && (same_as, key_type> + || (constructible_from && _Is_transparent_v) ) { - return _Emplace_hint(_Position, _STD forward<_K>(_Key_val), _STD forward<_Args_t>(_Args)...); + return _Emplace_hint( + _Position, _STD forward<_OtherKey>(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)...); } - template - pair insert_or_assign(_K&& _Key_val, _M&& _Obj) - requires assignable_from && constructible_from - && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) + template + pair insert_or_assign(_OtherKey&& _Key_val, _MappedTy&& _Mapped_val) + requires assignable_from && constructible_from + && (same_as, key_type> + || (constructible_from && _Is_transparent_v) ) { - auto _Res = try_emplace(_STD forward<_K>(_Key_val), _STD forward<_M>(_Obj)); + auto _Res = try_emplace(_STD forward<_OtherKey>(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); if (_Res.second) { // Insertion took place return _Res; } else { // Already exists - *(_Res.first._Mapped_it) = _STD forward<_M>(_Obj); + *(_Res.first._Mapped_it) = _STD forward<_MappedTy>(_Mapped_val); return _Res; } } - template - iterator insert_or_assign(const_iterator _Position, _K&& _Key_val, _M&& _Obj) - requires assignable_from && constructible_from - && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) + template + iterator insert_or_assign(const_iterator _Position, _OtherKey&& _Key_val, _MappedTy&& _Mapped_val) + requires assignable_from && constructible_from + && (same_as, key_type> + || (constructible_from && _Is_transparent_v) ) { - return _Emplace_hint(_Position, _STD forward<_K>(_Key_val), _STD forward<_M>(_Obj)); + return _Emplace_hint( + _Position, _STD forward<_OtherKey>(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); } iterator erase(iterator _Position) { @@ -662,14 +667,14 @@ public: return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } - template - size_type erase(_K&& _Key_val) - requires convertible_to<_K&&, const key_type&> - || (_Is_transparent_v && !convertible_to<_K &&, iterator> - && !convertible_to<_K &&, const_iterator>) + template + size_type erase(_OtherKey&& _Key_val) + requires convertible_to<_OtherKey&&, const key_type&> + || (_Is_transparent_v && !convertible_to<_OtherKey &&, iterator> + && !convertible_to<_OtherKey &&, const_iterator>) { - const_iterator _Pos_begin = lower_bound(_STD forward<_K>(_Key_val)); - const_iterator _Pos_end = upper_bound(_STD forward<_K>(_Key_val)); + const_iterator _Pos_begin = lower_bound(_STD forward<_OtherKey>(_Key_val)); + const_iterator _Pos_end = upper_bound(_STD forward<_OtherKey>(_Key_val)); size_type _Count = _Pos_end - _Pos_begin; erase(_Pos_begin, _Pos_end); return _Count; @@ -705,127 +710,128 @@ public: } // map operations - iterator find(const key_type& _X) { - return _Find(_X); + iterator find(const key_type& _Key_val) { + return _Find(_Key_val); } - template - iterator find(const _K& _X) + template + iterator find(const _OtherKey& _Key_val) requires _Is_transparent_v { - return _Find(_X); + return _Find(_Key_val); } - const_iterator find(const key_type& _X) const { - return _Find(_X); + const_iterator find(const key_type& _Key_val) const { + return _Find(_Key_val); } - template - const_iterator find(const _K& _X) const + template + const_iterator find(const _OtherKey& _Key_val) const requires _Is_transparent_v { - return _Find(_X); + return _Find(_Key_val); } - size_type count(const key_type& _X) const { - return _Count(_X); + size_type count(const key_type& _Key_val) const { + return _Count(_Key_val); } - template - size_type count(const _K& _X) const + template + size_type count(const _OtherKey& _Key_val) const requires _Is_transparent_v { - return _Count(_X); + return _Count(_Key_val); } - bool contains(const key_type& _X) const { - return _Contains(_X); + bool contains(const key_type& _Key_val) const { + return _Contains(_Key_val); } - template - bool contains(const _K& _X) const + template + bool contains(const _OtherKey& _Key_val) const requires _Is_transparent_v { - return _Contains(_X); + return _Contains(_Key_val); } - iterator lower_bound(const key_type& _X) { - return _Lower_bound(_X); + iterator lower_bound(const key_type& _Key_val) { + return _Lower_bound(_Key_val); } - template - iterator lower_bound(const _K& _X) + template + iterator lower_bound(const _OtherKey& _Key_val) requires _Is_transparent_v { - return _Lower_bound(_X); + return _Lower_bound(_Key_val); } - const_iterator lower_bound(const key_type& _X) const { - return _Lower_bound(_X); + const_iterator lower_bound(const key_type& _Key_val) const { + return _Lower_bound(_Key_val); } - template - const_iterator lower_bound(const _K& _X) const + template + const_iterator lower_bound(const _OtherKey& _Key_val) const requires _Is_transparent_v { - return _Lower_bound(_X); + return _Lower_bound(_Key_val); } - iterator upper_bound(const key_type& _X) { - return _Upper_bound(_X); + iterator upper_bound(const key_type& _Key_val) { + return _Upper_bound(_Key_val); } - template - iterator upper_bound(const _K& _X) + template + iterator upper_bound(const _OtherKey& _Key_val) requires _Is_transparent_v { - return _Upper_bound(_X); + return _Upper_bound(_Key_val); } - const_iterator upper_bound(const key_type& _X) const { - return _Upper_bound(_X); + const_iterator upper_bound(const key_type& _Key_val) const { + return _Upper_bound(_Key_val); } - template - const_iterator upper_bound(const _K& _X) const + template + const_iterator upper_bound(const _OtherKey& _Key_val) const requires _Is_transparent_v { - return _Upper_bound(_X); + return _Upper_bound(_Key_val); } - pair equal_range(const key_type& _X) { - return _Equal_range(_X); + pair equal_range(const key_type& _Key_val) { + return _Equal_range(_Key_val); } - template - pair equal_range(const _K& _X) + template + pair equal_range(const _OtherKey& _Key_val) requires _Is_transparent_v { - return _Equal_range(_X); + return _Equal_range(_Key_val); } - pair equal_range(const key_type& _X) const { - return _Equal_range(_X); + pair equal_range(const key_type& _Key_val) const { + return _Equal_range(_Key_val); } - template - pair equal_range(const _K& _X) const + template + pair equal_range(const _OtherKey& _Key_val) const requires _Is_transparent_v { - return _Equal_range(_X); + return _Equal_range(_Key_val); } - friend bool operator==(const _Derived& _X, const _Derived& _Y) { - return _RANGES equal(_X._Data.keys, _Y._Data.keys) && _RANGES equal(_X._Data.values, _Y._Data.values); + friend bool operator==(const _Derived& _Left, const _Derived& _Right) { + return _RANGES equal(_Left._Data.keys, _Right._Data.keys) + && _RANGES equal(_Left._Data.values, _Right._Data.values); } - friend auto operator<=>(const _Derived& _X, const _Derived& _Y) { + friend auto operator<=>(const _Derived& _Left, const _Derived& _Right) { return _STD lexicographical_compare_three_way( - _X.cbegin(), _X.cend(), _Y.cbegin(), _Y.cend(), _Synth_three_way{}); + _Left.cbegin(), _Left.cend(), _Right.cbegin(), _Right.cend(), _Synth_three_way{}); } - friend void swap(_Derived& _X, _Derived& _Y) noexcept { - _X.swap(_Y); + friend void swap(_Derived& _Left, _Derived& _Right) noexcept { + _Left.swap(_Right); } @@ -833,18 +839,18 @@ private: key_compare _Key_compare; containers _Data; - template - requires (same_as, key_type> && same_as, key_type>) - || (constructible_from && constructible_from + template + requires (same_as, key_type> && same_as, key_type>) + || (constructible_from && constructible_from && _Is_transparent_v) - bool _Key_equal(_K1&& _X, _K2&& _Y) const { - return !_Key_compare(_STD forward<_K1>(_X), _STD forward<_K2>(_Y)) - && !_Key_compare(_STD forward<_K2>(_Y), _STD forward<_K1>(_X)); + bool _Key_equal(_KeyTy1&& _Left, _KeyTy2&& _Right) const { + return !_Key_compare(_STD forward<_KeyTy1>(_Left), _STD forward<_KeyTy2>(_Right)) + && !_Key_compare(_STD forward<_KeyTy2>(_Right), _STD forward<_KeyTy1>(_Left)); } auto _View_to_sort() { - using _Sorting_iterator = _Paring_iterator_provider::_Iterator; + using _Sorting_iterator = _Pairing_iterator_provider::_Iterator; return _RANGES subrange<_Sorting_iterator>{_Sorting_iterator{_Data.keys.begin(), _Data.values.begin()}, _Sorting_iterator{_Data.keys.end(), _Data.values.end()}}; } @@ -858,28 +864,29 @@ private: void _Dedup() { _Clear_flat_map_scope_guard _Guard{this}; auto _Sorted_view = _View_to_sort(); - auto _Subrange = _RANGES unique(_Sorted_view, - [this](const_reference _X, const_reference _Y) { return this->_Key_equal(_X.first, _Y.first); }); + auto _Subrange = _RANGES unique(_Sorted_view, [this](const_reference _Left, const_reference _Right) { + return this->_Key_equal(_Left.first, _Right.first); + }); auto _Remaining_count = _STD distance(_Sorted_view.begin(), _Subrange.begin()); _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); _Data.values.erase(_Data.values.begin() + _Remaining_count, _Data.values.end()); _Guard._Clearable = nullptr; } - void _Insert_exact(const_iterator _Position, key_type&& _Key_val, mapped_type&& _Mapped) { + void _Insert_exact(const_iterator _Position, key_type&& _Key_val, mapped_type&& _Mapped_val) { _Clear_flat_map_scope_guard _Guard{this}; _Data.keys.insert(_Position._Key_it, _STD move(_Key_val)); - _Data.values.insert(_Position._Mapped_it, _STD move(_Mapped)); + _Data.values.insert(_Position._Mapped_it, _STD move(_Mapped_val)); _Guard._Clearable = nullptr; } - template - iterator _Emplace_hint(const_iterator _Position, _K&& _Key_val, _Mapped_args_t&&... _Args) - requires is_constructible_v - && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) + template + iterator _Emplace_hint(const_iterator _Position, _OtherKey&& _Key_val, _MappedArgTypes&&... _Args) + requires is_constructible_v + && (same_as, key_type> + || (constructible_from && _Is_transparent_v) ) { - static_assert(!(_Multi && _Overwrite_if_exists), + static_assert(!(_Multi && _OverwriteIfExists), "Overwriting is not supported when the container allows multiple copies of a key."); const const_iterator _Begin = cbegin(); const const_iterator _End = cend(); @@ -897,29 +904,29 @@ private: if (_Hint_is_accurate) { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); - _Insert_exact( - _Position, key_type{_STD forward<_K>(_Key_val)}, mapped_type{_STD forward<_Mapped_args_t>(_Args)...}); + _Insert_exact(_Position, key_type{_STD forward<_OtherKey>(_Key_val)}, + mapped_type{_STD forward<_MappedArgTypes>(_Args)...}); return begin() + _Dist; } else { - if constexpr (_Overwrite_if_exists) { + if constexpr (_OverwriteIfExists) { if (_Key_equal(_Key_val, *(_Position._Key_it))) { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); auto _It = begin() + _Dist; - *(_It._Mapped_it) = mapped_type{_STD forward<_Mapped_args_t>(_Args)...}; + *(_It._Mapped_it) = mapped_type{_STD forward<_MappedArgTypes>(_Args)...}; return _It; } } _Position = lower_bound(_Key_val); - if (_Overwrite_if_exists && _Position != _End && _Key_equal(_Key_val, *(_Position._Key_it))) { + if (_OverwriteIfExists && _Position != _End && _Key_equal(_Key_val, *(_Position._Key_it))) { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); auto _It = begin() + _Dist; - *(_It._Mapped_it) = mapped_type{_STD forward<_Mapped_args_t>(_Args)...}; + *(_It._Mapped_it) = mapped_type{_STD forward<_MappedArgTypes>(_Args)...}; return _It; } else { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); - _Insert_exact(_Position, key_type{_STD forward<_K>(_Key_val)}, - mapped_type{_STD forward<_Mapped_args_t>(_Args)...}); + _Insert_exact(_Position, key_type{_STD forward<_OtherKey>(_Key_val)}, + mapped_type{_STD forward<_MappedArgTypes>(_Args)...}); return begin() + _Dist; } } @@ -960,9 +967,9 @@ private: _Guard._Clearable = nullptr; } - template - _NODISCARD mapped_type& _At(const _K& _Key_val) - requires same_as<_K, key_type> || _Is_transparent_v + template + _NODISCARD mapped_type& _At(const _KeyTy& _Key_val) + requires same_as<_KeyTy, key_type> || _Is_transparent_v { iterator _Position = find(_Key_val); if (_Position == end()) { @@ -972,104 +979,104 @@ private: } } - template - iterator _Find(const _K& _X) - requires same_as<_K, key_type> || _Is_transparent_v + template + iterator _Find(const _KeyTy& _Key_val) + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - iterator _Position = lower_bound(_X); - if (_Position != end() && _Key_equal(_Position->first, _X)) { + iterator _Position = lower_bound(_Key_val); + if (_Position != end() && _Key_equal(_Position->first, _Key_val)) { return _Position; } else { return end(); } } - template - const_iterator _Find(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + template + const_iterator _Find(const _KeyTy& _Key_val) const + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - const_iterator _Position = lower_bound(_X); - if (_Position != cend() && _Key_equal(_Position->first, _X)) { + const_iterator _Position = lower_bound(_Key_val); + if (_Position != cend() && _Key_equal(_Position->first, _Key_val)) { return _Position; } else { return cend(); } } - template - size_type _Count(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + template + size_type _Count(const _KeyTy& _Key_val) const + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - return upper_bound(_X) - lower_bound(_X); + return upper_bound(_Key_val) - lower_bound(_Key_val); } - template - bool _Contains(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + template + bool _Contains(const _KeyTy& _Key_val) const + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - return find(_X) != cend(); + return find(_Key_val) != cend(); } - template - iterator _Lower_bound(const _K& _X) - requires same_as<_K, key_type> || _Is_transparent_v + template + iterator _Lower_bound(const _KeyTy& _Key_val) + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - auto _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _Key_val, _Key_compare); auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); auto _Val_it = _Data.values.begin() + _Dist; return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } - template - const_iterator _Lower_bound(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + template + const_iterator _Lower_bound(const _KeyTy& _Key_val) const + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - auto _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _Key_val, _Key_compare); auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); auto _Val_it = _Data.values.cbegin() + _Dist; return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; } - template - iterator _Upper_bound(const _K& _X) - requires same_as<_K, key_type> || _Is_transparent_v + template + iterator _Upper_bound(const _KeyTy& _Key_val) + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - auto _Key_it = _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Key_it = _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _Key_val, _Key_compare); auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); auto _Val_it = _Data.values.begin() + _Dist; return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } - template - const_iterator _Upper_bound(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + template + const_iterator _Upper_bound(const _KeyTy& _Key_val) const + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - auto _Key_it = _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Key_it = _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _Key_val, _Key_compare); auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); auto _Val_it = _Data.values.cbegin() + _Dist; return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; } - template - pair _Equal_range(const _K& _X) - requires same_as<_K, key_type> || _Is_transparent_v + template + pair _Equal_range(const _KeyTy& _Key_val) + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - return {lower_bound(_X), upper_bound(_X)}; + return {lower_bound(_Key_val), upper_bound(_Key_val)}; } - template - pair _Equal_range(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + template + pair _Equal_range(const _KeyTy& _Key_val) const + requires same_as<_KeyTy, key_type> || _Is_transparent_v { - return {lower_bound(_X), upper_bound(_X)}; + return {lower_bound(_Key_val), upper_bound(_Key_val)}; } }; template -class flat_map : public _Flat_Map_Base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, false, +class flat_map : public _Flat_map_base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, false, flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>> { private: - using _MyBase = _Flat_Map_Base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, false, + using _MyBase = _Flat_map_base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, false, flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>>; public: @@ -1078,10 +1085,10 @@ public: }; template -class flat_multimap : public _Flat_Map_Base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, true, +class flat_multimap : public _Flat_map_base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, true, flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>> { private: - using _MyBase = _Flat_Map_Base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, true, + using _MyBase = _Flat_map_base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, true, flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>>; public: @@ -1090,33 +1097,33 @@ public: }; template _Compare = less> + _Valid_compare_for_container<_KeyContainer> _Compare = less> flat_map(_KeyContainer, _MappedContainer, _Compare = _Compare()) -> flat_map; template _Allocator> + _Valid_allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> flat_map(_KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; -template _Compare, - _Valid_Allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> +template _Compare, + _Valid_allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> flat_map(_KeyContainer, _MappedContainer, _Compare, _Allocator) -> flat_map; template _Compare = less> + _Valid_compare_for_container<_KeyContainer> _Compare = less> flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare = _Compare()) -> flat_map; template _Allocator> + _Valid_allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; -template _Compare, - _Valid_Allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> +template _Compare, + _Valid_allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare, _Allocator) -> flat_map; @@ -1131,37 +1138,38 @@ flat_map(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare()) -> flat_map::first_type, typename iter_value_t<_InputIterator>::second_type, _Compare>; -template <_RANGES input_range _R, class _Compare = less::first_type>, +template <_RANGES input_range _Rng, class _Compare = less::first_type>, class _Allocator = allocator> -flat_map(from_range_t, _R&&, _Compare = _Compare(), _Allocator = _Allocator()) - -> flat_map::first_type, typename _RANGES range_value_t<_R>::second_type, +flat_map(from_range_t, _Rng&&, _Compare = _Compare(), _Allocator = _Allocator()) + -> flat_map::first_type, typename _RANGES range_value_t<_Rng>::second_type, _Compare, - vector::first_type, - _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_R>::first_type>>, - vector::second_type, - _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_R>::second_type>>>; - -template <_RANGES input_range _R, class _Allocator> -flat_map(from_range_t, _R&&, _Allocator) -> flat_map::first_type, - typename _RANGES range_value_t<_R>::second_type, less::first_type>, - vector::first_type, - _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_R>::first_type>>, - vector::second_type, - _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_R>::second_type>>>; - -template > -flat_map(initializer_list>, _Compare = _Compare()) -> flat_map<_Key, _T, _Compare>; - -template > -flat_map(sorted_unique_t, initializer_list>, _Compare = _Compare()) -> flat_map<_Key, _T, _Compare>; + vector::first_type, + _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_Rng>::first_type>>, + vector::second_type, + _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_Rng>::second_type>>>; + +template <_RANGES input_range _Rng, class _Allocator> +flat_map(from_range_t, _Rng&&, _Allocator) -> flat_map::first_type, + typename _RANGES range_value_t<_Rng>::second_type, less::first_type>, + vector::first_type, + _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_Rng>::first_type>>, + vector::second_type, + _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_Rng>::second_type>>>; + +template > +flat_map(initializer_list>, _Compare = _Compare()) -> flat_map<_Key, _Mapped, _Compare>; + +template > +flat_map(sorted_unique_t, initializer_list>, _Compare = _Compare()) + -> flat_map<_Key, _Mapped, _Compare>; // Specialization of uses_allocator -template -struct uses_allocator, _Allocator> +template +struct uses_allocator, _Allocator> : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; -template -struct uses_allocator, _Allocator> +template +struct uses_allocator, _Allocator> : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; _STD_END From 6aef7535c27efb6d6710ada8dc17049cbb78eaef Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 22 Jan 2024 07:35:08 +0800 Subject: [PATCH 02/11] Cleanup for `P0429R9_flat_map/test.cpp` - Get rid of `&=` on `bool`. - Make comparison operator defaulted as possible. --- tests/std/tests/P0429R9_flat_map/test.cpp | 38 +++++++++-------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp index b5cfda070f3..639e40b05df 100644 --- a/tests/std/tests/P0429R9_flat_map/test.cpp +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -28,20 +28,18 @@ bool check_container_requirements(T&&) { template consteval bool check_reversible_container_requirements() { using map_t = remove_cvref_t; - bool result = true; - result &= is_same_v, typename map_t::reverse_iterator>; - result &= is_same_v, typename map_t::const_reverse_iterator>; - result &= is_same_v().begin()), typename map_t::iterator>; - result &= is_same_v().end()), typename map_t::iterator>; - result &= is_same_v().cbegin()), typename map_t::const_iterator>; - result &= is_same_v().cend()), typename map_t::const_iterator>; - result &= is_same_v().rbegin()), typename map_t::reverse_iterator>; - result &= is_same_v().rend()), typename map_t::reverse_iterator>; - result &= is_same_v().crbegin()), typename map_t::const_reverse_iterator>; - result &= is_same_v().crend()), typename map_t::const_reverse_iterator>; - result &= is_convertible_v; - result &= is_convertible_v; - return result; + return is_same_v, typename map_t::reverse_iterator> + && is_same_v, typename map_t::const_reverse_iterator> + && is_same_v().begin()), typename map_t::iterator> + && is_same_v().end()), typename map_t::iterator> + && is_same_v().cbegin()), typename map_t::const_iterator> + && is_same_v().cend()), typename map_t::const_iterator> + && is_same_v().rbegin()), typename map_t::reverse_iterator> + && is_same_v().rend()), typename map_t::reverse_iterator> + && is_same_v().crbegin()), typename map_t::const_reverse_iterator> + && is_same_v().crend()), typename map_t::const_reverse_iterator> + && is_convertible_v + && is_convertible_v; } template @@ -120,21 +118,13 @@ class Packaged { value = t; } - friend bool operator==(const Packaged& lhs, const Packaged& rhs) { - return lhs.value == rhs.value; - } + friend bool operator==(const Packaged&, const Packaged&) = default; friend bool operator==(const Packaged& lhs, const T& rhs) { return lhs.value == rhs; } - friend bool operator==(const T& lhs, const Packaged& rhs) { - return lhs == rhs.value; - } - - friend auto operator<=>(const Packaged& lhs, const Packaged& rhs) { - return lhs.value <=> rhs.value; - } + friend auto operator<=>(const Packaged&, const Packaged&) = default; }; template From c7bc65758192ad734c01c7c98ea3c602e00b26bd Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 23 Jan 2024 01:31:28 +0800 Subject: [PATCH 03/11] Try to fix overloads for `flat_map`/`flat_multi_map` And fix some bad names. --- stl/inc/flat_map | 381 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 266 insertions(+), 115 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 6eef90d0655..be79b127cbe 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -513,56 +513,27 @@ public: return _STD min(_Data.keys.max_size(), _Data.values.max_size()); } - // [flat.map.access] Access - template - _NODISCARD mapped_type& operator[](_OtherKey&& _Key_val) - requires same_as, key_type> - || (_Is_transparent_v && constructible_from) - { - return try_emplace(_STD forward<_OtherKey>(_Key_val)).first->second; - } - - _NODISCARD mapped_type& at(const key_type& _Key_val) { - return _At(_Key_val); - } - - template - _NODISCARD const mapped_type& at(const _OtherKey& _Key_val) const - requires _Is_transparent_v - { - return _At(_Key_val); - } - - // [flat.map.modifiers] Modifiers - template - pair emplace(_MappedArgTypes&&... _Args) - requires is_constructible_v + template + iterator emplace_hint(const_iterator _Position, _ArgTypes&&... _Args) + requires is_constructible_v { - value_type _Val(_STD forward<_MappedArgTypes>(_Args)...); - return try_emplace(_STD move(_Val.first), _STD move(_Val.second)); + value_type _Val(_STD forward<_ArgTypes>(_Args)...); + return _Emplace_hint(_Position, _STD move(_Val.first), _STD move(_Val.second)); } - template - iterator emplace_hint(const_iterator _Position, _MappedArgTypes&&... _Args) - requires is_constructible_v - { - value_type _Val(_STD forward<_MappedArgTypes>(_Args)...); - - return _Emplace_hint(_Position, _STD move(_Val.first), _STD move(_Val.second)); + iterator insert(const_iterator _Position, const value_type& _Pair_val) { + return emplace_hint(_Position, _Pair_val); } - template - pair insert(_MappedTy&& _Mapped_val) - requires (same_as, value_type> || constructible_from) - { - return emplace(_STD forward<_MappedTy>(_Mapped_val)); + iterator insert(const_iterator _Position, value_type&& _Pair_val) { + return emplace_hint(_Position, _STD move(_Pair_val)); } - template - iterator insert(const_iterator _Position, _MappedTy&& _Mapped_val) - requires (same_as, value_type> || constructible_from) + template + iterator insert(const_iterator _Position, _PairValTy&& _Pair_val) + requires is_constructible_v { - return emplace_hint(_Position, _STD forward<_MappedTy>(_Mapped_val)); + return emplace_hint(_Position, _STD forward<_PairValTy>(_Pair_val)); } template @@ -590,63 +561,6 @@ public: insert(_Tag, _Ilist.begin(), _Ilist.end()); } - template - pair try_emplace(_OtherKey&& _Key_val, _MappedArgTypes&&... _Mapped_args) - requires constructible_from - && (same_as, key_type> - || (constructible_from && _Is_transparent_v - && !convertible_to<_OtherKey &&, const_iterator> && !convertible_to<_OtherKey &&, iterator>) ) - { - auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key_val, _Key_compare); - if (_Key_it != _Data.keys.end() && _Key_equal(*_Key_it, _STD forward<_OtherKey>(_Key_val))) { - // Already exists - return {begin() + _STD distance(_Data.keys.begin(), _Key_it), false}; - } else { - // Need to insert - auto _Index = _STD distance(_Data.keys.begin(), _Key_it); - _Insert_exact(cbegin() + _Index, key_type{_STD forward<_OtherKey>(_Key_val)}, - mapped_type{_STD forward<_MappedArgTypes>(_Mapped_args)...}); - return {begin() + _Index, true}; - } - } - - template - iterator try_emplace(const_iterator _Position, _OtherKey&& _Key_val, _MappedArgTypes&&... _Mapped_args) - requires constructible_from - && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) - { - return _Emplace_hint( - _Position, _STD forward<_OtherKey>(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)...); - } - - template - pair insert_or_assign(_OtherKey&& _Key_val, _MappedTy&& _Mapped_val) - requires assignable_from && constructible_from - && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) - { - auto _Res = try_emplace(_STD forward<_OtherKey>(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); - if (_Res.second) { - // Insertion took place - return _Res; - } else { - // Already exists - *(_Res.first._Mapped_it) = _STD forward<_MappedTy>(_Mapped_val); - return _Res; - } - } - - template - iterator insert_or_assign(const_iterator _Position, _OtherKey&& _Key_val, _MappedTy&& _Mapped_val) - requires assignable_from && constructible_from - && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) - { - return _Emplace_hint( - _Position, _STD forward<_OtherKey>(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); - } - iterator erase(iterator _Position) { return erase(static_cast(_Position)); } @@ -835,10 +749,11 @@ public: } -private: +protected: key_compare _Key_compare; containers _Data; +private: template requires (same_as, key_type> && same_as, key_type>) || (constructible_from && constructible_from @@ -880,20 +795,20 @@ private: _Guard._Clearable = nullptr; } - template + template iterator _Emplace_hint(const_iterator _Position, _OtherKey&& _Key_val, _MappedArgTypes&&... _Args) requires is_constructible_v && (same_as, key_type> || (constructible_from && _Is_transparent_v) ) { - static_assert(!(_Multi && _OverwriteIfExists), + static_assert(!(_IsMulti && _OverwriteIfExists), "Overwriting is not supported when the container allows multiple copies of a key."); const const_iterator _Begin = cbegin(); const const_iterator _End = cend(); bool _Insert_before_position = false; bool _Insert_after_position_minus_1 = false; - if constexpr (_Multi) { + if constexpr (_IsMulti) { _Insert_before_position = (_Position == _End) || !_Key_compare(*(_Position._Key_it), _Key_val); _Insert_after_position_minus_1 = (_Position == _Begin) || !_Key_compare(_Key_val, *(_Position._Key_it - 1)); } else { @@ -967,18 +882,6 @@ private: _Guard._Clearable = nullptr; } - template - _NODISCARD mapped_type& _At(const _KeyTy& _Key_val) - requires same_as<_KeyTy, key_type> || _Is_transparent_v - { - iterator _Position = find(_Key_val); - if (_Position == end()) { - _Xout_of_range("std::flat_map::at: the specified key does not exist."); - } else { - return _Position->second; - } - } - template iterator _Find(const _KeyTy& _Key_val) requires same_as<_KeyTy, key_type> || _Is_transparent_v @@ -1079,9 +982,218 @@ private: using _MyBase = _Flat_map_base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, false, flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>>; + using _MyBase::_Data; + using _MyBase::_Key_compare; + public: + using typename _MyBase::const_iterator; + using typename _MyBase::iterator; + using typename _MyBase::key_compare; + using typename _MyBase::key_type; + using typename _MyBase::mapped_type; + using typename _MyBase::value_type; + using _MyBase::_MyBase; using _MyBase::operator=; + + // [flat.map.access] Access + _NODISCARD mapped_type& operator[](const key_type& _Key_val) { + return this->try_emplace(_Key_val).first->second; + } + _NODISCARD mapped_type& operator[](key_type&& _Key_val) { + return this->try_emplace(_STD move(_Key_val)).first->second; + } + + template + _NODISCARD mapped_type& operator[](_OtherKey&& _Key_val) + requires _Is_transparent_v + { + return this->try_emplace(_STD forward<_OtherKey>(_Key_val)).first->second; + } + + _NODISCARD mapped_type& at(const key_type& _Key_val) { + return _At(_Key_val); + } + + _NODISCARD const mapped_type& at(const key_type& _Key_val) const { + return _At(_Key_val); + } + + template + _NODISCARD mapped_type& at(const _OtherKey& _Key_val) + requires _Is_transparent_v + { + return _At(_Key_val); + } + + template + _NODISCARD const mapped_type& at(const _OtherKey& _Key_val) const + requires _Is_transparent_v + { + return _At(_Key_val); + } + + // [flat.map.modifiers] Modifiers + template + pair emplace(_ArgTypes&&... _Args) + requires is_constructible_v + { + value_type _Val(_STD forward<_ArgTypes>(_Args)...); + return try_emplace(_STD move(_Val.first), _STD move(_Val.second)); + } + + pair insert(const value_type& _Pair_val) { + return try_emplace(_Pair_val.first, _Pair_val.second); + } + + pair insert(value_type&& _Pair_val) { + return try_emplace(_STD move(_Pair_val.first), _STD move(_Pair_val.second)); + } + + template + pair insert(_PairValTy&& _Pair_val) + requires is_constructible_v + { + return emplace(_STD forward<_PairValTy>(_Pair_val)); + } + + template + requires is_constructible_v + pair try_emplace(const key_type& _Key_val, _MappedArgTypes&&... _Mapped_args) { + return _Try_emplace(_Key_val, _STD forward<_MappedArgTypes>(_Mapped_args)); + } + + template + requires is_constructible_v + pair try_emplace(key_type&& _Key_val, _MappedArgTypes&&... _Mapped_args) { + return _Try_emplace(_STD move(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)); + } + + template + requires _Is_transparent_v && is_constructible_v + && is_constructible_v + && (!is_convertible_v<_OtherKey, const_iterator>) && (!is_convertible_v<_OtherKey, iterator>) + pair try_emplace(_OtherKey&& _Key_val, _MappedArgTypes&&... _Mapped_args) { + return _Try_emplace(_STD forward<_OtherKey>(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)); + } + + template + iterator try_emplace(const_iterator _Position, const key_type&& _Key_val, _MappedArgTypes&&... _Mapped_args) + requires is_constructible_v + { + return this->_Emplace_hint(_Position, _Key_val, _STD forward<_MappedArgTypes>(_Mapped_args)...); + } + + template + iterator try_emplace(const_iterator _Position, key_type&& _Key_val, _MappedArgTypes&&... _Mapped_args) + requires is_constructible_v + { + return this->_Emplace_hint( + _Position, _STD move(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)...); + } + + template + iterator try_emplace(const_iterator _Position, _OtherKey&& _Key_val, _MappedArgTypes&&... _Mapped_args) + requires _Is_transparent_v && is_constructible_v + && is_constructible_v + { + return this->_Emplace_hint( + _Position, _STD forward<_OtherKey>(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)...); + } + + template + pair insert_or_assign(const key_type& _Key_val, _MappedTy&& _Mapped_val) + requires is_assignable_v && is_constructible_v + { + return _Insert_or_assign(_Key_val, _STD forward<_MappedTy>(_Mapped_val)); + } + + template + pair insert_or_assign(key_type&& _Key_val, _MappedTy&& _Mapped_val) + requires is_assignable_v && is_constructible_v + { + return _Insert_or_assign(_STD move(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); + } + + template + pair insert_or_assign(_OtherKey&& _Key_val, _MappedTy&& _Mapped_val) + requires _Is_transparent_v && is_constructible_v + && is_assignable_v && is_constructible_v + { + return _Insert_or_assign(_STD forward<_OtherKey>(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); + } + + template + iterator insert_or_assign(const_iterator _Position, const key_type& _Key_val, _MappedTy&& _Mapped_val) + requires is_assignable_v && is_constructible_v + { + return this->_Emplace_hint(_Position, _Key_val, _STD forward<_MappedTy>(_Mapped_val)); + } + + template + iterator insert_or_assign(const_iterator _Position, key_type&& _Key_val, _MappedTy&& _Mapped_val) + requires is_assignable_v && is_constructible_v + { + return this->_Emplace_hint(_Position, _STD move(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); + } + + template + iterator insert_or_assign(const_iterator _Position, _OtherKey&& _Key_val, _MappedTy&& _Mapped_val) + requires _Is_transparent_v && is_constructible_v + && is_assignable_v && is_constructible_v + { + return this->_Emplace_hint( + _Position, _STD forward<_OtherKey>(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); + } + +private: + template + _NODISCARD mapped_type& _At(const _KeyTy& _Key_val) + requires same_as<_KeyTy, key_type> || _Is_transparent_v + { + const auto _Position = this->find(_Key_val); + if (_Position == this->end()) { + _Xout_of_range("std::flat_map::at: the specified key does not exist."); + } else { + return _Position->second; + } + } + + template + _NODISCARD const mapped_type& _At(const _KeyTy& _Key_val) const + requires same_as<_KeyTy, key_type> || _Is_transparent_v + { + const auto _Position = this->find(_Key_val); + if (_Position == this->end()) { + _Xout_of_range("std::flat_map::at: the specified key does not exist."); + } else { + return _Position->second; + } + } + + template + pair _Try_emplace(_KeyTy&& _Key_val, _MappedArgTypes&&... _Mapped_args) { + auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key_val, _Key_compare); + if (_Key_it != _Data.keys.end() && _Key_equal(*_Key_it, _STD forward<_KeyTy>(_Key_val))) { + // Already exists + return {this->begin() + _STD distance(_Data.keys.begin(), _Key_it), false}; + } else { + // Need to insert + auto _Index = _STD distance(_Data.keys.begin(), _Key_it); + this->_Insert_exact(this->cbegin() + _Index, key_type{_STD forward<_KeyTy>(_Key_val)}, + mapped_type{_STD forward<_MappedArgTypes>(_Mapped_args)...}); + return {this->begin() + _Index, true}; + } + } + + template + pair _Insert_or_assign(_KeyTy&& _Key_val, _MappedTy&& _Mapped_val) { + auto _Res = _Try_emplace(_STD forward<_KeyTy>(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); + if (!_Res.second) { // Already exists + _Res.first->second = _STD forward<_MappedTy>(_Mapped_val); + } + return _Res; + } }; template @@ -1091,9 +1203,48 @@ private: using _MyBase = _Flat_map_base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, true, flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>>; + using _MyBase::_Data; + using _MyBase::_Key_compare; + public: + using typename _MyBase::iterator; + using typename _MyBase::value_type; + using _MyBase::_MyBase; using _MyBase::operator=; + + // [flat.multimap.modifiers] Modifiers + template + iterator emplace(_ArgTypes&&... _Args) { + value_type _Val(_STD forward<_ArgTypes>(_Args)...); + return _Emplace_key_mapped(_STD move(_Val.first), _STD move(_Val.second)); + } + + iterator insert(const value_type& _Px) { + return _Emplace_key_mapped(_Px.first, _Px.second); + } + + iterator insert(value_type&& _Px) { + return _Emplace_key_mapped(_STD move(_Px.first), _STD move(_Px.second)); + } + + template + iterator insert(_PairValTy&& _Pair_val) + requires is_constructible_v + { + return emplace(_STD forward<_PairValTy>(_Pair_val)); + } + +private: + template + iterator _Emplace_key_mapped(_KeyTy&& _Key_val, _MappedTy&& _Mapped_val) { + auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key_val, _Key_compare); + auto _Index = _STD distance(_Data.keys.begin(), _Key_it); + + this->_Insert_exact( + this->cbegin() + _Index, _STD forward<_KeyTy>(_Key_val), _STD forward<_MappedTy>(_Mapped_val)); + return this->begin() + _Index; + } }; template Date: Tue, 23 Jan 2024 01:53:39 +0800 Subject: [PATCH 04/11] Fix and complete deduction guides And replace the non-uglified name `Allocator` with `_Allocator` --- stl/inc/flat_map | 212 ++++++++++++++++++++++++++++------------------- 1 file changed, 128 insertions(+), 84 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index be79b127cbe..8a4fe585ea1 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -276,11 +276,11 @@ public: explicit _Flat_map_base(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} _Flat_map_base() : _Flat_map_base(key_compare()) {} - template <_Valid_allocator_for_flat_map Allocator> - explicit _Flat_map_base(const Allocator& _Alloc) : _Flat_map_base(key_compare(), _Alloc) {} + template <_Valid_allocator_for_flat_map _Allocator> + explicit _Flat_map_base(const _Allocator& _Alloc) : _Flat_map_base(key_compare(), _Alloc) {} - template <_Valid_allocator_for_flat_map Allocator> - explicit _Flat_map_base(const key_compare& _Comp, const Allocator& _Alloc) + template <_Valid_allocator_for_flat_map _Allocator> + explicit _Flat_map_base(const key_compare& _Comp, const _Allocator& _Alloc) : _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc), .values = _STD make_obj_using_allocator(_Alloc)} {} @@ -293,9 +293,9 @@ public: } } - template <_Valid_allocator_for_flat_map Allocator> + template <_Valid_allocator_for_flat_map _Allocator> _Flat_map_base( - const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) + const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const _Allocator& _Alloc) : _Flat_map_base(_Sorted_t(), _Key_cont, _Mapped_cont, _Alloc) { _Sort(); if constexpr (!_IsMulti) { @@ -303,9 +303,9 @@ public: } } - template <_Valid_allocator_for_flat_map Allocator> + template <_Valid_allocator_for_flat_map _Allocator> _Flat_map_base(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, - const key_compare& _Comp, const Allocator& _Alloc) + const key_compare& _Comp, const _Allocator& _Alloc) : _Flat_map_base(_Sorted_t(), _Key_cont, _Mapped_cont, _Comp, _Alloc) { _Sort(); if constexpr (!_IsMulti) { @@ -317,16 +317,16 @@ public: const key_compare& _Comp = key_compare()) : _Key_compare(_Comp), _Data{.keys = _STD move(_Key_cont), .values = _STD move(_Mapped_cont)} {} - template <_Valid_allocator_for_flat_map Allocator> + template <_Valid_allocator_for_flat_map _Allocator> _Flat_map_base(_Sorted_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, - const Allocator& _Alloc) + const _Allocator& _Alloc) : _Key_compare(key_compare()), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} - template <_Valid_allocator_for_flat_map Allocator> + template <_Valid_allocator_for_flat_map _Allocator> _Flat_map_base(_Sorted_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, - const key_compare& _Comp, const Allocator& _Alloc) + const key_compare& _Comp, const _Allocator& _Alloc) : _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} @@ -338,9 +338,9 @@ public: insert(_First, _Last); } - template Allocator> + template _Allocator> requires _Is_iterator_v<_InputIterator> - _Flat_map_base(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) + _Flat_map_base(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const _Allocator& _Alloc) : _Flat_map_base(_Comp, _Alloc) { insert(_First, _Last); } @@ -350,8 +350,8 @@ public: : _Flat_map_base(_From_range, _STD forward<_Rng>(_Range), key_compare()) {} template <_Container_compatible_range _Rng, - _Valid_allocator_for_flat_map Allocator> - _Flat_map_base(from_range_t _From_range, _Rng&& _Range, const Allocator& _Alloc) + _Valid_allocator_for_flat_map _Allocator> + _Flat_map_base(from_range_t _From_range, _Rng&& _Range, const _Allocator& _Alloc) : _Flat_map_base(_From_range, _STD forward<_Rng>(_Range), key_compare(), _Alloc) {} template <_Container_compatible_range _Rng> @@ -360,8 +360,8 @@ public: } template <_Container_compatible_range _Rng, - _Valid_allocator_for_flat_map Allocator> - _Flat_map_base(from_range_t, _Rng&& _Range, const key_compare& _Comp, const Allocator& _Alloc) + _Valid_allocator_for_flat_map _Allocator> + _Flat_map_base(from_range_t, _Rng&& _Range, const key_compare& _Comp, const _Allocator& _Alloc) : _Flat_map_base(_Comp, _Alloc) { insert_range(_STD forward<_Rng>(_Range)); } @@ -374,40 +374,40 @@ public: insert(_Tag, _First, _Last); } - template Allocator> + template _Allocator> requires _Is_iterator_v<_InputIterator> _Flat_map_base( - _Sorted_t _Tag, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) + _Sorted_t _Tag, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const _Allocator& _Alloc) : _Flat_map_base(_Comp, _Alloc) { insert(_Tag, _First, _Last); } - template Allocator> + template _Allocator> requires _Is_iterator_v<_InputIterator> - _Flat_map_base(_Sorted_t _Tag, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc) + _Flat_map_base(_Sorted_t _Tag, _InputIterator _First, _InputIterator _Last, const _Allocator& _Alloc) : _Flat_map_base(_Tag, _First, _Last, key_compare(), _Alloc) {} _Flat_map_base(initializer_list _Ilist, const key_compare& _Comp = key_compare()) : _Flat_map_base(_Ilist.begin(), _Ilist.end(), _Comp) {} - template <_Valid_allocator_for_flat_map Allocator> - _Flat_map_base(initializer_list _Ilist, const key_compare& _Comp, const Allocator& _Alloc) + template <_Valid_allocator_for_flat_map _Allocator> + _Flat_map_base(initializer_list _Ilist, const key_compare& _Comp, const _Allocator& _Alloc) : _Flat_map_base(_Ilist.begin(), _Ilist.end(), _Comp, _Alloc) {} - template <_Valid_allocator_for_flat_map Allocator> - _Flat_map_base(initializer_list _Ilist, const Allocator& _Alloc) + template <_Valid_allocator_for_flat_map _Allocator> + _Flat_map_base(initializer_list _Ilist, const _Allocator& _Alloc) : _Flat_map_base(_Ilist, key_compare(), _Alloc) {} _Flat_map_base(_Sorted_t _Tag, initializer_list _Ilist, const key_compare& _Comp = key_compare()) : _Flat_map_base(_Tag, _Ilist.begin(), _Ilist.end(), _Comp) {} - template <_Valid_allocator_for_flat_map Allocator> + template <_Valid_allocator_for_flat_map _Allocator> _Flat_map_base( - _Sorted_t _Tag, initializer_list _Ilist, const key_compare& _Comp, const Allocator& _Alloc) + _Sorted_t _Tag, initializer_list _Ilist, const key_compare& _Comp, const _Allocator& _Alloc) : _Flat_map_base(_Tag, _Ilist.begin(), _Ilist.end(), _Comp, _Alloc) {} - template <_Valid_allocator_for_flat_map Allocator> - _Flat_map_base(_Sorted_t _Tag, initializer_list _Ilist, const Allocator& _Alloc) + template <_Valid_allocator_for_flat_map _Allocator> + _Flat_map_base(_Sorted_t _Tag, initializer_list _Ilist, const _Allocator& _Alloc) : _Flat_map_base(_Tag, _Ilist, key_compare(), _Alloc) {} // Copy constructors @@ -1196,6 +1196,69 @@ private: } }; +template _Compare = less> +flat_map(_KeyContainer, _MappedContainer, _Compare = _Compare()) -> flat_map; + +template _Allocator> +flat_map(_KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; + +template _Compare, + _Valid_allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> +flat_map(_KeyContainer, _MappedContainer, _Compare, _Allocator) -> flat_map; + +template _Compare = less> +flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare = _Compare()) + -> flat_map; + +template _Allocator> +flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; + +template _Compare, + _Valid_allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> +flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare, _Allocator) + -> flat_map; + +template >> +flat_map(_InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_map<_Guide_key_t<_InputIterator>, _Guide_val_t<_InputIterator>, _Compare>; + +template >> +flat_map(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_map<_Guide_key_t<_InputIterator>, _Guide_val_t<_InputIterator>, _Compare>; + +template <_RANGES input_range _Rng, class _Compare = less<_Range_key_type<_Rng>>, class _Allocator = allocator> +flat_map(from_range_t, _Rng&&, _Compare = _Compare(), _Allocator = _Allocator()) + -> flat_map<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, _Compare, + vector<_Range_key_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_key_type<_Rng>>>, + vector<_Range_mapped_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_mapped_type<_Rng>>>>; + +template <_RANGES input_range _Rng, class _Allocator> +flat_map(from_range_t, _Rng&&, _Allocator) -> flat_map<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, + less<_Range_key_type<_Rng>>, vector<_Range_key_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_key_type<_Rng>>>, + vector<_Range_mapped_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_mapped_type<_Rng>>>>; + +template > +flat_map(initializer_list>, _Compare = _Compare()) -> flat_map<_Key, _Mapped, _Compare>; + +template > +flat_map(sorted_unique_t, initializer_list>, _Compare = _Compare()) + -> flat_map<_Key, _Mapped, _Compare>; + +// Specialization of uses_allocator +template +struct uses_allocator, _Allocator> + : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; + template class flat_multimap : public _Flat_map_base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, true, flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>> { @@ -1247,78 +1310,59 @@ private: } }; -template _Compare = less> -flat_map(_KeyContainer, _MappedContainer, _Compare = _Compare()) -> flat_map> +flat_multimap(_KeyContainer, _KeyContainer, _Compare = _Compare()) -> flat_multimap; -template _Allocator> -flat_map(_KeyContainer, _MappedContainer, _Allocator) -> flat_map +flat_multimap(_KeyContainer, _MappedContainer, _Allocator) -> flat_multimap, _KeyContainer, _MappedContainer>; - -template _Compare, - _Valid_allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> -flat_map(_KeyContainer, _MappedContainer, _Compare, _Allocator) -> flat_map; - -template _Compare = less> -flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare = _Compare()) - -> flat_map +flat_multimap(_KeyContainer, _MappedContainer, _Compare, _Allocator) + -> flat_multimap; -template _Allocator> -flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; +template > +flat_multimap(sorted_equivalent_t, _KeyContainer, _MappedContainer, _Compare = _Compare()) + -> flat_multimap; -template _Compare, - _Valid_allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> -flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare, _Allocator) - -> flat_map +flat_multimap(sorted_equivalent_t, _KeyContainer, _MappedContainer, _Allocator) + -> flat_multimap, _KeyContainer, _MappedContainer>; +template +flat_multimap(sorted_equivalent_t, _KeyContainer, _MappedContainer, _Compare, _Allocator) + -> flat_multimap; -template ::first_type>> -flat_map(_InputIterator, _InputIterator, _Compare = _Compare()) - -> flat_map::first_type, typename iter_value_t<_InputIterator>::second_type, - _Compare>; +template >> +flat_multimap(_InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_multimap<_Guide_key_t<_InputIterator>, _Guide_val_t<_InputIterator>, _Compare>; -template ::first_type>> -flat_map(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare()) - -> flat_map::first_type, typename iter_value_t<_InputIterator>::second_type, - _Compare>; +template >> +flat_multimap(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_multimap<_Guide_key_t<_InputIterator>, _Guide_val_t<_InputIterator>, _Compare>; -template <_RANGES input_range _Rng, class _Compare = less::first_type>, - class _Allocator = allocator> -flat_map(from_range_t, _Rng&&, _Compare = _Compare(), _Allocator = _Allocator()) - -> flat_map::first_type, typename _RANGES range_value_t<_Rng>::second_type, - _Compare, - vector::first_type, - _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_Rng>::first_type>>, - vector::second_type, - _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_Rng>::second_type>>>; +template <_RANGES input_range _Rng, class _Compare = less<_Range_key_type<_Rng>>, class _Allocator = allocator> +flat_multimap(from_range_t, _Rng&&, _Compare = _Compare(), _Allocator = _Allocator()) + -> flat_multimap<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, _Compare, + vector<_Range_key_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_key_type<_Rng>>>, + vector<_Range_mapped_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_mapped_type<_Rng>>>>; template <_RANGES input_range _Rng, class _Allocator> -flat_map(from_range_t, _Rng&&, _Allocator) -> flat_map::first_type, - typename _RANGES range_value_t<_Rng>::second_type, less::first_type>, - vector::first_type, - _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_Rng>::first_type>>, - vector::second_type, - _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_Rng>::second_type>>>; +flat_multimap(from_range_t, _Rng&&, _Allocator) -> flat_multimap<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, + less<_Range_key_type<_Rng>>, vector<_Range_key_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_key_type<_Rng>>>, + vector<_Range_mapped_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_mapped_type<_Rng>>>>; template > -flat_map(initializer_list>, _Compare = _Compare()) -> flat_map<_Key, _Mapped, _Compare>; +flat_multimap(initializer_list>, _Compare = _Compare()) -> flat_multimap<_Key, _Mapped, _Compare>; template > -flat_map(sorted_unique_t, initializer_list>, _Compare = _Compare()) - -> flat_map<_Key, _Mapped, _Compare>; +flat_multimap(sorted_equivalent_t, initializer_list>, _Compare = _Compare()) + -> flat_multimap<_Key, _Mapped, _Compare>; // Specialization of uses_allocator -template -struct uses_allocator, _Allocator> - : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; - template struct uses_allocator, _Allocator> : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; From d6083c106395f97e6e7ba44413a77322ceff94f0 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 23 Jan 2024 02:41:32 +0800 Subject: [PATCH 05/11] Missed fixes --- stl/inc/flat_map | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 8a4fe585ea1..646b76fe8d8 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -581,17 +581,15 @@ public: return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } + size_type erase(const key_type& _Key_val) { + return _Erase_key(_Key_val); + } + template - size_type erase(_OtherKey&& _Key_val) - requires convertible_to<_OtherKey&&, const key_type&> - || (_Is_transparent_v && !convertible_to<_OtherKey &&, iterator> - && !convertible_to<_OtherKey &&, const_iterator>) - { - const_iterator _Pos_begin = lower_bound(_STD forward<_OtherKey>(_Key_val)); - const_iterator _Pos_end = upper_bound(_STD forward<_OtherKey>(_Key_val)); - size_type _Count = _Pos_end - _Pos_begin; - erase(_Pos_begin, _Pos_end); - return _Count; + requires _Is_transparent_v + && (!is_convertible_v<_OtherKey, iterator>) && (!is_convertible_v<_OtherKey, const_iterator>) + size_type erase(_OtherKey&& _Key_val) { + return _Erase_key(_STD forward<_OtherKey>(_Key_val)); } containers extract() && { @@ -882,6 +880,15 @@ private: _Guard._Clearable = nullptr; } + template + size_type _Erase_key(_KeyTy&& _Key_val) { + const_iterator _Pos_begin = lower_bound(_STD forward<_KeyTy>(_Key_val)); + const_iterator _Pos_end = upper_bound(_STD forward<_KeyTy>(_Key_val)); + size_type _Count = _Pos_end - _Pos_begin; + erase(_Pos_begin, _Pos_end); + return _Count; + } + template iterator _Find(const _KeyTy& _Key_val) requires same_as<_KeyTy, key_type> || _Is_transparent_v @@ -1311,7 +1318,7 @@ private: }; template > -flat_multimap(_KeyContainer, _KeyContainer, _Compare = _Compare()) -> flat_multimap flat_multimap; template From 83699c752ac6e983453cd90de0d176195811f1d9 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 23 Jan 2024 02:41:53 +0800 Subject: [PATCH 06/11] Implement `erase_if`! --- stl/inc/flat_map | 49 +++++++++++++++++++++-- tests/std/tests/P0429R9_flat_map/test.cpp | 14 +++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 646b76fe8d8..09bf0f5e74b 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -751,6 +751,24 @@ protected: key_compare _Key_compare; containers _Data; + template + size_type _Erase_if(_Predicate _Pred) { + _Clear_flat_map_scope_guard<_Flat_map_base> _Guard{this}; + + auto _View = _View_to_mutate(); + auto _Mut_first = _View.begin(); + auto _Mut_last = _View.end(); + const auto _Old_size = size(); + + _STD _Seek_wrapped(_Mut_first, _RANGES remove_if(_View, _Pred).begin()); + + erase(const_iterator{_Mut_first._Key_it, _Mut_first._Mapped_it}, + const_iterator{_Mut_last._Key_it, _Mut_last._Mapped_it}); + + _Guard._Clearable = nullptr; + return _Old_size - size(); + } + private: template requires (same_as, key_type> && same_as, key_type>) @@ -761,7 +779,7 @@ private: && !_Key_compare(_STD forward<_KeyTy2>(_Right), _STD forward<_KeyTy1>(_Left)); } - auto _View_to_sort() { + auto _View_to_mutate() { using _Sorting_iterator = _Pairing_iterator_provider::_Iterator; return _RANGES subrange<_Sorting_iterator>{_Sorting_iterator{_Data.keys.begin(), _Data.values.begin()}, @@ -770,13 +788,13 @@ private: void _Sort() { _Clear_flat_map_scope_guard _Guard{this}; - _RANGES sort(_View_to_sort(), value_compare(_Key_compare)); + _RANGES sort(_View_to_mutate(), value_compare(_Key_compare)); _Guard._Clearable = nullptr; } void _Dedup() { _Clear_flat_map_scope_guard _Guard{this}; - auto _Sorted_view = _View_to_sort(); + auto _Sorted_view = _View_to_mutate(); auto _Subrange = _RANGES unique(_Sorted_view, [this](const_reference _Left, const_reference _Right) { return this->_Key_equal(_Left.first, _Right.first); }); @@ -863,7 +881,7 @@ private: } // Sort the newly inserted elements - auto _Sorted_view = _View_to_sort(); + auto _Sorted_view = _View_to_mutate(); if constexpr (_NeedSorting) { auto _Sorted_new_elements = _Sorted_view; _Sorted_new_elements.advance(_OldSize); @@ -1154,6 +1172,12 @@ public: } private: + using _MyBase::_Erase_if; + + template + friend typename flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>::size_type erase_if( + flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>&, _Predicate); + template _NODISCARD mapped_type& _At(const _KeyTy& _Key_val) requires same_as<_KeyTy, key_type> || _Is_transparent_v @@ -1266,6 +1290,13 @@ template , _Allocator> : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; +_EXPORT_STD template +typename flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>::size_type erase_if( + flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>& _Cont, _Predicate _Pred) { + return _Cont._Erase_if(_STD _Pass_fn(_Pred)); +} + template class flat_multimap : public _Flat_map_base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, true, flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>> { @@ -1306,6 +1337,10 @@ public: } private: + template + friend typename flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>::size_type erase_if( + flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>&, _Predicate); + template iterator _Emplace_key_mapped(_KeyTy&& _Key_val, _MappedTy&& _Mapped_val) { auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key_val, _Key_compare); @@ -1374,6 +1409,12 @@ template , _Allocator> : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; +_EXPORT_STD template +typename flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>::size_type erase_if( + flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>& _Cont, _Predicate _Pred) { + return _Cont._Erase_if(_STD _Pass_fn(_Pred)); +} _STD_END #pragma pop_macro("new") diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp index 639e40b05df..f48ae0a3876 100644 --- a/tests/std/tests/P0429R9_flat_map/test.cpp +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -236,6 +236,19 @@ void test_construction() { } } +void test_erase_if() { + { + vector keys = {0, 1, 2, 3, 4, 2}; + vector vals = {44, 2324, 635462, 433, 5, 7}; + flat_map fmap(keys, vals); + const auto erased_num = erase_if( + fmap, [](pair refpr) { return refpr.first % 2 == 0 && refpr.second % 2 != 0; }); + assert(erased_num == 1); + assert(fmap.size() == 4); + assert(check_key_content(fmap, {0, 1, 2, 3})); + assert(check_value_content(fmap, {44, 2324, 635462, 433})); + } +} struct Incomplete; template @@ -258,4 +271,5 @@ void test_pointer_to_incomplete_type() { int main() { test_construction(); test_pointer_to_incomplete_type(); + test_erase_if(); } From 1beb7f0087883273fb9e26ec3a303ad33e94a8d3 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 23 Jan 2024 02:56:43 +0800 Subject: [PATCH 07/11] Implement SCARY iterators --- stl/inc/flat_map | 55 +++++++++-------------- tests/std/tests/P0429R9_flat_map/test.cpp | 32 +++++++++++++ 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 09bf0f5e74b..8c91429d7cc 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -98,19 +98,8 @@ struct _NODISCARD _Clear_flat_map_scope_guard { // Implementation -enum class _Pairing_iterator_kind : unsigned char { - _Sort, - _Mutable, - _Const, -}; - -template +template struct _Pairing_iterator_provider { - using _Key_iterator_t = conditional_t<_Kind == _Pairing_iterator_kind::_Sort, typename _KeyContainer::iterator, - typename _KeyContainer::const_iterator>; - using _Mapped_iterator_t = conditional_t<_Kind == _Pairing_iterator_kind::_Const, - typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>; - class _Iterator { public: template && same_as<_Mapped, typename _MappedContainer::value_type> friend class _Flat_map_base; + _Iterator() = default; - _Iterator(_Key_iterator_t _Key_it, _Mapped_iterator_t _Mapped_it) : _Key_it(_Key_it), _Mapped_it(_Mapped_it) {} + _Iterator(_KeyIter _Key_iter, _MappedIter _Mapped_iter) : _Key_it(_Key_iter), _Mapped_it(_Mapped_iter) {} using iterator_category = input_iterator_tag; using iterator_concept = random_access_iterator_tag; using difference_type = ptrdiff_t; - using value_type = pair, iter_value_t<_Mapped_iterator_t>>; - using reference = pair, iter_reference_t<_Mapped_iterator_t>>; + using value_type = pair, iter_value_t<_MappedIter>>; + using reference = pair, iter_reference_t<_MappedIter>>; private: + using _Const_iterator = + typename _Pairing_iterator_provider<_KeyIter, _MappedConvIter, _MappedConvIter>::_Iterator; + class _Arrow_proxy { public: explicit _Arrow_proxy(const reference& _Rx) noexcept : _Ref{_Rx} {} @@ -219,20 +212,15 @@ struct _Pairing_iterator_provider { return _Right + _Off; } - private: - using _Const_iterator = - _Pairing_iterator_provider<_KeyContainer, _MappedContainer, _Pairing_iterator_kind::_Const>::_Iterator; - - public: operator _Const_iterator() const - requires (_Kind == _Pairing_iterator_kind::_Mutable) + requires (!is_same_v<_MappedIter, _MappedConvIter>) { return _Const_iterator{_Key_it, _Mapped_it}; } private: - _Key_iterator_t _Key_it; - _Mapped_iterator_t _Mapped_it; + _KeyIter _Key_it; + _MappedIter _Mapped_it; }; _STL_INTERNAL_STATIC_ASSERT(swappable<_Iterator>); @@ -258,10 +246,10 @@ public: using difference_type = ptrdiff_t; using key_container_type = _KeyContainer; using mapped_container_type = _MappedContainer; - using iterator = _Pairing_iterator_provider::_Iterator; - using const_iterator = _Pairing_iterator_provider::_Iterator; + using iterator = _Pairing_iterator_provider::_Iterator; + using const_iterator = _Pairing_iterator_provider::_Iterator; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; @@ -780,10 +768,10 @@ private: } auto _View_to_mutate() { - using _Sorting_iterator = _Pairing_iterator_provider::_Iterator; - return _RANGES subrange<_Sorting_iterator>{_Sorting_iterator{_Data.keys.begin(), _Data.values.begin()}, - _Sorting_iterator{_Data.keys.end(), _Data.values.end()}}; + using _Mutating_iterator = _Pairing_iterator_provider::_Iterator; + return _RANGES subrange<_Mutating_iterator>{_Mutating_iterator{_Data.keys.begin(), _Data.values.begin()}, + _Mutating_iterator{_Data.keys.end(), _Data.values.end()}}; } void _Sort() { @@ -1353,8 +1341,9 @@ private: }; template > -flat_multimap(_KeyContainer, _MappedContainer, _Compare = _Compare()) -> flat_multimap; +flat_multimap(_KeyContainer, _MappedContainer, _Compare = _Compare()) + -> flat_multimap; template flat_multimap(_KeyContainer, _MappedContainer, _Allocator) -> flat_multimap, shared_ptr>> fmap; } +// Test MSVC STL-specific SCARY-ness +namespace scary_test { + static_assert(is_same_v::iterator, flat_map>::iterator>); + static_assert(is_same_v::iterator, + flat_map, vector>, vector>>::iterator>); + static_assert(is_same_v::const_iterator, flat_map>::const_iterator>); + static_assert(is_same_v::const_iterator, + flat_map, vector>, vector>>::const_iterator>); + + static_assert(is_same_v::iterator, flat_multimap>::iterator>); + static_assert(is_same_v::iterator, + flat_multimap, vector>, vector>>::iterator>); + static_assert( + is_same_v::const_iterator, flat_multimap>::const_iterator>); + static_assert(is_same_v::const_iterator, + flat_multimap, vector>, vector>>::const_iterator>); + + static_assert(is_same_v::iterator, flat_multimap::iterator>); + static_assert(is_same_v::const_iterator, flat_multimap::const_iterator>); + + static_assert(is_same_v::containers, flat_map>::containers>); + static_assert(is_same_v::containers, flat_multimap>::containers>); + static_assert(is_same_v::containers, flat_multimap::containers>); + + static_assert(is_same_v::value_compare, + flat_map, vector>, vector>>::value_compare>); + static_assert(is_same_v::value_compare, + flat_multimap, vector>, + vector>>::value_compare>); + static_assert(is_same_v::value_compare, flat_multimap::value_compare>); +} // namespace scary_test + int main() { test_construction(); test_pointer_to_incomplete_type(); From f6b46c7c6a3e3f69c5e57f758ea77be692e89517 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 23 Jan 2024 07:14:22 +0800 Subject: [PATCH 08/11] Ensure that `_Erase_if` from the base class is made private --- stl/inc/flat_map | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 8c91429d7cc..312fba51b97 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1325,6 +1325,8 @@ public: } private: + using _MyBase::_Erase_if; + template friend typename flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>::size_type erase_if( flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>&, _Predicate); From 4c8e5aa5b6073ebc39caefc0cd3dbf6114615676 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 23 Jan 2024 09:13:37 +0800 Subject: [PATCH 09/11] Fix pack expansion and get rid of name shadowing --- stl/inc/flat_map | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 312fba51b97..101b8d11f6a 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1073,13 +1073,13 @@ public: template requires is_constructible_v pair try_emplace(const key_type& _Key_val, _MappedArgTypes&&... _Mapped_args) { - return _Try_emplace(_Key_val, _STD forward<_MappedArgTypes>(_Mapped_args)); + return _Try_emplace(_Key_val, _STD forward<_MappedArgTypes>(_Mapped_args)...); } template requires is_constructible_v pair try_emplace(key_type&& _Key_val, _MappedArgTypes&&... _Mapped_args) { - return _Try_emplace(_STD move(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)); + return _Try_emplace(_STD move(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)...); } template @@ -1087,7 +1087,7 @@ public: && is_constructible_v && (!is_convertible_v<_OtherKey, const_iterator>) && (!is_convertible_v<_OtherKey, iterator>) pair try_emplace(_OtherKey&& _Key_val, _MappedArgTypes&&... _Mapped_args) { - return _Try_emplace(_STD forward<_OtherKey>(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)); + return _Try_emplace(_STD forward<_OtherKey>(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)...); } template @@ -1162,9 +1162,9 @@ public: private: using _MyBase::_Erase_if; - template - friend typename flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>::size_type erase_if( - flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>&, _Predicate); + template + friend typename flat_map<_KTy, _MTy, _Comp, _KeyCont, _MappedCont>::size_type erase_if( + flat_map<_KTy, _MTy, _Comp, _KeyCont, _MappedCont>&, _Pred); template _NODISCARD mapped_type& _At(const _KeyTy& _Key_val) @@ -1327,9 +1327,9 @@ public: private: using _MyBase::_Erase_if; - template - friend typename flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>::size_type erase_if( - flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>&, _Predicate); + template + friend typename flat_multimap<_KTy, _MTy, _Comp, _KeyCont, _MappedCont>::size_type erase_if( + flat_multimap<_KTy, _MTy, _Comp, _KeyCont, _MappedCont>&, _Pred); template iterator _Emplace_key_mapped(_KeyTy&& _Key_val, _MappedTy&& _Mapped_val) { From 40be7454d437816dd0cd06dcc1ea680a30e286d4 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 23 Jan 2024 09:15:11 +0800 Subject: [PATCH 10/11] Guard 2 deduction guides with `__cpp_lib_byte` --- stl/inc/flat_map | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 101b8d11f6a..a3189a074ae 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1255,11 +1255,13 @@ template flat_map<_Guide_key_t<_InputIterator>, _Guide_val_t<_InputIterator>, _Compare>; +#ifdef __cpp_lib_byte template <_RANGES input_range _Rng, class _Compare = less<_Range_key_type<_Rng>>, class _Allocator = allocator> flat_map(from_range_t, _Rng&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_map<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, _Compare, vector<_Range_key_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_key_type<_Rng>>>, vector<_Range_mapped_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_mapped_type<_Rng>>>>; +#endif // defined(__cpp_lib_byte) template <_RANGES input_range _Rng, class _Allocator> flat_map(from_range_t, _Rng&&, _Allocator) -> flat_map<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, @@ -1377,11 +1379,13 @@ template flat_multimap<_Guide_key_t<_InputIterator>, _Guide_val_t<_InputIterator>, _Compare>; +#ifdef __cpp_lib_byte template <_RANGES input_range _Rng, class _Compare = less<_Range_key_type<_Rng>>, class _Allocator = allocator> flat_multimap(from_range_t, _Rng&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_multimap<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, _Compare, vector<_Range_key_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_key_type<_Rng>>>, vector<_Range_mapped_type<_Rng>, _Rebind_alloc_t<_Allocator, _Range_mapped_type<_Rng>>>>; +#endif // defined(__cpp_lib_byte) template <_RANGES input_range _Rng, class _Allocator> flat_multimap(from_range_t, _Rng&&, _Allocator) -> flat_multimap<_Range_key_type<_Rng>, _Range_mapped_type<_Rng>, From 12c6ed853b19bb0eaa21345c5c35b1a7478841da Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 23 Jan 2024 09:43:58 +0800 Subject: [PATCH 11/11] Fix misspelled `const key_type&&` and dependent calls --- stl/inc/flat_map | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index a3189a074ae..c73b25e9e1b 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1091,17 +1091,17 @@ public: } template - iterator try_emplace(const_iterator _Position, const key_type&& _Key_val, _MappedArgTypes&&... _Mapped_args) + iterator try_emplace(const_iterator _Position, const key_type& _Key_val, _MappedArgTypes&&... _Mapped_args) requires is_constructible_v { - return this->_Emplace_hint(_Position, _Key_val, _STD forward<_MappedArgTypes>(_Mapped_args)...); + return this->template _Emplace_hint(_Position, _Key_val, _STD forward<_MappedArgTypes>(_Mapped_args)...); } template iterator try_emplace(const_iterator _Position, key_type&& _Key_val, _MappedArgTypes&&... _Mapped_args) requires is_constructible_v { - return this->_Emplace_hint( + return this->template _Emplace_hint( _Position, _STD move(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)...); } @@ -1110,7 +1110,7 @@ public: requires _Is_transparent_v && is_constructible_v && is_constructible_v { - return this->_Emplace_hint( + return this->template _Emplace_hint( _Position, _STD forward<_OtherKey>(_Key_val), _STD forward<_MappedArgTypes>(_Mapped_args)...); }