From e9f8d353244cb903c9d62ade48122d6bacc5bc0d Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Sat, 27 May 2023 01:24:12 +0200 Subject: [PATCH 01/25] Introduce `_Is_transparent` helper trait Also a concept for future-proofing. --- stl/inc/xhash | 14 ++++++++------ stl/inc/xtree | 32 ++++++++++++++++++-------------- stl/inc/xutility | 14 ++++++++++++++ 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/stl/inc/xhash b/stl/inc/xhash index 71460bb5e27..836ed52e21b 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -108,12 +108,16 @@ struct _Uhash_choose_transparency { #if _HAS_CXX20 template struct _Uhash_choose_transparency<_Kty, _Hasher, _Keyeq, - void_t> { + enable_if_t, _Is_transparent<_Keyeq>>>> { // transparency selector for transparent hashed containers template using _Deduce_key = const _Keyty&; - using _Transparent = void; + template , + is_convertible<_Kx, typename _Container::iterator>>, + int> = 0> + using _Supports_transparency = void; }; #endif // _HAS_CXX20 @@ -1140,8 +1144,7 @@ public: } #if _HAS_CXX23 - template , is_convertible<_Kx, iterator>>, int> = 0> + template > size_type erase(_Kx&& _Keyval) noexcept(noexcept(_Erase(_Keyval))) /* strengthened */ { return _Erase(_Keyval); } @@ -1380,8 +1383,7 @@ public: } #if _HAS_CXX23 - template , is_convertible<_Kx, iterator>>, int> = 0> + template > node_type extract(_Kx&& _Keyval) { const auto _Ptr = _Extract(_Keyval); if (!_Ptr) { diff --git a/stl/inc/xtree b/stl/inc/xtree index 639185e6395..167e168acd7 100644 --- a/stl/inc/xtree +++ b/stl/inc/xtree @@ -1344,8 +1344,10 @@ public: } #if _HAS_CXX23 - template , is_convertible<_Kx, iterator>>, int> = 0> + template , + negation, is_convertible<_Kx, iterator>>>>, + int> = 0> size_type erase(_Kx&& _Keyval) noexcept(noexcept(_Eqrange(_Keyval))) /* strengthened */ { return _Erase(_Eqrange(_Keyval)); } @@ -1382,12 +1384,12 @@ public: return const_iterator(_Find(_Keyval), _Get_scary()); } - template + template , int> = 0> _NODISCARD iterator find(const _Other& _Keyval) { return iterator(_Find(_Keyval), _Get_scary()); } - template + template , int> = 0> _NODISCARD const_iterator find(const _Other& _Keyval) const { return const_iterator(_Find(_Keyval), _Get_scary()); } @@ -1397,7 +1399,7 @@ public: return _Lower_bound_duplicate(_Find_lower_bound(_Keyval)._Bound, _Keyval); } - template + template , int> = 0> _NODISCARD bool contains(const _Other& _Keyval) const { return _Lower_bound_duplicate(_Find_lower_bound(_Keyval)._Bound, _Keyval); } @@ -1413,7 +1415,7 @@ public: } } - template + template , int> = 0> _NODISCARD size_type count(const _Other& _Keyval) const { const auto _Ans = _Eqrange(_Keyval); return static_cast(_STD distance( @@ -1428,12 +1430,12 @@ public: return const_iterator(_Find_lower_bound(_Keyval)._Bound, _Get_scary()); } - template + template , int> = 0> _NODISCARD iterator lower_bound(const _Other& _Keyval) { return iterator(_Find_lower_bound(_Keyval)._Bound, _Get_scary()); } - template + template , int> = 0> _NODISCARD const_iterator lower_bound(const _Other& _Keyval) const { return const_iterator(_Find_lower_bound(_Keyval)._Bound, _Get_scary()); } @@ -1446,12 +1448,12 @@ public: return const_iterator(_Find_upper_bound(_Keyval)._Bound, _Get_scary()); } - template + template , int> = 0> _NODISCARD iterator upper_bound(const _Other& _Keyval) { return iterator(_Find_upper_bound(_Keyval)._Bound, _Get_scary()); } - template + template , int> = 0> _NODISCARD const_iterator upper_bound(const _Other& _Keyval) const { return const_iterator(_Find_upper_bound(_Keyval)._Bound, _Get_scary()); } @@ -1468,14 +1470,14 @@ public: return {const_iterator(_Result.first, _Scary), const_iterator(_Result.second, _Scary)}; } - template + template , int> = 0> _NODISCARD pair equal_range(const _Other& _Keyval) { const auto _Result = _Eqrange(_Keyval); const auto _Scary = _Get_scary(); return {iterator(_Result.first, _Scary), iterator(_Result.second, _Scary)}; } - template + template , int> = 0> _NODISCARD pair equal_range(const _Other& _Keyval) const { const auto _Result = _Eqrange(_Keyval); const auto _Scary = _Get_scary(); @@ -1750,8 +1752,10 @@ public: } #if _HAS_CXX23 - template , is_convertible<_Kx, iterator>>, int> = 0> + template , + negation, is_convertible<_Kx, iterator>>>>, + int> = 0> node_type extract(_Kx&& _Keyval) { const const_iterator _Where = find(_Keyval); if (_Where == end()) { diff --git a/stl/inc/xutility b/stl/inc/xutility index 82888aab50e..d5ed5a226b0 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -537,6 +537,20 @@ struct less_equal { using is_transparent = int; }; +template +_INLINE_VAR constexpr bool _Is_transparent_v = false; + +template +_INLINE_VAR constexpr bool _Is_transparent_v<_Ty, void_t> = true; + +template +struct _Is_transparent : bool_constant<_Is_transparent_v<_Ty>> {}; + +#ifdef __cpp_lib_concepts // TRANSITION, GH-395 +template +concept _Transparent = _Is_transparent_v<_Ty>; +#endif // __cpp_lib_concepts + template struct _Ref_fn { // pass function object by value as a reference template From 42a7d3500ce3514bac60943e137315412e9de260 Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Sat, 27 May 2023 17:41:07 +0200 Subject: [PATCH 02/25] Make `_Supports_transparency` a `constexpr bool` and utilize `enable_if_t` where it is used --- stl/inc/xhash | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/stl/inc/xhash b/stl/inc/xhash index 836ed52e21b..358f5ac4504 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -113,11 +113,10 @@ struct _Uhash_choose_transparency<_Kty, _Hasher, _Keyeq, template using _Deduce_key = const _Keyty&; - template , - is_convertible<_Kx, typename _Container::iterator>>, - int> = 0> - using _Supports_transparency = void; + template + static constexpr bool _Supports_transparency = + !disjunction_v, + is_convertible<_Kx, typename _Container::iterator>>; }; #endif // _HAS_CXX20 @@ -1144,7 +1143,8 @@ public: } #if _HAS_CXX23 - template > + template , int> = 0> size_type erase(_Kx&& _Keyval) noexcept(noexcept(_Erase(_Keyval))) /* strengthened */ { return _Erase(_Keyval); } @@ -1383,7 +1383,8 @@ public: } #if _HAS_CXX23 - template > + template , int> = 0> node_type extract(_Kx&& _Keyval) { const auto _Ptr = _Extract(_Keyval); if (!_Ptr) { From 0aab1aabc13923cccaa732fb5f20254f7a018d34 Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Thu, 25 May 2023 04:39:25 +0200 Subject: [PATCH 03/25] Implement #2912 `` (P1222R4) --- stl/CMakeLists.txt | 1 + stl/inc/__msvc_all_public_headers.hpp | 1 + stl/inc/flat_set | 693 ++++++++++++++++++ stl/inc/header-units.json | 1 + stl/inc/yvals_core.h | 4 + stl/modules/std.ixx | 1 + tests/std/tests/P1222R4_flat_set/env.lst | 4 + tests/std/tests/P1222R4_flat_set/test.cpp | 25 + .../importable_cxx_library_headers.jsonc | 1 + .../include_each_header_alone_matrix.lst | 1 + 10 files changed, 732 insertions(+) create mode 100644 stl/inc/flat_set create mode 100644 tests/std/tests/P1222R4_flat_set/env.lst create mode 100644 tests/std/tests/P1222R4_flat_set/test.cpp diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index 6c2e456eedf..a5c3d67c519 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -155,6 +155,7 @@ set(HEADERS ${CMAKE_CURRENT_LIST_DIR}/inc/experimental/unordered_set ${CMAKE_CURRENT_LIST_DIR}/inc/experimental/vector ${CMAKE_CURRENT_LIST_DIR}/inc/filesystem + ${CMAKE_CURRENT_LIST_DIR}/inc/flat_set ${CMAKE_CURRENT_LIST_DIR}/inc/format ${CMAKE_CURRENT_LIST_DIR}/inc/forward_list ${CMAKE_CURRENT_LIST_DIR}/inc/fstream diff --git a/stl/inc/__msvc_all_public_headers.hpp b/stl/inc/__msvc_all_public_headers.hpp index ccb3267943a..248d8819dc2 100644 --- a/stl/inc/__msvc_all_public_headers.hpp +++ b/stl/inc/__msvc_all_public_headers.hpp @@ -92,6 +92,7 @@ #include #include #include +#include #include #include #include diff --git a/stl/inc/flat_set b/stl/inc/flat_set new file mode 100644 index 00000000000..fe3feb6c5f2 --- /dev/null +++ b/stl/inc/flat_set @@ -0,0 +1,693 @@ +// flat_set standard header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once +#ifndef _FLAT_SET_ +#define _FLAT_SET_ +#include +#if _STL_COMPILER_PREPROCESSOR +#include +#include +#include +#include +#include + +_STD_BEGIN + +template +struct _Is_transparent : false_type {}; + +template +struct _Is_transparent<_Ty, void_t> : true_type {}; + +template +class _Base_flat_set { +private: + static constexpr bool _Keylt_transparent = _Is_transparent<_Keylt>::value; + +public: + static_assert(is_same_v<_Kty, typename _Container::value_type>, + "The C++ Standard dictates that the Key type must be the " + "same as the container's value type [flatset.overview]"); + + using key_type = _Kty; + using value_type = _Kty; + using key_compare = _Keylt; + using value_compare = _Keylt; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = typename _Container::size_type; + using difference_type = typename _Container::difference_type; + using iterator = typename _Container::iterator; + using const_iterator = typename _Container::const_iterator; + using reverse_iterator = _STD reverse_iterator; + using const_reverse_iterator = _STD reverse_iterator; + using container_type = _Container; + + static_assert(random_access_iterator, "The C++ Standard forbids containers without random " + "access iterators from being adapted. See [flatset.overview]."); + + _Base_flat_set() : _My_pair(_Zero_then_variadic_args_t{}, _Keylt()) {} + + explicit _Base_flat_set(container_type _Cont, const key_compare& _Comp = key_compare()) + : _My_pair(_One_then_variadic_args_t{}, _STD move(_Cont), _Comp) { + _Make_invariants_fulfilled(); + } + + _Base_flat_set(_Tsorted, container_type _Cont, const key_compare& _Comp = key_compare()) + : _My_pair(_One_then_variadic_args_t{}, _STD move(_Cont), _Comp) {} + + explicit _Base_flat_set(const key_compare& _Comp) : _My_pair(_Zero_then_variadic_args_t{}, _Comp) {} + + template + _Base_flat_set(_Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) + : _Base_flat_set(container_type(_First, _Last), _Comp) {} + + template <_Container_compatible_range<_Kty> _Rng> + _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp = key_compare()) + : _Base_flat_set(to(_STD forward<_Rng>(_Range)), _Comp) {} + + template + _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) + : _Base_flat_set(_S, container_type(_First, _Last), _Comp) {} + + _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) + : _Base_flat_set(_Ilist.begin(), _Ilist.end(), _Comp) {} + + _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) + : _Base_flat_set(_S, _Ilist.begin(), _Ilist.end(), _Comp) {} + + template >> + _Base_flat_set(const container_type& _Cont, const _Alloc& _Al) : _Base_flat_set(container_type(_Cont, _Al)) {} + + template >> + _Base_flat_set(const container_type& _Cont, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(container_type(_Cont, _Al), _Comp) {} + + template >> + _Base_flat_set(_Tsorted _S, const container_type& _Cont, const _Alloc& _Al) + : _Base_flat_set(_S, container_type(_Cont, _Al)) {} + + template >> + _Base_flat_set(_Tsorted _S, const container_type& _Cont, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(_S, container_type(_Cont, _Al), _Comp) {} + + template >> + _Base_flat_set(const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(_Comp, container_type(_Al)) {} + + template >> + explicit _Base_flat_set(const _Alloc& _Al) : _Base_flat_set(container_type(_Al)) {} + + template >> + _Base_flat_set(_Iter _First, _Iter _Last, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(container_type(_First, _Last, _Al), _Comp) {} + + template >> + _Base_flat_set(_Iter _First, _Iter _Last, const _Alloc& _Al) : _Base_flat_set(container_type(_First, _Last, _Al)) {} + + template <_Container_compatible_range<_Kty> _Rng, class _Alloc, + enable_if_t>> + _Base_flat_set(from_range_t, _Rng&& _Range, const _Alloc& _Al) + : _Base_flat_set(to(_STD forward<_Rng>(_Range), _Al)) {} + + template <_Container_compatible_range<_Kty> _Rng, class _Alloc, + enable_if_t>> + _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(to(_STD forward<_Rng>(_Range), _Al), _Comp) {} + + template >> + _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(_S, container_type(_First, _Last, _Al), _Comp) {} + + template >> + _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const _Alloc& _Al) + : _Base_flat_set(_S, container_type(_First, _Last, _Al)) {} + + template >> + _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} + + template >> + _Base_flat_set(initializer_list<_Kty> _Ilist, const _Alloc& _Al) + : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} + + template >> + _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} + + template >> + _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const _Alloc& _Al) + : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} + + _Deriv& operator=(initializer_list<_Kty> _Ilist) { + _Get_cont() = container_type(_Ilist.begin(), _Ilist.end()); + _Make_invariants_fulfilled(); + return static_cast<_Deriv>(*this); + } + + _NODISCARD iterator begin() noexcept { + return _Get_cont().begin(); + } + _NODISCARD const_iterator begin() const noexcept { + return _Get_cont().begin(); + } + _NODISCARD iterator end() noexcept { + return _Get_cont().end(); + } + _NODISCARD const_iterator end() const noexcept { + return _Get_cont().end(); + } + _NODISCARD reverse_iterator rbegin() noexcept { + return _Get_cont().rbegin(); + } + _NODISCARD const_reverse_iterator rbegin() const noexcept { + return _Get_cont().rbegin(); + } + _NODISCARD reverse_iterator rend() noexcept { + return _Get_cont().rend(); + } + _NODISCARD const_reverse_iterator rend() const noexcept { + return _Get_cont().rend(); + } + _NODISCARD const_iterator cbegin() const noexcept { + return _Get_cont().cbegin(); + } + _NODISCARD const_iterator cend() const noexcept { + return _Get_cont().cend(); + } + _NODISCARD const_reverse_iterator crbegin() const noexcept { + return _Get_cont().crbegin(); + } + _NODISCARD const_reverse_iterator crend() const noexcept { + return _Get_cont().crend(); + } + + _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { + return _Get_cont().empty(); + } + _NODISCARD size_type size() const noexcept { + return _Get_cont().size(); + } + _NODISCARD size_type max_size() const noexcept { + return _Get_cont().max_size(); + } + + template + auto emplace(_Args&&... _Vals) { + _Kty _Temp{_STD forward<_Args>(_Vals)...}; + _Container& _Cont = _Get_cont(); + iterator _End = end(); + iterator _Where = _STD lower_bound(begin(), _End, _Temp, _Get_comp()); + if constexpr (_Mfl) { + return _Cont.insert(_Where, _STD move(_Temp)); + } else { + if (_Where != _End && _Keys_equal(_Temp, *_Where)) { + return pair{_Where, false}; + } + return pair{_Cont.insert(_Where, _STD move(_Temp)), true}; + } + } + + template + iterator emplace_hint(const_iterator _Where, _Args&&... _Vals) { + _Kty _Temp{_STD forward<_Args>(_Vals)...}; + _Keylt& _Compare = _Get_comp(); + _Container& _Cont = _Get_cont(); + const iterator _Begin = begin(); + const iterator _End = end(); + if (_Where == _End || _Compare(_Temp, *_Where)) { + do { + _Where--; + } while (_Where != _Begin && !_Compare(*_Where, _Temp)); + } else { + do { + _Where++; + } while (_Where != _End && _Compare(*_Where, _Temp)); + } + + if constexpr (_Mfl) { + return _Cont.insert(_Where, _STD move(_Temp)); + } else { + if (_Where == _End || !_Keys_equal(_Temp, *_Where)) { + return _Cont.insert(_Where, _STD move(_Temp)); + } + return _Where; + } + } + + auto insert(const value_type& _Val) { + return emplace(_Val); + } + auto insert(value_type&& _Val) { + return emplace(_STD move(_Val)); + } + + template >> + auto insert(_Other&& _Val) { + const _Container _Cont = _Get_cont(); + const iterator _End = end(); + const iterator _Where = _STD lower_bound(begin(), _End, _Val, _Get_comp()); + if constexpr (_Mfl) { + return _Cont.insert(_Where, _STD forward<_Other>(_Val)); + } else { + if (_Where != _End && _Key_other_equal(*_Where, _Val)) { + return pair{_Where, false}; + } + return pair{_Cont.insert(_Where, _STD forward<_Other>(_Val)), true}; + } + } + + template >> + iterator insert(const_iterator _Where, _Other&& _Val) { + return emplace_hint(_Where, _STD forward<_Other>(_Val)); + } + + iterator insert(const_iterator _Where, const value_type& _Val) { + return emplace_hint(_Where, _Val); + } + iterator insert(const_iterator _Where, value_type&& _Val) { + return emplace_hint(_Where, _STD move(_Val)); + } + + template + void insert(const _Iter& _First, const _Iter& _Last) { + _Insert_range(_First, _Last); + } + + template + void insert(_Tsorted, _Iter _First, _Iter _Last) { + _Insert_range(_First, _Last); + } + + template <_Container_compatible_range<_Kty> _Rng> + void insert_range(_Rng&& _Range) { + const auto _Old_size = _STD distance(begin(), end()); + _Container& _Cont = _Get_cont(); + + // This stinks!! + for (const auto& _Val : _Range) { + _Cont.insert(_Cont.end(), _Val); + } + + _Restore_invariants_after_insert(_Old_size); + } + + container_type extract() && { + // The container NEEDS to be cleared no matter what, + // which is not guaranteed by simply moving it away + // ("... valid but unspecified ...") + container_type& _Cont = _Get_cont(); + _TRY_BEGIN + container_type _Temp = _STD move(_Cont); + _Cont.clear(); + return _Temp; + _CATCH_ALL + _Cont.clear(); + _RERAISE; + _CATCH_END + } + + void replace(container_type&& _Cont) { + _Get_cont() = _STD move(_Cont); + } + + iterator erase(iterator _Where) { + return _Get_cont().erase(_Where); + } + iterator erase(const_iterator _Where) { + return _Get_cont().erase(_Where); + } + size_type erase(const _Kty& _Val) { + return erase<_Kty>(_Val); + } + + template >> + size_type erase(_Other&& _Val) { + const auto [_First, _Last] = _STD equal_range(begin(), end(), _Val, _Get_comp()); + + const auto _Removed = _STD distance(_First, _Last); + _Get_cont().erase(_First, _Last); + return _Removed; + } + + iterator erase(const_iterator _First, const_iterator _Last) { + return _Get_cont().erase(_First, _Last); + } + + void swap(_Deriv& _Other) noexcept { + _RANGES swap(_Get_comp(), _Other._Get_comp()); + _RANGES swap(_Get_cont(), _Other._Get_cont()); + } + + void clear() noexcept { + _Get_cont().clear(); + } + + _NODISCARD key_compare key_comp() const { + return _Get_comp(); + } + _NODISCARD value_compare value_comp() const { + return _Get_comp(); + } + + _NODISCARD iterator find(const _Kty& _Val) { + const iterator _End = end(); + const iterator _Where = lower_bound(_Val); + if (_Where != _End && _Keys_equal(*_Where, _Val)) { + return _Where; + } else { + return _End; + } + } + + _NODISCARD const_iterator find(const _Kty& _Val) const { + const const_iterator _End = cend(); + const const_iterator _Where = lower_bound(_Val); + if (_Where != _End && _Keys_equal(*_Where, _Val)) { + return _Where; + } else { + return _End; + } + } + + template > + _NODISCARD iterator find(const _Other& _Val) { + const iterator _End = end(); + const iterator _Where = lower_bound(_Val); + if (_Where != _End && _Key_other_equal(*_Where, _Val)) { + return _Where; + } else { + return _End; + } + } + + template > + _NODISCARD const_iterator find(const _Other& _Val) const { + const const_iterator _End = cend(); + const const_iterator _Where = lower_bound(_Val); + if (_Where != _End && _Key_other_equal(*_Where, _Val)) { + return _Where; + } else { + return _End; + } + } + + _NODISCARD size_type count(const _Kty& _Val) const { + return count<_Kty>(_Val); + } + + template >> + _NODISCARD size_type count(const _Other& _Val) const { + const auto [_First, _Last] = _STD equal_range(cbegin(), cend(), _Val); + return _STD distance(_First, _Last); + } + + _NODISCARD bool contains(const _Kty& _Val) const { + return find(_Val) != end(); + } + template > + _NODISCARD bool contains(const _Other& _Val) const { + return find(_Val) != end(); + } + _NODISCARD iterator lower_bound(const _Kty& _Val) { + return _STD lower_bound(begin(), end(), _Val, _Get_comp()); + } + _NODISCARD const_iterator lower_bound(const _Kty& _Val) const { + return _STD lower_bound(cbegin(), cend(), _Val, _Get_comp()); + } + + template > + _NODISCARD iterator lower_bound(const _Other& _Val) { + return _STD lower_bound(begin(), end(), _Val, _Get_comp()); + } + + template > + _NODISCARD const_iterator lower_bound(const _Other& _Val) const { + return _STD lower_bound(cbegin(), cend(), _Val, _Get_comp()); + } + + _NODISCARD iterator upper_bound(const _Kty& _Val) { + return _STD upper_bound(begin(), end(), _Val, _Get_comp()); + } + + _NODISCARD const_iterator upper_bound(const _Kty& _Val) const { + return _STD upper_bound(cbegin(), cend(), _Val, _Get_comp()); + } + + template > + _NODISCARD iterator upper_bound(const _Other& _Val) { + return _STD upper_bound(begin(), end(), _Val, _Get_comp()); + } + + template > + _NODISCARD const_iterator upper_bound(const _Other& _Val) const { + return _STD upper_bound(cbegin(), cend(), _Val, _Get_comp()); + } + + _NODISCARD pair equal_range(const _Kty& _Val) { + return _STD equal_range(begin(), end(), _Val, _Get_comp()); + } + + _NODISCARD pair equal_range(const _Kty& _Val) const { + return _STD equal_range(cbegin(), cend(), _Val, _Get_comp()); + } + + template > + _NODISCARD pair equal_range(const _Other& _Val) { + return _STD equal_range(begin(), end(), _Val, _Get_comp()); + } + + template > + _NODISCARD pair equal_range(const _Other& _Val) const { + return _STD equal_range(cbegin(), cend(), _Val, _Get_comp()); + } + + _NODISCARD friend bool operator==(const _Deriv& _Lhs, const _Deriv& _Rhs) { + return _Lhs.size() == _Rhs.size() && _STD equal(_Lhs.cbegin(), _Lhs.cend(), _Rhs.cbegin()); + } + + _NODISCARD friend _Synth_three_way_result<_Kty> operator<=>(const _Deriv& _Lhs, const _Deriv& _Rhs) { + return _STD lexicographical_compare_three_way( + _Lhs.cbegin(), _Lhs.cend(), _Rhs.cbegin(), _Rhs.cend(), _Synth_three_way{}); + } + + friend void swap(_Deriv& _Lhs, _Deriv& _Rhs) noexcept { + _Lhs.swap(_Rhs); + } + +private: + template + void _Insert_range(_Iter _First, _Iter _Last) { + const auto _Old_size = _STD distance(begin(), end()); + _Container& _Cont = _Get_cont(); + _Cont.insert(_Cont.end(), _First, _Last); + _Restore_invariants_after_insert<_Presorted>(_Old_size); + } + + _NODISCARD bool _Keys_equal(const _Kty& _Lhs, const _Kty& _Rhs) { + key_compare& _Compare = _Get_comp(); + return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs); + } + + template > + _NODISCARD bool _Key_other_equal(const _Kty& _Lhs, const _Other& _Rhs) { + key_compare& _Compare = _Get_comp(); + return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs); + } + + // O(N) if already sorted. + void _Sort_potentially_sorted(const iterator& _Begin, const iterator& _End) { + key_compare& _Compare = _Get_comp(); + const iterator _Begin_unsorted = is_sorted_until(_Begin, _End, _Compare); + + if (_Begin_unsorted != _End) { + sort(_Begin_unsorted, _End, _Compare); + } + } + + void _Erase_dupes_if_needed() { + _Erase_dupes_if_needed(begin(), end()); + } + + void _Erase_dupes_if_needed(const iterator& _Begin, const iterator& _End) { + if constexpr (!_Mfl) { + iterator _New_end = + unique(_Begin, _End, [&](const _Kty& lhs, const _Kty& rhs) { return _Keys_equal(lhs, rhs); }); + _Get_cont().erase(_New_end, _End); + } + } + + template + void _Restore_invariants_after_insert(const typename iterator::difference_type& _Old_size) { + key_compare& _Compare = _Get_comp(); + const iterator _Old_end = begin() + _Old_size; + const iterator _New_end = end(); + + if constexpr (_Presorted) { + _STD sort(_Old_end, _New_end, _Compare); + } + + _STD inplace_merge(begin(), _Old_end, _New_end, _Compare); + + _Erase_dupes_if_needed(); + } + + void _Make_invariants_fulfilled() { + const iterator _Begin = begin(); + const iterator _End = end(); + + if (_Begin == _End) { + return; + } + + _Sort_potentially_sorted(_Begin, _End); + + _Erase_dupes_if_needed(); + } + + _NODISCARD const _Container& _Get_cont() const noexcept { + return _My_pair._Get_first(); + } + + _NODISCARD _Container& _Get_cont() noexcept { + return _My_pair._Get_first(); + } + + _NODISCARD const key_compare& _Get_comp() const noexcept { + return _My_pair._Myval2; + } + + _NODISCARD key_compare& _Get_comp() noexcept { + return _My_pair._Myval2; + } + + _Compressed_pair _My_pair; +}; + +_EXPORT_STD struct sorted_unique_t { + explicit sorted_unique_t() = default; +}; +_EXPORT_STD inline constexpr sorted_unique_t sorted_unique{}; + +_EXPORT_STD struct sorted_equivalent_t { + explicit sorted_equivalent_t() = default; +}; +_EXPORT_STD inline constexpr sorted_equivalent_t sorted_equivalent{}; + +template , class _Container = vector<_Kty>> +_EXPORT_STD class flat_set + : public _Base_flat_set<_Kty, _Keylt, _Container, false, flat_set<_Kty, _Keylt, _Container>, sorted_unique_t> { +public: + using _Base_flat_set<_Kty, _Keylt, _Container, false, flat_set, sorted_unique_t>::_Base_flat_set; +}; + +template , class _Container = vector<_Kty>> +_EXPORT_STD class flat_multiset : public _Base_flat_set<_Kty, _Keylt, _Container, true, + flat_multiset<_Kty, _Keylt, _Container>, sorted_equivalent_t> { +public: + using _Base_flat_set<_Kty, _Keylt, _Container, true, flat_multiset, sorted_equivalent_t>::_Base_flat_set; +}; + +_EXPORT_STD template +size_t erase_if(flat_set<_Kty, _Keylt, _Container>& _Val, _Pred _Predicate) { + _TRY_BEGIN + return _Erase_remove_if(_Val, _Pass_fn(_Predicate)); + _CATCH_ALL + _Val.clear(); + _RERAISE; + _CATCH_END +} + +_EXPORT_STD template +size_t erase_if(flat_multiset<_Kty, _Keylt, _Container>& _Val, _Pred _Predicate) { + _TRY_BEGIN + return _Erase_remove_if(_Val, _Pass_fn(_Predicate)); + _CATCH_ALL + _Val.clear(); + _RERAISE; + _CATCH_END +} + +template +struct uses_allocator, _Alloc> + : bool_constant> {}; + +template +struct uses_allocator, _Alloc> + : bool_constant> {}; + +_EXPORT_STD template > +flat_set(_Container, _Keylt = _Keylt()) -> flat_set; +_EXPORT_STD template +flat_set(_Container, _Alloc) + -> flat_set, _Container>; +_EXPORT_STD template +flat_set(_Container, _Keylt, _Alloc) -> flat_set; + +_EXPORT_STD template > +flat_set(sorted_unique_t, _Container, _Keylt = _Keylt()) + -> flat_set; +_EXPORT_STD template +flat_set(sorted_unique_t, _Container, _Alloc) + -> flat_set, _Container>; +_EXPORT_STD template +flat_set(sorted_unique_t, _Container, _Keylt, _Alloc) -> flat_set; + +_EXPORT_STD template >> +flat_set(_Iter, _Iter, _Keylt = _Keylt()) -> flat_set, _Keylt>; +_EXPORT_STD template >> +flat_set(sorted_unique_t, _Iter, _Iter, _Keylt = _Keylt()) -> flat_set, _Keylt>; +_EXPORT_STD template <_RANGES input_range _Range, class _Keylt = less<_RANGES range_value_t<_Range>>, + class _Alloc = allocator<_RANGES range_value_t<_Range>>> +flat_set(from_range_t, _Range&&, _Keylt = _Keylt(), _Alloc = _Alloc()) + -> flat_set<_RANGES range_value_t<_Range>, _Keylt>; +_EXPORT_STD template <_RANGES input_range _Range, class _Alloc> +flat_set(from_range_t, _Range&&, _Alloc) + -> flat_set<_RANGES range_value_t<_Range>, less<_RANGES range_value_t<_Range>>>; +_EXPORT_STD template > +flat_set(initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_set<_Kty, _Keylt>; +_EXPORT_STD template > +flat_set(sorted_unique_t, initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_set<_Kty, _Keylt>; + + +_EXPORT_STD template > +flat_multiset(_Container, _Keylt = _Keylt()) -> flat_multiset; +_EXPORT_STD template +flat_multiset(_Container, _Alloc) + -> flat_multiset, _Container>; +_EXPORT_STD template +flat_multiset(_Container, _Keylt, _Alloc) -> flat_multiset; + +_EXPORT_STD template > +flat_multiset(sorted_equivalent_t, _Container, _Keylt = _Keylt()) + -> flat_multiset; +_EXPORT_STD template +flat_multiset(sorted_equivalent_t, _Container, _Alloc) + -> flat_multiset, _Container>; +_EXPORT_STD template +flat_multiset(sorted_equivalent_t, _Container, _Keylt, _Alloc) + -> flat_multiset; + +_EXPORT_STD template >> +flat_multiset(_Iter, _Iter, _Keylt = _Keylt()) -> flat_multiset, iter_value_t<_Iter>, _Keylt>; +_EXPORT_STD template >> +flat_multiset(sorted_equivalent_t, _Iter, _Iter, _Keylt = _Keylt()) + -> flat_multiset, iter_value_t<_Iter>, _Keylt>; +_EXPORT_STD template <_RANGES input_range _Range, class _Keylt = less<_RANGES range_value_t<_Range>>, + class _Alloc = allocator<_RANGES range_value_t<_Range>>> +flat_multiset(from_range_t, _Range&&, _Keylt = _Keylt(), _Alloc = _Alloc()) + -> flat_multiset<_RANGES range_value_t<_Range>, _Keylt>; +_EXPORT_STD template <_RANGES input_range _Range, class _Alloc> +flat_multiset(from_range_t, _Range&&, _Alloc) + -> flat_multiset<_RANGES range_value_t<_Range>, less<_RANGES range_value_t<_Range>>>; +_EXPORT_STD template > +flat_multiset(initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_multiset<_Kty, _Keylt>; +_EXPORT_STD template > +flat_multiset(sorted_equivalent_t, initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_multiset<_Kty, _Keylt>; + +_STD_END + +#endif // _STL_COMPILER_PREPROCESSOR +#endif // _FLAT_SET_ diff --git a/stl/inc/header-units.json b/stl/inc/header-units.json index 345af8adf51..cd6a2b97ef2 100644 --- a/stl/inc/header-units.json +++ b/stl/inc/header-units.json @@ -62,6 +62,7 @@ "execution", "expected", "filesystem", + "flat_set", "format", "forward_list", "fstream", diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 2973f2fa6e7..95489fff095 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1769,6 +1769,10 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #endif // __cpp_lib_concepts #define __cpp_lib_unreachable 202202L + +#ifdef __cpp_lib_concepts +#define __cpp_lib_flat_set 202207L +#endif // __cpp_lib_concepts #endif // _HAS_CXX23 // macros with language mode sensitivity diff --git a/stl/modules/std.ixx b/stl/modules/std.ixx index 326d944d74f..cfae4e6fc95 100644 --- a/stl/modules/std.ixx +++ b/stl/modules/std.ixx @@ -59,6 +59,7 @@ export module std; #include #include #include +#include #include #include #include diff --git a/tests/std/tests/P1222R4_flat_set/env.lst b/tests/std/tests/P1222R4_flat_set/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P1222R4_flat_set/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P1222R4_flat_set/test.cpp b/tests/std/tests/P1222R4_flat_set/test.cpp new file mode 100644 index 00000000000..f7199419976 --- /dev/null +++ b/tests/std/tests/P1222R4_flat_set/test.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef __EDG__ // TRANSITION, VSO-1285779 +#include +#include +#include +#include + +using namespace std; + +int main() { + flat_set s{1, 2, 2, 2, 3}; + assert(s.size() == 3); + s.insert(43); + assert(s.size() == 4); + + int myInts[] = {1, 2, 3, 4, 55}; + s.insert_range(myInts); + + flat_multiset, deque> d; +} +#else // ^^^ !defined(__EDG__) / defined(__EDG__) vvv +int main() {} +#endif // ^^^ defined(__EDG__) ^^^ diff --git a/tests/std/tests/P1502R1_standard_library_header_units/importable_cxx_library_headers.jsonc b/tests/std/tests/P1502R1_standard_library_header_units/importable_cxx_library_headers.jsonc index 70d0af803ec..51f0fd7365c 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/importable_cxx_library_headers.jsonc +++ b/tests/std/tests/P1502R1_standard_library_header_units/importable_cxx_library_headers.jsonc @@ -23,6 +23,7 @@ "execution", "expected", "filesystem", + "flat_set", "format", "forward_list", "fstream", diff --git a/tests/std/tests/include_each_header_alone_matrix.lst b/tests/std/tests/include_each_header_alone_matrix.lst index 9b041e051e5..0de7b470c6c 100644 --- a/tests/std/tests/include_each_header_alone_matrix.lst +++ b/tests/std/tests/include_each_header_alone_matrix.lst @@ -26,6 +26,7 @@ PM_CL="/DMEOW_HEADER=exception" PM_CL="/DMEOW_HEADER=execution" PM_CL="/DMEOW_HEADER=expected" PM_CL="/DMEOW_HEADER=filesystem" +PM_CL="/DMEOW_HEADER=flat_set" PM_CL="/DMEOW_HEADER=format" PM_CL="/DMEOW_HEADER=forward_list" PM_CL="/DMEOW_HEADER=fstream" From 4a9b733de6fddbfa1808e6ad6c600dc9aa5a837c Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Thu, 25 May 2023 04:57:56 +0200 Subject: [PATCH 04/25] Apply LWG-3786 --- stl/inc/flat_set | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index fe3feb6c5f2..f23f3014a5c 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -641,11 +641,11 @@ _EXPORT_STD template >> flat_set(sorted_unique_t, _Iter, _Iter, _Keylt = _Keylt()) -> flat_set, _Keylt>; _EXPORT_STD template <_RANGES input_range _Range, class _Keylt = less<_RANGES range_value_t<_Range>>, class _Alloc = allocator<_RANGES range_value_t<_Range>>> -flat_set(from_range_t, _Range&&, _Keylt = _Keylt(), _Alloc = _Alloc()) - -> flat_set<_RANGES range_value_t<_Range>, _Keylt>; +flat_set(from_range_t, _Range&&, _Keylt = _Keylt(), _Alloc = _Alloc()) -> flat_set<_RANGES range_value_t<_Range>, + _Keylt, vector<_RANGES range_value_t<_Range>, _Rebind_alloc_t<_Alloc, _RANGES range_value_t<_Range>>>>; _EXPORT_STD template <_RANGES input_range _Range, class _Alloc> -flat_set(from_range_t, _Range&&, _Alloc) - -> flat_set<_RANGES range_value_t<_Range>, less<_RANGES range_value_t<_Range>>>; +flat_set(from_range_t, _Range&&, _Alloc) -> flat_set<_RANGES range_value_t<_Range>, less<_RANGES range_value_t<_Range>>, + vector<_RANGES range_value_t<_Range>, _Rebind_alloc_t<_Alloc, _RANGES range_value_t<_Range>>>>; _EXPORT_STD template > flat_set(initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_set<_Kty, _Keylt>; _EXPORT_STD template > @@ -678,10 +678,12 @@ flat_multiset(sorted_equivalent_t, _Iter, _Iter, _Keylt = _Keylt()) _EXPORT_STD template <_RANGES input_range _Range, class _Keylt = less<_RANGES range_value_t<_Range>>, class _Alloc = allocator<_RANGES range_value_t<_Range>>> flat_multiset(from_range_t, _Range&&, _Keylt = _Keylt(), _Alloc = _Alloc()) - -> flat_multiset<_RANGES range_value_t<_Range>, _Keylt>; + -> flat_multiset<_RANGES range_value_t<_Range>, _Keylt, + vector<_RANGES range_value_t<_Range>, _Rebind_alloc_t<_Alloc, _RANGES range_value_t<_Range>>>>; _EXPORT_STD template <_RANGES input_range _Range, class _Alloc> flat_multiset(from_range_t, _Range&&, _Alloc) - -> flat_multiset<_RANGES range_value_t<_Range>, less<_RANGES range_value_t<_Range>>>; + -> flat_multiset<_RANGES range_value_t<_Range>, less<_RANGES range_value_t<_Range>>, + vector<_RANGES range_value_t<_Range>, _Rebind_alloc_t<_Alloc, _RANGES range_value_t<_Range>>>>; _EXPORT_STD template > flat_multiset(initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_multiset<_Kty, _Keylt>; _EXPORT_STD template > From 921a9c07a436d6114aba174513f28eb8077705bd Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Sat, 27 May 2023 22:40:39 +0200 Subject: [PATCH 05/25] Cleanup, fixes, optimizations --- stl/inc/flat_set | 311 +++++++++++++++++++++++++---------------------- 1 file changed, 168 insertions(+), 143 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index f23f3014a5c..2c235d44c36 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -15,20 +15,16 @@ #include _STD_BEGIN - -template -struct _Is_transparent : false_type {}; - -template -struct _Is_transparent<_Ty, void_t> : true_type {}; +template +concept _Allocator_for = uses_allocator_v<_Container, _Alloc>; template class _Base_flat_set { private: - static constexpr bool _Keylt_transparent = _Is_transparent<_Keylt>::value; + static constexpr bool _Keylt_transparent = _Is_transparent_v<_Keylt>; public: - static_assert(is_same_v<_Kty, typename _Container::value_type>, + static_assert(same_as<_Kty, typename _Container::value_type>, "The C++ Standard dictates that the Key type must be the " "same as the container's value type [flatset.overview]"); @@ -57,11 +53,13 @@ public: } _Base_flat_set(_Tsorted, container_type _Cont, const key_compare& _Comp = key_compare()) - : _My_pair(_One_then_variadic_args_t{}, _STD move(_Cont), _Comp) {} + : _My_pair(_One_then_variadic_args_t{}, _STD move(_Cont), _Comp) { + _Assert_after_sorted_input(); + } explicit _Base_flat_set(const key_compare& _Comp) : _My_pair(_Zero_then_variadic_args_t{}, _Comp) {} - template + template _Base_flat_set(_Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) : _Base_flat_set(container_type(_First, _Last), _Comp) {} @@ -69,82 +67,94 @@ public: _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp = key_compare()) : _Base_flat_set(to(_STD forward<_Rng>(_Range)), _Comp) {} - template + template _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) - : _Base_flat_set(_S, container_type(_First, _Last), _Comp) {} + : _Base_flat_set(_S, container_type(_First, _Last), _Comp) { + _Assert_after_sorted_input(); + } _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) : _Base_flat_set(_Ilist.begin(), _Ilist.end(), _Comp) {} _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) - : _Base_flat_set(_S, _Ilist.begin(), _Ilist.end(), _Comp) {} + : _Base_flat_set(_S, _Ilist.begin(), _Ilist.end(), _Comp) { + _Assert_after_sorted_input(); + } - template >> + template <_Allocator_for<_Container> _Alloc> _Base_flat_set(const container_type& _Cont, const _Alloc& _Al) : _Base_flat_set(container_type(_Cont, _Al)) {} - template >> + template <_Allocator_for<_Container> _Alloc> _Base_flat_set(const container_type& _Cont, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(container_type(_Cont, _Al), _Comp) {} - template >> + template <_Allocator_for<_Container> _Alloc> _Base_flat_set(_Tsorted _S, const container_type& _Cont, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Cont, _Al)) {} + : _Base_flat_set(_S, container_type(_Cont, _Al)) { + _Assert_after_sorted_input(); + } - template >> + template <_Allocator_for<_Container> _Alloc> _Base_flat_set(_Tsorted _S, const container_type& _Cont, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Cont, _Al), _Comp) {} + : _Base_flat_set(_S, container_type(_Cont, _Al), _Comp) { + _Assert_after_sorted_input(); + } - template >> + template <_Allocator_for<_Container> _Alloc> _Base_flat_set(const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(_Comp, container_type(_Al)) {} - template >> + template <_Allocator_for<_Container> _Alloc> explicit _Base_flat_set(const _Alloc& _Al) : _Base_flat_set(container_type(_Al)) {} - template >> + template _Alloc> _Base_flat_set(_Iter _First, _Iter _Last, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(container_type(_First, _Last, _Al), _Comp) {} - template >> + template _Alloc> _Base_flat_set(_Iter _First, _Iter _Last, const _Alloc& _Al) : _Base_flat_set(container_type(_First, _Last, _Al)) {} - template <_Container_compatible_range<_Kty> _Rng, class _Alloc, - enable_if_t>> + template <_Container_compatible_range<_Kty> _Rng, _Allocator_for<_Container> _Alloc> _Base_flat_set(from_range_t, _Rng&& _Range, const _Alloc& _Al) : _Base_flat_set(to(_STD forward<_Rng>(_Range), _Al)) {} - template <_Container_compatible_range<_Kty> _Rng, class _Alloc, - enable_if_t>> + template <_Container_compatible_range<_Kty> _Rng, _Allocator_for<_Container> _Alloc> _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(to(_STD forward<_Rng>(_Range), _Al), _Comp) {} - template >> + template _Alloc> _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_First, _Last, _Al), _Comp) {} + : _Base_flat_set(_S, container_type(_First, _Last, _Al), _Comp) { + _Assert_after_sorted_input(); + } - template >> + template _Alloc> _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_First, _Last, _Al)) {} + : _Base_flat_set(_S, container_type(_First, _Last, _Al)) { + _Assert_after_sorted_input(); + } - template >> + template <_Allocator_for<_Container> _Alloc> _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} - template >> + template <_Allocator_for<_Container> _Alloc> _Base_flat_set(initializer_list<_Kty> _Ilist, const _Alloc& _Al) : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} - template >> + template <_Allocator_for<_Container> _Alloc> _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} + : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) { + _Assert_after_sorted_input(); + } - template >> + template <_Allocator_for<_Container> _Alloc> _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const _Alloc& _Al) : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} _Deriv& operator=(initializer_list<_Kty> _Ilist) { _Get_cont() = container_type(_Ilist.begin(), _Ilist.end()); _Make_invariants_fulfilled(); - return static_cast<_Deriv>(*this); + return static_cast<_Deriv&>(*this); } _NODISCARD iterator begin() noexcept { @@ -196,87 +206,56 @@ public: template auto emplace(_Args&&... _Vals) { - _Kty _Temp{_STD forward<_Args>(_Vals)...}; - _Container& _Cont = _Get_cont(); - iterator _End = end(); - iterator _Where = _STD lower_bound(begin(), _End, _Temp, _Get_comp()); - if constexpr (_Mfl) { - return _Cont.insert(_Where, _STD move(_Temp)); - } else { - if (_Where != _End && _Keys_equal(_Temp, *_Where)) { - return pair{_Where, false}; - } - return pair{_Cont.insert(_Where, _STD move(_Temp)), true}; - } + insert<_Kty>(_Kty{_STD forward<_Args>(_Vals)...}); } template - iterator emplace_hint(const_iterator _Where, _Args&&... _Vals) { - _Kty _Temp{_STD forward<_Args>(_Vals)...}; - _Keylt& _Compare = _Get_comp(); - _Container& _Cont = _Get_cont(); - const iterator _Begin = begin(); - const iterator _End = end(); - if (_Where == _End || _Compare(_Temp, *_Where)) { - do { - _Where--; - } while (_Where != _Begin && !_Compare(*_Where, _Temp)); - } else { - do { - _Where++; - } while (_Where != _End && _Compare(*_Where, _Temp)); - } - - if constexpr (_Mfl) { - return _Cont.insert(_Where, _STD move(_Temp)); - } else { - if (_Where == _End || !_Keys_equal(_Temp, *_Where)) { - return _Cont.insert(_Where, _STD move(_Temp)); - } - return _Where; - } + iterator emplace_hint(const_iterator _Hint, _Args&&... _Vals) { + return _Emplace_hint(_Hint, _Kty{_STD forward<_Args>(_Vals)...}); } auto insert(const value_type& _Val) { - return emplace(_Val); + return insert<_Kty>(_Val); } auto insert(value_type&& _Val) { - return emplace(_STD move(_Val)); + return insert<_Kty>(_STD move(_Val)); } - template >> + template + requires (_Keylt_transparent && is_constructible_v<_Kty, _Other>) || is_same_v<_Other, _Kty> auto insert(_Other&& _Val) { - const _Container _Cont = _Get_cont(); - const iterator _End = end(); - const iterator _Where = _STD lower_bound(begin(), _End, _Val, _Get_comp()); + _Container& _Cont = _Get_cont(); + const iterator _End = end(); + const iterator _Where = lower_bound(_Val); if constexpr (_Mfl) { - return _Cont.insert(_Where, _STD forward<_Other>(_Val)); + return _Cont.emplace(_Where, _STD forward<_Other>(_Val)); } else { - if (_Where != _End && _Key_other_equal(*_Where, _Val)) { + if (_Where != _End && _Keys_equal(*_Where, _Val)) { return pair{_Where, false}; } - return pair{_Cont.insert(_Where, _STD forward<_Other>(_Val)), true}; + return pair{_Cont.emplace(_Where, _STD forward<_Other>(_Val)), true}; } } - template >> - iterator insert(const_iterator _Where, _Other&& _Val) { - return emplace_hint(_Where, _STD forward<_Other>(_Val)); + template + requires _Keylt_transparent && is_constructible_v<_Kty, _Other> + iterator insert(const_iterator _Hint, _Other&& _Val) { + return _Emplace_hint(_Hint, _STD forward<_Other>(_Val)); } - iterator insert(const_iterator _Where, const value_type& _Val) { - return emplace_hint(_Where, _Val); + iterator insert(const_iterator _Hint, const value_type& _Val) { + return _Emplace_hint(_Hint, _Val); } - iterator insert(const_iterator _Where, value_type&& _Val) { - return emplace_hint(_Where, _STD move(_Val)); + iterator insert(const_iterator _Hint, value_type&& _Val) { + return _Emplace_hint(_Hint, _STD move(_Val)); } - template + template void insert(const _Iter& _First, const _Iter& _Last) { _Insert_range(_First, _Last); } - template + template void insert(_Tsorted, _Iter _First, _Iter _Last) { _Insert_range(_First, _Last); } @@ -284,17 +263,11 @@ public: template <_Container_compatible_range<_Kty> _Rng> void insert_range(_Rng&& _Range) { const auto _Old_size = _STD distance(begin(), end()); - _Container& _Cont = _Get_cont(); - - // This stinks!! - for (const auto& _Val : _Range) { - _Cont.insert(_Cont.end(), _Val); - } - + _Get_cont().append_range(_STD forward<_Rng>(_Range)); _Restore_invariants_after_insert(_Old_size); } - container_type extract() && { + _NODISCARD container_type extract() && { // The container NEEDS to be cleared no matter what, // which is not guaranteed by simply moving it away // ("... valid but unspecified ...") @@ -311,6 +284,7 @@ public: void replace(container_type&& _Cont) { _Get_cont() = _STD move(_Cont); + _Assert_after_sorted_input(); } iterator erase(iterator _Where) { @@ -323,9 +297,10 @@ public: return erase<_Kty>(_Val); } - template >> + template + requires _Keylt_transparent || is_same_v<_Other, _Kty> size_type erase(_Other&& _Val) { - const auto [_First, _Last] = _STD equal_range(begin(), end(), _Val, _Get_comp()); + const auto [_First, _Last] = equal_range(_Val); const auto _Removed = _STD distance(_First, _Last); _Get_cont().erase(_First, _Last); @@ -353,41 +328,31 @@ public: } _NODISCARD iterator find(const _Kty& _Val) { - const iterator _End = end(); - const iterator _Where = lower_bound(_Val); - if (_Where != _End && _Keys_equal(*_Where, _Val)) { - return _Where; - } else { - return _End; - } + return find<_Kty>(_Val); } _NODISCARD const_iterator find(const _Kty& _Val) const { - const const_iterator _End = cend(); - const const_iterator _Where = lower_bound(_Val); - if (_Where != _End && _Keys_equal(*_Where, _Val)) { - return _Where; - } else { - return _End; - } + return find<_Kty>(_Val); } - template > + template + requires _Keylt_transparent || is_same_v<_Other, _Kty> _NODISCARD iterator find(const _Other& _Val) { const iterator _End = end(); const iterator _Where = lower_bound(_Val); - if (_Where != _End && _Key_other_equal(*_Where, _Val)) { + if (_Where != _End && _Keys_equal(*_Where, _Val)) { return _Where; } else { return _End; } } - template > + template + requires _Keylt_transparent || is_same_v<_Other, _Kty> _NODISCARD const_iterator find(const _Other& _Val) const { const const_iterator _End = cend(); const const_iterator _Where = lower_bound(_Val); - if (_Where != _End && _Key_other_equal(*_Where, _Val)) { + if (_Where != _End && _Keys_equal(*_Where, _Val)) { return _Where; } else { return _End; @@ -398,16 +363,18 @@ public: return count<_Kty>(_Val); } - template >> + template + requires _Keylt_transparent || is_same_v<_Other, _Kty> _NODISCARD size_type count(const _Other& _Val) const { - const auto [_First, _Last] = _STD equal_range(cbegin(), cend(), _Val); + const auto [_First, _Last] = equal_range(_Val); return _STD distance(_First, _Last); } _NODISCARD bool contains(const _Kty& _Val) const { return find(_Val) != end(); } - template > + template + requires _Keylt_transparent _NODISCARD bool contains(const _Other& _Val) const { return find(_Val) != end(); } @@ -418,12 +385,14 @@ public: return _STD lower_bound(cbegin(), cend(), _Val, _Get_comp()); } - template > + template + requires _Keylt_transparent _NODISCARD iterator lower_bound(const _Other& _Val) { return _STD lower_bound(begin(), end(), _Val, _Get_comp()); } - template > + template + requires _Keylt_transparent _NODISCARD const_iterator lower_bound(const _Other& _Val) const { return _STD lower_bound(cbegin(), cend(), _Val, _Get_comp()); } @@ -436,12 +405,14 @@ public: return _STD upper_bound(cbegin(), cend(), _Val, _Get_comp()); } - template > + template + requires _Keylt_transparent _NODISCARD iterator upper_bound(const _Other& _Val) { return _STD upper_bound(begin(), end(), _Val, _Get_comp()); } - template > + template + requires _Keylt_transparent _NODISCARD const_iterator upper_bound(const _Other& _Val) const { return _STD upper_bound(cbegin(), cend(), _Val, _Get_comp()); } @@ -454,12 +425,14 @@ public: return _STD equal_range(cbegin(), cend(), _Val, _Get_comp()); } - template > + template + requires _Keylt_transparent _NODISCARD pair equal_range(const _Other& _Val) { return _STD equal_range(begin(), end(), _Val, _Get_comp()); } - template > + template + requires _Keylt_transparent _NODISCARD pair equal_range(const _Other& _Val) const { return _STD equal_range(cbegin(), cend(), _Val, _Get_comp()); } @@ -478,6 +451,59 @@ public: } private: + void inline _Assert_after_sorted_input() const { + _STL_ASSERT(_STD is_sorted(begin(), end(), _Get_comp()), "Input was not sorted!"); + _STL_ASSERT(_Mfl || _Is_unique(), "Input was not unique!"); + } + + bool _Is_unique() const { + if (empty()) { + return true; + } + const_iterator _End = cend(); + const_iterator _It = begin(); + while (++_It != _End) { + if (_Keys_equal(*(_It - 1), *_It)) { + return false; + } + } + return true; + } + + template + requires (_Keylt_transparent && is_constructible_v<_Kty, _Ty>) || is_same_v<_Ty, _Kty> + void _Emplace_hint(const_iterator _Where, _Ty&& _Val) { + _Container& _Cont = _Get_cont(); + _Keylt& _Compare = _Get_comp(); + const iterator _Begin = begin(); + const iterator _End = end(); + + if (_Where == _End || !_Compare(*_Where, _Val)) { + // _Val <= *_Where + // Left of _Where + if (_Where == _Begin || !_Compare(_Val, *(_Where - 1))) { + // _Val >= (*_Where - 1) + // Insert before _Where + } else { + // _Val < (*_Where - 1) + _Where = _STD upper_bound(_Begin, _Where, _Val, _Compare); + } + } else { + // _Val > *_Where + // Right of _Where + _Where = _STD lower_bound(_Where + 1, _End, _Val, _Compare); + } + + if constexpr (_Mfl) { + return _Cont.insert(_Where, _STD forward<_Ty>(_Val)); + } else { + if (_Where == _End || !_Keys_equal(_Val, *_Where)) { + return _Cont.insert(_Where, _STD forward<_Ty>(_Val)); + } + return _Where; + } + } + template void _Insert_range(_Iter _First, _Iter _Last) { const auto _Old_size = _STD distance(begin(), end()); @@ -486,21 +512,17 @@ private: _Restore_invariants_after_insert<_Presorted>(_Old_size); } - _NODISCARD bool _Keys_equal(const _Kty& _Lhs, const _Kty& _Rhs) { - key_compare& _Compare = _Get_comp(); - return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs); - } - - template > - _NODISCARD bool _Key_other_equal(const _Kty& _Lhs, const _Other& _Rhs) { - key_compare& _Compare = _Get_comp(); + template + requires _Keylt_transparent || (is_same_v<_Kty, _Lhty> && is_same_v<_Lhty, _Rhty>) + _NODISCARD bool _Keys_equal(const _Lhty& _Lhs, const _Rhty& _Rhs) const { + const key_compare& _Compare = _Get_comp(); return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs); } // O(N) if already sorted. void _Sort_potentially_sorted(const iterator& _Begin, const iterator& _End) { key_compare& _Compare = _Get_comp(); - const iterator _Begin_unsorted = is_sorted_until(_Begin, _End, _Compare); + const iterator _Begin_unsorted = _STD is_sorted_until(_Begin, _End, _Compare); if (_Begin_unsorted != _End) { sort(_Begin_unsorted, _End, _Compare); @@ -508,15 +530,13 @@ private: } void _Erase_dupes_if_needed() { - _Erase_dupes_if_needed(begin(), end()); - } - - void _Erase_dupes_if_needed(const iterator& _Begin, const iterator& _End) { + iterator _End = end(); if constexpr (!_Mfl) { iterator _New_end = - unique(_Begin, _End, [&](const _Kty& lhs, const _Kty& rhs) { return _Keys_equal(lhs, rhs); }); + unique(begin(), _End, [&](const _Kty& lhs, const _Kty& rhs) { return _Keys_equal(lhs, rhs); }); _Get_cont().erase(_New_end, _End); } + _STL_INTERNAL_CHECK(_Mfl || _Is_unique()); } template @@ -525,12 +545,16 @@ private: const iterator _Old_end = begin() + _Old_size; const iterator _New_end = end(); - if constexpr (_Presorted) { + if constexpr (!_Presorted) { _STD sort(_Old_end, _New_end, _Compare); + } else { + _STL_ASSERT(_STD is_sorted(_Old_end, _New_end, _Compare), "Input was not sorted!"); } _STD inplace_merge(begin(), _Old_end, _New_end, _Compare); + _STL_INTERNAL_CHECK(_STD is_sorted(begin(), end(), _Get_comp())); + _Erase_dupes_if_needed(); } @@ -543,6 +567,7 @@ private: } _Sort_potentially_sorted(_Begin, _End); + _STL_INTERNAL_CHECK(_STD is_sorted(begin(), end(), _Get_comp())); _Erase_dupes_if_needed(); } From 549ab7b2f02fe98260a796726e307b84d983b3bd Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Sat, 27 May 2023 23:58:00 +0200 Subject: [PATCH 06/25] Apply suggested changes Co-Authored-By: A. Jiang <23228989+frederick-vs-ja@users.noreply.github.com> --- stl/inc/flat_set | 3 +-- stl/inc/yvals_core.h | 9 +++++---- tests/std/tests/P1222R4_flat_set/env.lst | 2 +- tests/std/tests/P1222R4_flat_set/test.cpp | 4 ---- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 2c235d44c36..b7d4794ea43 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -11,8 +11,8 @@ #include #include #include -#include #include +#include _STD_BEGIN template @@ -713,7 +713,6 @@ _EXPORT_STD template > flat_multiset(initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_multiset<_Kty, _Keylt>; _EXPORT_STD template > flat_multiset(sorted_equivalent_t, initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_multiset<_Kty, _Keylt>; - _STD_END #endif // _STL_COMPILER_PREPROCESSOR diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 95489fff095..d4c07003813 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1725,6 +1725,11 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #endif // __cpp_lib_concepts #define __cpp_lib_forward_like 202207L + +#ifdef __cpp_lib_concepts +#define __cpp_lib_flat_set 202207L +#endif // __cpp_lib_concepts + #define __cpp_lib_invoke_r 202106L #define __cpp_lib_ios_noreplace 202207L #define __cpp_lib_is_scoped_enum 202011L @@ -1769,10 +1774,6 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #endif // __cpp_lib_concepts #define __cpp_lib_unreachable 202202L - -#ifdef __cpp_lib_concepts -#define __cpp_lib_flat_set 202207L -#endif // __cpp_lib_concepts #endif // _HAS_CXX23 // macros with language mode sensitivity diff --git a/tests/std/tests/P1222R4_flat_set/env.lst b/tests/std/tests/P1222R4_flat_set/env.lst index 642f530ffad..18e2d7c71ec 100644 --- a/tests/std/tests/P1222R4_flat_set/env.lst +++ b/tests/std/tests/P1222R4_flat_set/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\usual_latest_matrix.lst +RUNALL_INCLUDE ..\concepts_latest_matrix.lst diff --git a/tests/std/tests/P1222R4_flat_set/test.cpp b/tests/std/tests/P1222R4_flat_set/test.cpp index f7199419976..c75bf98f8c4 100644 --- a/tests/std/tests/P1222R4_flat_set/test.cpp +++ b/tests/std/tests/P1222R4_flat_set/test.cpp @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#ifndef __EDG__ // TRANSITION, VSO-1285779 #include #include #include @@ -20,6 +19,3 @@ int main() { flat_multiset, deque> d; } -#else // ^^^ !defined(__EDG__) / defined(__EDG__) vvv -int main() {} -#endif // ^^^ defined(__EDG__) ^^^ From b20e8d8f32bcec21487e198a68fc6fb28997660c Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Sun, 28 May 2023 22:02:10 +0200 Subject: [PATCH 07/25] Fixes, renames, refactors, more tests! --- stl/inc/flat_set | 257 +++++++++++----------- stl/inc/yvals_core.h | 2 +- tests/std/tests/P1222R4_flat_set/test.cpp | 206 ++++++++++++++++- 3 files changed, 328 insertions(+), 137 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index b7d4794ea43..ef74d687929 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -18,7 +18,7 @@ _STD_BEGIN template concept _Allocator_for = uses_allocator_v<_Container, _Alloc>; -template +template class _Base_flat_set { private: static constexpr bool _Keylt_transparent = _Is_transparent_v<_Keylt>; @@ -51,103 +51,73 @@ public: : _My_pair(_One_then_variadic_args_t{}, _STD move(_Cont), _Comp) { _Make_invariants_fulfilled(); } - - _Base_flat_set(_Tsorted, container_type _Cont, const key_compare& _Comp = key_compare()) - : _My_pair(_One_then_variadic_args_t{}, _STD move(_Cont), _Comp) { - _Assert_after_sorted_input(); - } - - explicit _Base_flat_set(const key_compare& _Comp) : _My_pair(_Zero_then_variadic_args_t{}, _Comp) {} - - template - _Base_flat_set(_Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) - : _Base_flat_set(container_type(_First, _Last), _Comp) {} - - template <_Container_compatible_range<_Kty> _Rng> - _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp = key_compare()) - : _Base_flat_set(to(_STD forward<_Rng>(_Range)), _Comp) {} - - template - _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) - : _Base_flat_set(_S, container_type(_First, _Last), _Comp) { - _Assert_after_sorted_input(); - } - - _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) - : _Base_flat_set(_Ilist.begin(), _Ilist.end(), _Comp) {} - - _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) - : _Base_flat_set(_S, _Ilist.begin(), _Ilist.end(), _Comp) { - _Assert_after_sorted_input(); - } - - template <_Allocator_for<_Container> _Alloc> + template <_Allocator_for _Alloc> _Base_flat_set(const container_type& _Cont, const _Alloc& _Al) : _Base_flat_set(container_type(_Cont, _Al)) {} - - template <_Allocator_for<_Container> _Alloc> + template <_Allocator_for _Alloc> _Base_flat_set(const container_type& _Cont, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(container_type(_Cont, _Al), _Comp) {} - template <_Allocator_for<_Container> _Alloc> - _Base_flat_set(_Tsorted _S, const container_type& _Cont, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Cont, _Al)) { + _Base_flat_set(_Tsorted, container_type _Cont, const key_compare& _Comp = key_compare()) + : _My_pair(_One_then_variadic_args_t{}, _STD move(_Cont), _Comp) { _Assert_after_sorted_input(); } - - template <_Allocator_for<_Container> _Alloc> + template <_Allocator_for _Alloc> + _Base_flat_set(_Tsorted _S, const container_type& _Cont, const _Alloc& _Al) + : _Base_flat_set(_S, container_type(_Cont, _Al)) {} + template <_Allocator_for _Alloc> _Base_flat_set(_Tsorted _S, const container_type& _Cont, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Cont, _Al), _Comp) { - _Assert_after_sorted_input(); - } + : _Base_flat_set(_S, container_type(_Cont, _Al), _Comp) {} - template <_Allocator_for<_Container> _Alloc> + explicit _Base_flat_set(const key_compare& _Comp) : _My_pair(_Zero_then_variadic_args_t{}, _Comp) {} + template <_Allocator_for _Alloc> _Base_flat_set(const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(_Comp, container_type(_Al)) {} - - template <_Allocator_for<_Container> _Alloc> + template <_Allocator_for _Alloc> explicit _Base_flat_set(const _Alloc& _Al) : _Base_flat_set(container_type(_Al)) {} - template _Alloc> + template + _Base_flat_set(_Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) + : _Base_flat_set(container_type(_First, _Last), _Comp) {} + template _Alloc> _Base_flat_set(_Iter _First, _Iter _Last, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(container_type(_First, _Last, _Al), _Comp) {} - - template _Alloc> + template _Alloc> _Base_flat_set(_Iter _First, _Iter _Last, const _Alloc& _Al) : _Base_flat_set(container_type(_First, _Last, _Al)) {} - template <_Container_compatible_range<_Kty> _Rng, _Allocator_for<_Container> _Alloc> - _Base_flat_set(from_range_t, _Rng&& _Range, const _Alloc& _Al) - : _Base_flat_set(to(_STD forward<_Rng>(_Range), _Al)) {} - - template <_Container_compatible_range<_Kty> _Rng, _Allocator_for<_Container> _Alloc> - _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(to(_STD forward<_Rng>(_Range), _Al), _Comp) {} + template <_Container_compatible_range<_Kty> _Rng> + _Base_flat_set(from_range_t _R, _Rng&& _Range, const key_compare& _Comp = key_compare()) + : _Base_flat_set(container_type(_R, _STD forward<_Rng>(_Range)), _Comp) {} + template <_Container_compatible_range<_Kty> _Rng, _Allocator_for _Alloc> + _Base_flat_set(from_range_t _R, _Rng&& _Range, const _Alloc& _Al) + : _Base_flat_set(container_type(_R, _STD forward<_Rng>(_Range), _Al)) {} + template <_Container_compatible_range<_Kty> _Rng, _Allocator_for _Alloc> + _Base_flat_set(from_range_t _R, _Rng&& _Range, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(container_type(_R, _STD forward<_Rng>(_Range), _Al), _Comp) {} - template _Alloc> + template + _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) + : _Base_flat_set(_S, container_type(_First, _Last), _Comp) {} + template _Alloc> _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_First, _Last, _Al), _Comp) { - _Assert_after_sorted_input(); - } - - template _Alloc> + : _Base_flat_set(_S, container_type(_First, _Last, _Al), _Comp) {} + template _Alloc> _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_First, _Last, _Al)) { - _Assert_after_sorted_input(); - } + : _Base_flat_set(_S, container_type(_First, _Last, _Al)) {} - template <_Allocator_for<_Container> _Alloc> + _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) + : _Base_flat_set(_Ilist.begin(), _Ilist.end(), _Comp) {} + template <_Allocator_for _Alloc> _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} - - template <_Allocator_for<_Container> _Alloc> + template <_Allocator_for _Alloc> _Base_flat_set(initializer_list<_Kty> _Ilist, const _Alloc& _Al) : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} - template <_Allocator_for<_Container> _Alloc> + _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) + : _Base_flat_set(_S, _Ilist.begin(), _Ilist.end(), _Comp) {} + template <_Allocator_for _Alloc> _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) { - _Assert_after_sorted_input(); - } - - template <_Allocator_for<_Container> _Alloc> + : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} + template <_Allocator_for _Alloc> _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const _Alloc& _Al) : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} @@ -215,30 +185,20 @@ public: } auto insert(const value_type& _Val) { - return insert<_Kty>(_Val); + return _Insert<_Kty>(_Val); } auto insert(value_type&& _Val) { - return insert<_Kty>(_STD move(_Val)); + return _Insert(_STD move(_Val)); } template - requires (_Keylt_transparent && is_constructible_v<_Kty, _Other>) || is_same_v<_Other, _Kty> + requires (!_Multi && _Keylt_transparent && is_constructible_v<_Kty, _Other>) auto insert(_Other&& _Val) { - _Container& _Cont = _Get_cont(); - const iterator _End = end(); - const iterator _Where = lower_bound(_Val); - if constexpr (_Mfl) { - return _Cont.emplace(_Where, _STD forward<_Other>(_Val)); - } else { - if (_Where != _End && _Keys_equal(*_Where, _Val)) { - return pair{_Where, false}; - } - return pair{_Cont.emplace(_Where, _STD forward<_Other>(_Val)), true}; - } + return _Insert(_STD forward<_Other>(_Val)); } template - requires _Keylt_transparent && is_constructible_v<_Kty, _Other> + requires (!_Multi && _Keylt_transparent && is_constructible_v<_Kty, _Other>) iterator insert(const_iterator _Hint, _Other&& _Val) { return _Emplace_hint(_Hint, _STD forward<_Other>(_Val)); } @@ -262,7 +222,7 @@ public: template <_Container_compatible_range<_Kty> _Rng> void insert_range(_Rng&& _Range) { - const auto _Old_size = _STD distance(begin(), end()); + const size_type _Old_size = size(); _Get_cont().append_range(_STD forward<_Rng>(_Range)); _Restore_invariants_after_insert(_Old_size); } @@ -294,17 +254,13 @@ public: return _Get_cont().erase(_Where); } size_type erase(const _Kty& _Val) { - return erase<_Kty>(_Val); + return _Erase(_Val); } template - requires _Keylt_transparent || is_same_v<_Other, _Kty> + requires _Keylt_transparent size_type erase(_Other&& _Val) { - const auto [_First, _Last] = equal_range(_Val); - - const auto _Removed = _STD distance(_First, _Last); - _Get_cont().erase(_First, _Last); - return _Removed; + return _Erase(_STD forward<_Other>(_Val)); } iterator erase(const_iterator _First, const_iterator _Last) { @@ -328,43 +284,32 @@ public: } _NODISCARD iterator find(const _Kty& _Val) { - return find<_Kty>(_Val); + return _Find(_Val); } _NODISCARD const_iterator find(const _Kty& _Val) const { - return find<_Kty>(_Val); + return _Find(_Val); } template - requires _Keylt_transparent || is_same_v<_Other, _Kty> + requires _Keylt_transparent _NODISCARD iterator find(const _Other& _Val) { - const iterator _End = end(); - const iterator _Where = lower_bound(_Val); - if (_Where != _End && _Keys_equal(*_Where, _Val)) { - return _Where; - } else { - return _End; - } + return _Find(_Val); } template - requires _Keylt_transparent || is_same_v<_Other, _Kty> + requires _Keylt_transparent _NODISCARD const_iterator find(const _Other& _Val) const { - const const_iterator _End = cend(); - const const_iterator _Where = lower_bound(_Val); - if (_Where != _End && _Keys_equal(*_Where, _Val)) { - return _Where; - } else { - return _End; - } + return _Find(_Val); } _NODISCARD size_type count(const _Kty& _Val) const { - return count<_Kty>(_Val); + const auto [_First, _Last] = equal_range(_Val); + return _STD distance(_First, _Last); } template - requires _Keylt_transparent || is_same_v<_Other, _Kty> + requires _Keylt_transparent _NODISCARD size_type count(const _Other& _Val) const { const auto [_First, _Last] = equal_range(_Val); return _STD distance(_First, _Last); @@ -438,7 +383,7 @@ public: } _NODISCARD friend bool operator==(const _Deriv& _Lhs, const _Deriv& _Rhs) { - return _Lhs.size() == _Rhs.size() && _STD equal(_Lhs.cbegin(), _Lhs.cend(), _Rhs.cbegin()); + return _RANGES equal(_Lhs, _Rhs); } _NODISCARD friend _Synth_three_way_result<_Kty> operator<=>(const _Deriv& _Lhs, const _Deriv& _Rhs) { @@ -453,7 +398,9 @@ public: private: void inline _Assert_after_sorted_input() const { _STL_ASSERT(_STD is_sorted(begin(), end(), _Get_comp()), "Input was not sorted!"); - _STL_ASSERT(_Mfl || _Is_unique(), "Input was not unique!"); + if constexpr (!_Multi) { + _STL_ASSERT(_Is_unique(), "Input was not unique!"); + } } bool _Is_unique() const { @@ -494,7 +441,7 @@ private: _Where = _STD lower_bound(_Where + 1, _End, _Val, _Compare); } - if constexpr (_Mfl) { + if constexpr (_Multi) { return _Cont.insert(_Where, _STD forward<_Ty>(_Val)); } else { if (_Where == _End || !_Keys_equal(_Val, *_Where)) { @@ -506,12 +453,62 @@ private: template void _Insert_range(_Iter _First, _Iter _Last) { - const auto _Old_size = _STD distance(begin(), end()); - _Container& _Cont = _Get_cont(); + const size_type _Old_size = size(); + _Container& _Cont = _Get_cont(); _Cont.insert(_Cont.end(), _First, _Last); _Restore_invariants_after_insert<_Presorted>(_Old_size); } + template + requires (!_Multi && _Keylt_transparent && is_constructible_v<_Kty, _Ty>) || is_same_v<_Ty, _Kty> + auto _Insert(_Ty&& _Val) { + _Container& _Cont = _Get_cont(); + const iterator _End = end(); + const iterator _Where = lower_bound(_Val); + if constexpr (_Multi) { + return _Cont.emplace(_Where, _STD forward<_Ty>(_Val)); + } else { + if (_Where != _End && _Keys_equal(*_Where, _Val)) { + return pair{_Where, false}; + } + return pair{_Cont.emplace(_Where, _STD forward<_Ty>(_Val)), true}; + } + } + + template + requires _Keylt_transparent || is_same_v<_Ty, _Kty> + size_type _Erase(_Ty&& _Val) { + const auto [_First, _Last] = equal_range(_Val); + + const difference_type _Removed = _STD distance(_First, _Last); + _Get_cont().erase(_First, _Last); + return _Removed; + } + + template + requires _Keylt_transparent || is_same_v<_Other, _Kty> + _NODISCARD iterator _Find(const _Other& _Val) { + const iterator _End = end(); + const iterator _Where = lower_bound(_Val); + if (_Where != _End && _Keys_equal(*_Where, _Val)) { + return _Where; + } else { + return _End; + } + } + + template + requires _Keylt_transparent || is_same_v<_Other, _Kty> + _NODISCARD const_iterator _Find(const _Other& _Val) const { + const iterator _End = end(); + const iterator _Where = lower_bound(_Val); + if (_Where != _End && _Keys_equal(*_Where, _Val)) { + return _Where; + } else { + return _End; + } + } + template requires _Keylt_transparent || (is_same_v<_Kty, _Lhty> && is_same_v<_Lhty, _Rhty>) _NODISCARD bool _Keys_equal(const _Lhty& _Lhs, const _Rhty& _Rhs) const { @@ -524,25 +521,27 @@ private: key_compare& _Compare = _Get_comp(); const iterator _Begin_unsorted = _STD is_sorted_until(_Begin, _End, _Compare); - if (_Begin_unsorted != _End) { - sort(_Begin_unsorted, _End, _Compare); - } + _STD sort(_Begin_unsorted, _End, _Compare); + + _STD inplace_merge(begin(), _Begin_unsorted, _End, _Compare); } void _Erase_dupes_if_needed() { - iterator _End = end(); - if constexpr (!_Mfl) { + if constexpr (!_Multi) { + iterator _End = end(); iterator _New_end = unique(begin(), _End, [&](const _Kty& lhs, const _Kty& rhs) { return _Keys_equal(lhs, rhs); }); _Get_cont().erase(_New_end, _End); } - _STL_INTERNAL_CHECK(_Mfl || _Is_unique()); + if constexpr (!_Multi) { + _STL_INTERNAL_CHECK(_Is_unique()); + } } template - void _Restore_invariants_after_insert(const typename iterator::difference_type& _Old_size) { + void _Restore_invariants_after_insert(const size_type& _Old_size) { key_compare& _Compare = _Get_comp(); - const iterator _Old_end = begin() + _Old_size; + const iterator _Old_end = begin() + static_cast(_Old_size); const iterator _New_end = end(); if constexpr (!_Presorted) { diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index d4c07003813..5b62a61dd10 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1724,7 +1724,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_expected 202211L #endif // __cpp_lib_concepts -#define __cpp_lib_forward_like 202207L +#define __cpp_lib_forward_like 202207L #ifdef __cpp_lib_concepts #define __cpp_lib_flat_set 202207L diff --git a/tests/std/tests/P1222R4_flat_set/test.cpp b/tests/std/tests/P1222R4_flat_set/test.cpp index c75bf98f8c4..c166771e3fe 100644 --- a/tests/std/tests/P1222R4_flat_set/test.cpp +++ b/tests/std/tests/P1222R4_flat_set/test.cpp @@ -4,18 +4,210 @@ #include #include #include +#include +#include #include using namespace std; +using namespace ranges; + +template +void assert_container_requirements(const T& s) { + T m = s; + assert(m == s); + + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_convertible_v); + static_assert(is_same_v m.end()), strong_ordering>); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + + T my_moved = std::move(m); + assert(!(my_moved != s)); + + T empty{}; + assert(empty.empty()); + + T non_empty = s; + empty.swap(non_empty); + assert(non_empty.empty()); + assert(empty == s); + + std::swap(empty, non_empty); + assert(empty.empty()); + assert(non_empty == s); + + assert(s.cbegin() <= s.cend()); + assert(s.cbegin() < s.cend() || s.empty()); + + assert(m.begin() <= m.end()); + assert(m.begin() < m.end() || m.empty()); + + assert(static_cast(s.cend() - s.cbegin()) == s.size()); +} + +template +void assert_reversible_container_requirements(const T& s) { + static_assert(is_same_v, typename T::reverse_iterator>); + static_assert(is_same_v, typename T::const_reverse_iterator>); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_same_v); + static_assert(is_convertible_v); +} + +template +void assert_all_requirements_and_equals(const T& s, const initializer_list& il) { + assert_container_requirements(s); + assert_reversible_container_requirements(s); + + auto val_comp = s.value_comp(); + auto begin_it = s.cbegin(); + auto end_it = s.cend(); + assert(std::is_sorted(begin_it, end_it, val_comp)); + if constexpr (!_Is_specialization_v) { + if (!s.empty()) { + auto it = begin_it; + while (++it != end_it) { + assert(val_comp(*(it - 1), *it)); + } + } + } + + if (s.size() != il.size() || !std::equal(s.begin(), s.end(), il.begin())) { + cout << "Expected: {"; + for (auto&& e : il) { + cout << e << ", "; + } + cout << "}" << endl; + cout << "Got: {"; + for (auto&& e : s) { + cout << e << ", "; + } + cout << "}" << endl; + assert(false); + } +} + +template +void assert_basic() { + T s{3, 2, 2, 2, 1}; + assert_all_requirements_and_equals(s, {1, 2, 3}); -int main() { - flat_set s{1, 2, 2, 2, 3}; - assert(s.size() == 3); s.insert(43); - assert(s.size() == 4); + assert_all_requirements_and_equals(s, {1, 2, 3, 43}); + + int my_ints[] = {1, 2, 3, 4, 55}; + s.insert_range(my_ints); + assert_all_requirements_and_equals(s, {1, 2, 3, 4, 43, 55}); +} + +template +void test_constructors() { + using lt = std::less; + using gt = std::greater; + + assert_all_requirements_and_equals(flat_set(), {}); + assert_all_requirements_and_equals(flat_multiset(), {}); + assert_all_requirements_and_equals(flat_set(C{3, 7, 1, 85, 222, 1}), {1, 3, 7, 85, 222}); + assert_all_requirements_and_equals(flat_multiset(C{3, 7, 1, 85, 7, 222, 1}), {1, 1, 3, 7, 7, 85, 222}); + assert_all_requirements_and_equals(flat_set(C{1, 2, 3, 3}, gt()), {3, 2, 1}); + assert_all_requirements_and_equals(flat_multiset(C{1, 1, 2, 3}, gt()), {3, 2, 1, 1}); + assert_all_requirements_and_equals(flat_set(sorted_unique, C{30000, 200, 1}, gt()), {30000, 200, 1}); + assert_all_requirements_and_equals(flat_multiset(sorted_equivalent, C{3, 3, -1}, gt()), {3, 3, -1}); + assert_all_requirements_and_equals(flat_set({30000, 200, 1}, gt()), {30000, 200, 1}); + assert_all_requirements_and_equals(flat_multiset({3, 3, -1}, gt()), {3, 3, -1}); + assert_all_requirements_and_equals(flat_set(sorted_unique, {30000, 200, 1}, gt()), {30000, 200, 1}); + assert_all_requirements_and_equals(flat_multiset(sorted_equivalent, {3, 3, -1}, gt()), {3, 3, -1}); + + flat_set a{}; + a = {1, 7, 7, 7, 2, 100, -1}; + assert_all_requirements_and_equals(a, {-1, 1, 2, 7, 100}); + flat_multiset b{}; + b = {1, 7, 7, 7, 2, 100, -1}; + assert_all_requirements_and_equals(b, {-1, 1, 2, 7, 7, 7, 100}); +} + +template +void test_spaceship_operator() { + static constexpr bool multiset = _Is_specialization_v; + static constexpr bool invert = is_same_v>; + + T a{3, 2, 2, 1}; + T b{1, 2, 3}; + assert( + (a <=> b) == (multiset ? (invert ? strong_ordering::greater : strong_ordering::less) : strong_ordering::equal)); + + T c{3, 2}; + assert((c <=> b) == (invert ? strong_ordering::less : strong_ordering::greater)); + + T d{5, 6, 7, 7, 8, 9}; + T e{5, 6, 7, 8, 100}; + assert((d <=> e) == strong_ordering::less); + + T f{1, 2, 3, 4}; + assert((f <=> a) == strong_ordering::greater); +} + +template +struct proxy_comparer { + bool operator()(const T& lhs, const T& rhs) const { + return less ? (lhs < rhs) : (lhs > rhs); + } + + bool less = true; +}; + +void test_non_static_comparer() { + flat_set> a{3, 2, 2, 1}; + assert_all_requirements_and_equals(a, {1, 2, 3}); + auto b = flat_set>({-1, 5, 9, 9, 9, 9, 9}, proxy_comparer{.less = false}); + assert_all_requirements_and_equals(b, {9, 5, -1}); + + auto aBackup = a; + a = b; + assert_all_requirements_and_equals(a, {9, 5, -1}); + a.insert_range(vector{7, 7, 3, 3, 2}); + assert_all_requirements_and_equals(a, {9, 7, 5, 3, 2, -1}); + + a = std::move(aBackup); + assert_all_requirements_and_equals(a, {1, 2, 3}); + + a.insert(-100); + assert_all_requirements_and_equals(a, {-100, 1, 2, 3}); + + a = b; + assert_all_requirements_and_equals(a, {9, 5, -1}); + + a.insert(7); + assert_all_requirements_and_equals(a, {9, 7, 5, -1}); +} + +int main() { + test_spaceship_operator>(); + test_spaceship_operator>(); + test_spaceship_operator>>(); + test_spaceship_operator>>(); + test_spaceship_operator, deque>>(); + test_spaceship_operator, deque>>(); + test_spaceship_operator, deque>>(); + test_spaceship_operator, deque>>(); + + test_constructors>(); + test_constructors>(); + + test_non_static_comparer(); - int myInts[] = {1, 2, 3, 4, 55}; - s.insert_range(myInts); + assert_basic>(); + assert_basic, deque>>(); - flat_multiset, deque> d; + flat_multiset, deque> d; } From a807eb6ff29f8e051a4e081b90b4146e41063797 Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Wed, 21 Jun 2023 04:09:30 +0200 Subject: [PATCH 08/25] Clean up minor issues Co-Authored-By: A. Jiang <23228989+frederick-vs-ja@users.noreply.github.com> --- stl/inc/flat_set | 77 +++++++++++------------ stl/inc/xutility | 14 ----- tests/std/tests/P1222R4_flat_set/test.cpp | 4 +- 3 files changed, 39 insertions(+), 56 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index ef74d687929..b6d6acc2a8c 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -15,6 +15,16 @@ #include _STD_BEGIN +template +struct _NODISCARD _Clear_scope_guard { + _Ty* _Clearable; + ~_Clear_scope_guard() { + if (_Clearable) { + _Clearable->clear(); + } + } +}; + template concept _Allocator_for = uses_allocator_v<_Container, _Alloc>; @@ -232,14 +242,9 @@ public: // which is not guaranteed by simply moving it away // ("... valid but unspecified ...") container_type& _Cont = _Get_cont(); - _TRY_BEGIN + _Clear_scope_guard _Guard{this}; container_type _Temp = _STD move(_Cont); - _Cont.clear(); return _Temp; - _CATCH_ALL - _Cont.clear(); - _RERAISE; - _CATCH_END } void replace(container_type&& _Cont) { @@ -616,22 +621,14 @@ public: _EXPORT_STD template size_t erase_if(flat_set<_Kty, _Keylt, _Container>& _Val, _Pred _Predicate) { - _TRY_BEGIN + _Clear_scope_guard _Guard{&_Val}; return _Erase_remove_if(_Val, _Pass_fn(_Predicate)); - _CATCH_ALL - _Val.clear(); - _RERAISE; - _CATCH_END } _EXPORT_STD template size_t erase_if(flat_multiset<_Kty, _Keylt, _Container>& _Val, _Pred _Predicate) { - _TRY_BEGIN + _Clear_scope_guard _Guard{&_Val}; return _Erase_remove_if(_Val, _Pass_fn(_Predicate)); - _CATCH_ALL - _Val.clear(); - _RERAISE; - _CATCH_END } template @@ -642,75 +639,75 @@ template struct uses_allocator, _Alloc> : bool_constant> {}; -_EXPORT_STD template > +template > flat_set(_Container, _Keylt = _Keylt()) -> flat_set; -_EXPORT_STD template +template flat_set(_Container, _Alloc) -> flat_set, _Container>; -_EXPORT_STD template +template flat_set(_Container, _Keylt, _Alloc) -> flat_set; -_EXPORT_STD template > +template > flat_set(sorted_unique_t, _Container, _Keylt = _Keylt()) -> flat_set; -_EXPORT_STD template +template flat_set(sorted_unique_t, _Container, _Alloc) -> flat_set, _Container>; -_EXPORT_STD template +template flat_set(sorted_unique_t, _Container, _Keylt, _Alloc) -> flat_set; -_EXPORT_STD template >> +template >> flat_set(_Iter, _Iter, _Keylt = _Keylt()) -> flat_set, _Keylt>; -_EXPORT_STD template >> +template >> flat_set(sorted_unique_t, _Iter, _Iter, _Keylt = _Keylt()) -> flat_set, _Keylt>; -_EXPORT_STD template <_RANGES input_range _Range, class _Keylt = less<_RANGES range_value_t<_Range>>, +template <_RANGES input_range _Range, class _Keylt = less<_RANGES range_value_t<_Range>>, class _Alloc = allocator<_RANGES range_value_t<_Range>>> flat_set(from_range_t, _Range&&, _Keylt = _Keylt(), _Alloc = _Alloc()) -> flat_set<_RANGES range_value_t<_Range>, _Keylt, vector<_RANGES range_value_t<_Range>, _Rebind_alloc_t<_Alloc, _RANGES range_value_t<_Range>>>>; -_EXPORT_STD template <_RANGES input_range _Range, class _Alloc> +template <_RANGES input_range _Range, class _Alloc> flat_set(from_range_t, _Range&&, _Alloc) -> flat_set<_RANGES range_value_t<_Range>, less<_RANGES range_value_t<_Range>>, vector<_RANGES range_value_t<_Range>, _Rebind_alloc_t<_Alloc, _RANGES range_value_t<_Range>>>>; -_EXPORT_STD template > +template > flat_set(initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_set<_Kty, _Keylt>; -_EXPORT_STD template > +template > flat_set(sorted_unique_t, initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_set<_Kty, _Keylt>; -_EXPORT_STD template > +template > flat_multiset(_Container, _Keylt = _Keylt()) -> flat_multiset; -_EXPORT_STD template +template flat_multiset(_Container, _Alloc) -> flat_multiset, _Container>; -_EXPORT_STD template +template flat_multiset(_Container, _Keylt, _Alloc) -> flat_multiset; -_EXPORT_STD template > +template > flat_multiset(sorted_equivalent_t, _Container, _Keylt = _Keylt()) -> flat_multiset; -_EXPORT_STD template +template flat_multiset(sorted_equivalent_t, _Container, _Alloc) -> flat_multiset, _Container>; -_EXPORT_STD template +template flat_multiset(sorted_equivalent_t, _Container, _Keylt, _Alloc) -> flat_multiset; -_EXPORT_STD template >> +template >> flat_multiset(_Iter, _Iter, _Keylt = _Keylt()) -> flat_multiset, iter_value_t<_Iter>, _Keylt>; -_EXPORT_STD template >> +template >> flat_multiset(sorted_equivalent_t, _Iter, _Iter, _Keylt = _Keylt()) -> flat_multiset, iter_value_t<_Iter>, _Keylt>; -_EXPORT_STD template <_RANGES input_range _Range, class _Keylt = less<_RANGES range_value_t<_Range>>, +template <_RANGES input_range _Range, class _Keylt = less<_RANGES range_value_t<_Range>>, class _Alloc = allocator<_RANGES range_value_t<_Range>>> flat_multiset(from_range_t, _Range&&, _Keylt = _Keylt(), _Alloc = _Alloc()) -> flat_multiset<_RANGES range_value_t<_Range>, _Keylt, vector<_RANGES range_value_t<_Range>, _Rebind_alloc_t<_Alloc, _RANGES range_value_t<_Range>>>>; -_EXPORT_STD template <_RANGES input_range _Range, class _Alloc> +template <_RANGES input_range _Range, class _Alloc> flat_multiset(from_range_t, _Range&&, _Alloc) -> flat_multiset<_RANGES range_value_t<_Range>, less<_RANGES range_value_t<_Range>>, vector<_RANGES range_value_t<_Range>, _Rebind_alloc_t<_Alloc, _RANGES range_value_t<_Range>>>>; -_EXPORT_STD template > +template > flat_multiset(initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_multiset<_Kty, _Keylt>; -_EXPORT_STD template > +template > flat_multiset(sorted_equivalent_t, initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_multiset<_Kty, _Keylt>; _STD_END diff --git a/stl/inc/xutility b/stl/inc/xutility index 6c85a8163c5..0e7933c44ad 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -541,20 +541,6 @@ struct less_equal { using is_transparent = int; }; -template -_INLINE_VAR constexpr bool _Is_transparent_v = false; - -template -_INLINE_VAR constexpr bool _Is_transparent_v<_Ty, void_t> = true; - -template -struct _Is_transparent : bool_constant<_Is_transparent_v<_Ty>> {}; - -#ifdef __cpp_lib_concepts // TRANSITION, GH-395 -template -concept _Transparent = _Is_transparent_v<_Ty>; -#endif // __cpp_lib_concepts - template struct _Ref_fn { // pass function object by value as a reference template diff --git a/tests/std/tests/P1222R4_flat_set/test.cpp b/tests/std/tests/P1222R4_flat_set/test.cpp index c166771e3fe..44deaa13908 100644 --- a/tests/std/tests/P1222R4_flat_set/test.cpp +++ b/tests/std/tests/P1222R4_flat_set/test.cpp @@ -136,7 +136,7 @@ void test_constructors() { assert_all_requirements_and_equals(b, {-1, 1, 2, 7, 7, 7, 100}); } -template +template void test_spaceship_operator() { static constexpr bool multiset = _Is_specialization_v; static constexpr bool invert = is_same_v>; @@ -157,7 +157,7 @@ void test_spaceship_operator() { assert((f <=> a) == strong_ordering::greater); } -template +template struct proxy_comparer { bool operator()(const T& lhs, const T& rhs) const { return less ? (lhs < rhs) : (lhs > rhs); From fb1bf7926f061a9a169af207a75eff39478fd21a Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Thu, 22 Jun 2023 00:55:17 +0200 Subject: [PATCH 09/25] CXX23 guards Co-Authored-By: Stephan T. Lavavej Co-Authored-By: Alex Guteniev <3995422+alexguteniev@users.noreply.github.com> --- stl/inc/flat_set | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index b6d6acc2a8c..e2c41f6995c 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -8,6 +8,9 @@ #define _FLAT_SET_ #include #if _STL_COMPILER_PREPROCESSOR +#if !_HAS_CXX23 || !defined(__cpp_lib_concepts) // TRANSITION, GH-395 +_EMIT_STL_WARNING(STL4038, "The contents of are available only with C++23 or later."); +#else // ^^^ not supported / supported language mode vvv #include #include #include @@ -15,6 +18,7 @@ #include _STD_BEGIN + template struct _NODISCARD _Clear_scope_guard { _Ty* _Clearable; @@ -709,7 +713,9 @@ template > flat_multiset(initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_multiset<_Kty, _Keylt>; template > flat_multiset(sorted_equivalent_t, initializer_list<_Kty>, _Keylt = _Keylt()) -> flat_multiset<_Kty, _Keylt>; + _STD_END +#endif // ^^^ supported language mode ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _FLAT_SET_ From 577dd6aa7f25c9b6aa03510385833814f1b1a244 Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Thu, 22 Jun 2023 01:23:58 +0200 Subject: [PATCH 10/25] Down with `typename` Co-Authored-By: Alex Guteniev <3995422+alexguteniev@users.noreply.github.com> --- stl/inc/flat_set | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index e2c41f6995c..c4c5a3c8ba0 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -48,10 +48,10 @@ public: using value_compare = _Keylt; using reference = value_type&; using const_reference = const value_type&; - using size_type = typename _Container::size_type; - using difference_type = typename _Container::difference_type; - using iterator = typename _Container::iterator; - using const_iterator = typename _Container::const_iterator; + using size_type = _Container::size_type; + using difference_type = _Container::difference_type; + using iterator = _Container::iterator; + using const_iterator = _Container::const_iterator; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; using container_type = _Container; From 7b448fb852fd2125fec5fb11ebd4ec09635fd1d5 Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Thu, 22 Jun 2023 01:24:13 +0200 Subject: [PATCH 11/25] Fix `_EXPORT_STD` location --- stl/inc/flat_set | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index c4c5a3c8ba0..4a7f14b00f3 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -609,15 +609,15 @@ _EXPORT_STD struct sorted_equivalent_t { }; _EXPORT_STD inline constexpr sorted_equivalent_t sorted_equivalent{}; -template , class _Container = vector<_Kty>> -_EXPORT_STD class flat_set +_EXPORT_STD template , class _Container = vector<_Kty>> +class flat_set : public _Base_flat_set<_Kty, _Keylt, _Container, false, flat_set<_Kty, _Keylt, _Container>, sorted_unique_t> { public: using _Base_flat_set<_Kty, _Keylt, _Container, false, flat_set, sorted_unique_t>::_Base_flat_set; }; -template , class _Container = vector<_Kty>> -_EXPORT_STD class flat_multiset : public _Base_flat_set<_Kty, _Keylt, _Container, true, +_EXPORT_STD template , class _Container = vector<_Kty>> +class flat_multiset : public _Base_flat_set<_Kty, _Keylt, _Container, true, flat_multiset<_Kty, _Keylt, _Container>, sorted_equivalent_t> { public: using _Base_flat_set<_Kty, _Keylt, _Container, true, flat_multiset, sorted_equivalent_t>::_Base_flat_set; From caf825bb78c6b60561a869ff727c9091a8f7a112 Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Thu, 22 Jun 2023 01:34:40 +0200 Subject: [PATCH 12/25] Oops, format! --- stl/inc/flat_set | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 4a7f14b00f3..85c78d27f38 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -617,8 +617,8 @@ public: }; _EXPORT_STD template , class _Container = vector<_Kty>> -class flat_multiset : public _Base_flat_set<_Kty, _Keylt, _Container, true, - flat_multiset<_Kty, _Keylt, _Container>, sorted_equivalent_t> { +class flat_multiset : public _Base_flat_set<_Kty, _Keylt, _Container, true, flat_multiset<_Kty, _Keylt, _Container>, + sorted_equivalent_t> { public: using _Base_flat_set<_Kty, _Keylt, _Container, true, flat_multiset, sorted_equivalent_t>::_Base_flat_set; }; From 24dbda21bcbb8591791322e5189ffbd542f36db3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 07:15:10 -0700 Subject: [PATCH 13/25] tests/std/test.lst: Add P1222R4_flat_set. --- tests/std/test.lst | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/std/test.lst b/tests/std/test.lst index 822cf153b82..0c0c4e860f9 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -542,6 +542,7 @@ tests\P1206R7_vector_assign_range tests\P1206R7_vector_from_range tests\P1206R7_vector_insert_range tests\P1208R6_source_location +tests\P1222R4_flat_set tests\P1223R5_ranges_alg_find_last tests\P1223R5_ranges_alg_find_last_if tests\P1223R5_ranges_alg_find_last_if_not From 2d44508bc68412d2b4e30be13b112433c7c3f9b6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 07:23:16 -0700 Subject: [PATCH 14/25] yvals_core.h: Sort the feature-test macro. --- stl/inc/yvals_core.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index b8c5b085131..3cf143884e8 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1722,14 +1722,10 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #ifdef __cpp_lib_concepts #define __cpp_lib_containers_ranges 202202L #define __cpp_lib_expected 202211L +#define __cpp_lib_flat_set 202207L #endif // __cpp_lib_concepts -#define __cpp_lib_forward_like 202207L - -#ifdef __cpp_lib_concepts -#define __cpp_lib_flat_set 202207L -#endif // __cpp_lib_concepts - +#define __cpp_lib_forward_like 202207L #define __cpp_lib_invoke_r 202106L #define __cpp_lib_ios_noreplace 202207L #define __cpp_lib_is_scoped_enum 202011L From e85e2c27c261fc1dcb27b331f95766c62efab16d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 07:25:43 -0700 Subject: [PATCH 15/25] yvals_core.h: Add a comment listing the new feature. --- stl/inc/yvals_core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 3cf143884e8..761d5e2291d 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -316,6 +316,7 @@ // P1132R7 out_ptr(), inout_ptr() // P1147R1 Printing volatile Pointers // P1206R7 Conversions From Ranges To Containers +// P1222R4 // P1223R5 ranges::find_last, ranges::find_last_if, ranges::find_last_if_not // P1272R4 byteswap() // P1328R1 constexpr type_info::operator==() From 2213dc0a5cf86045b1fce369c42a101c0d8c0e24 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 07:29:25 -0700 Subject: [PATCH 16/25] VSO_0157762_feature_test_macros: Add test coverage. --- .../test.compile.pass.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 276dd6fdd8d..8a626a8eeb0 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -876,6 +876,20 @@ STATIC_ASSERT(__cpp_lib_filesystem == 201703L); #endif #endif +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 +#ifndef __cpp_lib_flat_set +#error __cpp_lib_flat_set is not defined +#elif __cpp_lib_flat_set != 202207L +#error __cpp_lib_flat_set is not 202207L +#else +STATIC_ASSERT(__cpp_lib_flat_set == 202207L); +#endif +#else +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 +#error __cpp_lib_flat_set is defined +#endif +#endif + #ifdef __cpp_lib_concepts #ifndef __cpp_lib_format #error __cpp_lib_format is not defined From e6157cdc51c57d32f062f0d8110c52a04fc5c0b3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 07:36:14 -0700 Subject: [PATCH 17/25] Add placeholder test coverage for header units and modules. --- tests/std/include/test_header_units_and_modules.hpp | 8 ++++++++ .../tests/P1502R1_standard_library_header_units/test.cpp | 1 + 2 files changed, 9 insertions(+) diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index ce362844dc7..6710a8e7099 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -234,6 +234,13 @@ void test_filesystem() { assert(info.capacity != static_cast(-1)); } +void test_flat_set() { + using namespace std; + puts("Testing ."); + + // FIXME! ADD TEST COVERAGE HERE! +} + void test_format() { using namespace std; puts("Testing ."); @@ -1082,6 +1089,7 @@ void all_cpp_header_tests() { test_execution(); test_expected(); test_filesystem(); + test_flat_set(); test_format(); test_forward_list(); test_fstream(); diff --git a/tests/std/tests/P1502R1_standard_library_header_units/test.cpp b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp index f9fa3090a20..fa11f9e9a79 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/test.cpp +++ b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp @@ -29,6 +29,7 @@ import ; import ; import ; import ; +import ; import ; import ; import ; From c6c59cb30b24239b77f9d055ed3f2a31a4682900 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 07:44:58 -0700 Subject: [PATCH 18/25] flat_set: `_Tsorted _S` => `_Tsorted _Tsort` --- stl/inc/flat_set | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 85c78d27f38..4171876fc7b 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -76,11 +76,11 @@ public: _Assert_after_sorted_input(); } template <_Allocator_for _Alloc> - _Base_flat_set(_Tsorted _S, const container_type& _Cont, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Cont, _Al)) {} + _Base_flat_set(_Tsorted _Tsort, const container_type& _Cont, const _Alloc& _Al) + : _Base_flat_set(_Tsort, container_type(_Cont, _Al)) {} template <_Allocator_for _Alloc> - _Base_flat_set(_Tsorted _S, const container_type& _Cont, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Cont, _Al), _Comp) {} + _Base_flat_set(_Tsorted _Tsort, const container_type& _Cont, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(_Tsort, container_type(_Cont, _Al), _Comp) {} explicit _Base_flat_set(const key_compare& _Comp) : _My_pair(_Zero_then_variadic_args_t{}, _Comp) {} template <_Allocator_for _Alloc> @@ -108,14 +108,14 @@ public: : _Base_flat_set(container_type(_R, _STD forward<_Rng>(_Range), _Al), _Comp) {} template - _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) - : _Base_flat_set(_S, container_type(_First, _Last), _Comp) {} + _Base_flat_set(_Tsorted _Tsort, _Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) + : _Base_flat_set(_Tsort, container_type(_First, _Last), _Comp) {} template _Alloc> - _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_First, _Last, _Al), _Comp) {} + _Base_flat_set(_Tsorted _Tsort, _Iter _First, _Iter _Last, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(_Tsort, container_type(_First, _Last, _Al), _Comp) {} template _Alloc> - _Base_flat_set(_Tsorted _S, _Iter _First, _Iter _Last, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_First, _Last, _Al)) {} + _Base_flat_set(_Tsorted _Tsort, _Iter _First, _Iter _Last, const _Alloc& _Al) + : _Base_flat_set(_Tsort, container_type(_First, _Last, _Al)) {} _Base_flat_set(initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) : _Base_flat_set(_Ilist.begin(), _Ilist.end(), _Comp) {} @@ -126,14 +126,14 @@ public: _Base_flat_set(initializer_list<_Kty> _Ilist, const _Alloc& _Al) : _Base_flat_set(container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} - _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) - : _Base_flat_set(_S, _Ilist.begin(), _Ilist.end(), _Comp) {} + _Base_flat_set(_Tsorted _Tsort, initializer_list<_Kty> _Ilist, const key_compare& _Comp = key_compare()) + : _Base_flat_set(_Tsort, _Ilist.begin(), _Ilist.end(), _Comp) {} template <_Allocator_for _Alloc> - _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} + _Base_flat_set(_Tsorted _Tsort, initializer_list<_Kty> _Ilist, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(_Tsort, container_type(_Ilist.begin(), _Ilist.end(), _Al), _Comp) {} template <_Allocator_for _Alloc> - _Base_flat_set(_Tsorted _S, initializer_list<_Kty> _Ilist, const _Alloc& _Al) - : _Base_flat_set(_S, container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} + _Base_flat_set(_Tsorted _Tsort, initializer_list<_Kty> _Ilist, const _Alloc& _Al) + : _Base_flat_set(_Tsort, container_type(_Ilist.begin(), _Ilist.end(), _Al)) {} _Deriv& operator=(initializer_list<_Kty> _Ilist) { _Get_cont() = container_type(_Ilist.begin(), _Ilist.end()); From 9b46a5c62f13d9f97aaed5253eae4cbd91200d09 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 07:49:33 -0700 Subject: [PATCH 19/25] flat_set: Replace `_R` with `from_range`. --- stl/inc/flat_set | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 4171876fc7b..b92a7163412 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -98,14 +98,14 @@ public: _Base_flat_set(_Iter _First, _Iter _Last, const _Alloc& _Al) : _Base_flat_set(container_type(_First, _Last, _Al)) {} template <_Container_compatible_range<_Kty> _Rng> - _Base_flat_set(from_range_t _R, _Rng&& _Range, const key_compare& _Comp = key_compare()) - : _Base_flat_set(container_type(_R, _STD forward<_Rng>(_Range)), _Comp) {} + _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp = key_compare()) + : _Base_flat_set(container_type(from_range, _STD forward<_Rng>(_Range)), _Comp) {} template <_Container_compatible_range<_Kty> _Rng, _Allocator_for _Alloc> - _Base_flat_set(from_range_t _R, _Rng&& _Range, const _Alloc& _Al) - : _Base_flat_set(container_type(_R, _STD forward<_Rng>(_Range), _Al)) {} + _Base_flat_set(from_range_t, _Rng&& _Range, const _Alloc& _Al) + : _Base_flat_set(container_type(from_range, _STD forward<_Rng>(_Range), _Al)) {} template <_Container_compatible_range<_Kty> _Rng, _Allocator_for _Alloc> - _Base_flat_set(from_range_t _R, _Rng&& _Range, const key_compare& _Comp, const _Alloc& _Al) - : _Base_flat_set(container_type(_R, _STD forward<_Rng>(_Range), _Al), _Comp) {} + _Base_flat_set(from_range_t, _Rng&& _Range, const key_compare& _Comp, const _Alloc& _Al) + : _Base_flat_set(container_type(from_range, _STD forward<_Rng>(_Range), _Al), _Comp) {} template _Base_flat_set(_Tsorted _Tsort, _Iter _First, _Iter _Last, const key_compare& _Comp = key_compare()) From 4fba290363bd7c287c82934d8453e91aac3a7cfd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 07:58:08 -0700 Subject: [PATCH 20/25] flat_set: `lhs` => `_Lhs`, `rhs` => `_Rhs`. --- stl/inc/flat_set | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index b92a7163412..1223c2d9886 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -539,7 +539,7 @@ private: if constexpr (!_Multi) { iterator _End = end(); iterator _New_end = - unique(begin(), _End, [&](const _Kty& lhs, const _Kty& rhs) { return _Keys_equal(lhs, rhs); }); + unique(begin(), _End, [&](const _Kty& _Lhs, const _Kty& _Rhs) { return _Keys_equal(_Lhs, _Rhs); }); _Get_cont().erase(_New_end, _End); } if constexpr (!_Multi) { From 618f0fb507d49d43277bc61a8f9e74f45653ecf5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 08:03:20 -0700 Subject: [PATCH 21/25] flat_set: Qualify `_STD unique`. --- stl/inc/flat_set | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 1223c2d9886..67dc93c4da7 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -539,7 +539,7 @@ private: if constexpr (!_Multi) { iterator _End = end(); iterator _New_end = - unique(begin(), _End, [&](const _Kty& _Lhs, const _Kty& _Rhs) { return _Keys_equal(_Lhs, _Rhs); }); + _STD unique(begin(), _End, [&](const _Kty& _Lhs, const _Kty& _Rhs) { return _Keys_equal(_Lhs, _Rhs); }); _Get_cont().erase(_New_end, _End); } if constexpr (!_Multi) { From f5aa4e4d0c80cef63a9cde6019d2b485ae98fcab Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 08:09:37 -0700 Subject: [PATCH 22/25] P1222R4_flat_set: `multiset` => `multi` --- tests/std/tests/P1222R4_flat_set/test.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P1222R4_flat_set/test.cpp b/tests/std/tests/P1222R4_flat_set/test.cpp index 44deaa13908..344c31e9245 100644 --- a/tests/std/tests/P1222R4_flat_set/test.cpp +++ b/tests/std/tests/P1222R4_flat_set/test.cpp @@ -138,13 +138,12 @@ void test_constructors() { template void test_spaceship_operator() { - static constexpr bool multiset = _Is_specialization_v; - static constexpr bool invert = is_same_v>; + static constexpr bool multi = _Is_specialization_v; + static constexpr bool invert = is_same_v>; T a{3, 2, 2, 1}; T b{1, 2, 3}; - assert( - (a <=> b) == (multiset ? (invert ? strong_ordering::greater : strong_ordering::less) : strong_ordering::equal)); + assert((a <=> b) == (multi ? (invert ? strong_ordering::greater : strong_ordering::less) : strong_ordering::equal)); T c{3, 2}; assert((c <=> b) == (invert ? strong_ordering::less : strong_ordering::greater)); From e6107e8f880764da873a9e5ff47d52a591d0a5a2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 08:10:52 -0700 Subject: [PATCH 23/25] P1222R4_flat_set: `less` => `m_less` --- tests/std/tests/P1222R4_flat_set/test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P1222R4_flat_set/test.cpp b/tests/std/tests/P1222R4_flat_set/test.cpp index 344c31e9245..f95f8c2ee2d 100644 --- a/tests/std/tests/P1222R4_flat_set/test.cpp +++ b/tests/std/tests/P1222R4_flat_set/test.cpp @@ -159,16 +159,16 @@ void test_spaceship_operator() { template struct proxy_comparer { bool operator()(const T& lhs, const T& rhs) const { - return less ? (lhs < rhs) : (lhs > rhs); + return m_less ? (lhs < rhs) : (lhs > rhs); } - bool less = true; + bool m_less = true; }; void test_non_static_comparer() { flat_set> a{3, 2, 2, 1}; assert_all_requirements_and_equals(a, {1, 2, 3}); - auto b = flat_set>({-1, 5, 9, 9, 9, 9, 9}, proxy_comparer{.less = false}); + auto b = flat_set>({-1, 5, 9, 9, 9, 9, 9}, proxy_comparer{.m_less = false}); assert_all_requirements_and_equals(b, {9, 5, -1}); auto aBackup = a; From 172f1c528e9950fcce125fccbf20c8a912896e96 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 08:13:12 -0700 Subject: [PATCH 24/25] P1222R4_flat_set: Include `` for `less` etc. --- tests/std/tests/P1222R4_flat_set/test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/std/tests/P1222R4_flat_set/test.cpp b/tests/std/tests/P1222R4_flat_set/test.cpp index f95f8c2ee2d..f053656cc70 100644 --- a/tests/std/tests/P1222R4_flat_set/test.cpp +++ b/tests/std/tests/P1222R4_flat_set/test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include From 7ba514f50dd7e262e61bab47e61a5177d2ccfec1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 Jun 2023 08:13:49 -0700 Subject: [PATCH 25/25] P1222R4_flat_set: `` is unused. --- tests/std/tests/P1222R4_flat_set/test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/std/tests/P1222R4_flat_set/test.cpp b/tests/std/tests/P1222R4_flat_set/test.cpp index f053656cc70..6a3ae2e1223 100644 --- a/tests/std/tests/P1222R4_flat_set/test.cpp +++ b/tests/std/tests/P1222R4_flat_set/test.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include using namespace std;