From adec1b72b127845afb4a08788ff61e9540e6bd90 Mon Sep 17 00:00:00 2001 From: Vinay Deshmukh Date: Fri, 3 Oct 2025 16:10:04 -0400 Subject: [PATCH 01/19] From PR 134330 Apply initial _LIBCPP_CONSTEXPR_SINCE_CXX26 Add feature test macro one test to start with start seeing constexpr failures for at.pass.cpp member call on object outside its lifetime is not allowed in a constant expression Move past member call on object past it's lifetime Add ctor to initialize __value_type and __tree_node_base, and the object of unique_ptr construction works, at() fails due to throw_out_of_range can't intentionally throw in constexpr note: cast from 'void *' is not allowed in a constant expression because the pointed object type 'std::__tree_node, min_pointer>' is not similar to the target type 'std::__tree_node_base>' note: cast from 'void *' is not allowed in a constant expression because the pointed object type 'std::__tree_node, min_pointer>' is not similar to the target type 'std::__tree_node_base> ignore min_allocator tests for now at.pass.cpp works in cpp26 for some reason empty.verify.cpp passes index_key_.pass.cpp constexpr fixed, but other failure index_rv_key.pass.cpp constexpr fixed, but other failure fix index_tuple.pass.cpp fix: iterator.pass.cpp fix max_size.pass.cpp size.pass.cpp alloc.pass.cpp blocked on assign_initializer_list compare.pass.cpp Modify all tests to have TEST_CONSTEXPR_CXX26 and without passing at: copy_assign.addressof.compile.pass.cpp failing at copy_assign.pass.cpp only in constexpr pass deduct.pass.cpp fix map.cons/from_range.pass.cpp fail at map.cons/move_alloc.pass.cpp fail at map.cons/move_assign.pass.cpp fix map.cons/move_noexcept.pass.cpp pass map.erasure/erase_if.pass.cpp error: call to deleted constructor at map.modifiers/emplace.pass.cpp pass map.modifiers/erase_iter.pass.cpp pass map.modifiers/extract_iterator.pass.cpp TODO: node-handle tests pass map.modifiers/extract_key.pass.cpp pass map.modifiers/insert_and_emplace_allocator_requirements.pass.cpp pass map.modifiers/insert_cv.pass.cpp pass map.modifiers/insert_iter_cv.pass.cpp pass map.modifiers/insert_iter_rv.pass.cpp pass map.modifiers/insert_node_type.pass pass map.modifiers/insert_node_type_hint.pass.cpp pass map.modifiers/insert_or_assign.pass.cpp pass map.modifiers/insert_rv.pass.cpp pass map.modifiers/try.emplace.pass.cpp, fix typos pass map.nonmember/compare.three_way.pass.cpp pass map.nonmember/op_compare.pass.cpp pass map.observers/key_comp.pass.cpp pass map.observers/value_comp.pass.cpp pass map.ops/contains.pass.cpp pass map.ops/contains_transparent.pass.cpp pass map.ops/count.pass.cpp pass map.ops/count_transparent.pass.cpp pass map.ops/equal_range_transparent.pass.cpp pass map.special/member_swap.pass.cpp pass map.value_compare/invoke.pass.cpp pass map.value_compare/types.pass.cpp cleanup Pass compare.pass.cpp pass incomplete_type.pass.cpp error: call to deleted constructor of '__node_value_type' (aka 'std::__value_type') clang-format Generate macro version correctly fix unrelated CI failures pass map.modifiers/emplace.pass.cpp pass map.modifiers/emplace_hint.pass.cpp at.pass.cpp passes again iterator.pass.cpp passes move_assign.pass.cpp constexpr fixed move_alloc.pass.cpp constexpr fixed, other remains copy_assign.pass.cpp constexpr fixed, other remains erase_iter.pass.cpp fix typo map.ops pass Partially fix assign_initializer_list.pass.cpp Fix assign_initializer_list.pass.cpp fix placement new to use std::addressof fix copy_assign.pass.cpp move alloc failure location git-clang-format upstream/main featuer test generation <__type_traits/is_constant_evaluated.h> __node_value_type Use __libcpp_is_constant_evaluated, still at 7 failures fix feature gen? feature macros ? lang support cf restore pair to main back at 7 failures due to min_allocator.h cf? insert_range.pass.cpp, empty passes, stuck at next min_allocator to main tree clang format fix CI? try CI fix? readability-identifier-naming libcpp-hide-from-abi cf _Args not Args map? generic-cxx03 libcpp-hide-from-abi cxx03 tmp WIP??? constexpr test ID* at.pass.cpp works empty.pass.cpp index_key.pass.cpp -> static_assert error: static assertion failed due to requirement 'std::is_same, CopyInsertable<2>>, void *>, std::pair, CopyInsertable<2>>>::value': Only allowed to construct Up iterator.pass.cpp size.pass.cpp map.cons/assign_initializer_list.pass.cpp map.modifiers/emplace.pass.cpp map.modifiers/emplace_hint.pass.cpp map.modifiers/erase_key.pass.cpp map.ops/count.pass.cpp map.ops/equal_range.pass.cpp map.ops/find.pass.cpp map.ops/upper_bound.pass.cpp clang-format fix error value_comp bad merge _root cannot be redeclared remove base and cast copy_assign.pass.cpp fails largely because of constexpr limit, because for Container c, issues happen similar to move_alloc move_assign use __node_traits::construct over placement new, copy_assing copy_alloc still pass cf note for failure TODO add constexpr cpp26 mistake 6 failures something clean clean more fix same_as allocate issues in index_rv_key failures at move_alloc and move_assign allocator for copy_assign index_rv_key at it again haxxx Temporary solution for UB & restriction copy_assign.pass.cpp Finally only 2 tests fail insert_key.pass.cpp Move_alloc.pass.cpp fails add docs move_alloc and move_assign, fail in __insert_unique_from_orphaned_node, need to place the SFINAE there, not in __assign_value kind of fixed it, almost Fix for move_assign almost a fix for move_assign.pass.cpp insert_range_maps_sets.h, needs a lot of constexpr depth add why sfinae insert_and_emplace_allocator_requirements.pass.cpp passes use the typedef remove concepts, collapse unnecessary sfinae some docs breaks correctly still correct failures with cleanup more cleans more clean PR review comment include __memory/construct_at `Assertion `getConstructController()->isInAllocatorConstruct()' failed.`Revert "PR review comment" This reverts commit 4fbb47245f2e47f1e9b59f656b8d29fc5d332082. Fails with: ``` # .---command stderr------------ # | t.tmp.exe: /home/runner/_work/llvm-project/llvm-project/libcxx/test/support/container_test_types.h:399: CopyInsertable<1>::CopyInsertable(const CopyInsertable &) [Dummy = 1]: Assertion `getConstructController()->isInAllocatorConstruct()' failed. # `----------------------------- # error: command failed with exit status: 250 ``` one clean cleanup for libcxx/test/support/container_test_types.h clean back clang-format adjust constexpr steps arg clean Redundant check Add ReleaseNotes use allocator as template arg and allocator_traits, tests passed in cpp26 cf hide from abi Attempt fix for gcc-15 std=c++26 try format and arm fix attempt' cf fix non-ascii =default; noop abi constexpr-dtor WIP: gcc-15 failure investigation fix the first failure with ptr_ is uninitialized fix map revert min_allocator default construction _ptr is not initialized use allocator as template arg and allocator_traits, tests passed in cpp26 remove UB using list cf doc-fix Replace __value_ with __get_value() for __tree_node miss typo fix ctor for cpp03 buffer cf rename in map as well cf include more? hide from abi terser redundant launder single branch remove the & from buffer remove _LIBCPP_STANDALONE_DEBUG cf disable test for g++-15 remove debugging attempts Remove debugging attempt Fix testing at runtime as well Description and links partial fix for } restore TEST_HAS_NO_EXCEPTIONS Remove extra include remove set -x undo debug attempts Refactor libcxx/test/std/containers/associative/map/map.modifiers/insert_range.pass.cpp CWG1514: key() is not constexpr static can't be constexpr Refactor libcxx/test/std/containers/associative/map/map.cons/from_range.pass.cpp Refactor libcxx/test/std/containers/associative/map/map.cons/copy_alloc.pass.cpp Refactor libcxx/test/std/containers/associative/map/map.cons/copy.pass.cpp Refactor libcxx/test/std/containers/associative/map/map.access/index_rv_key.pass.cpp Refactor libcxx/test/std/containers/associative/map/map.access/index_key.pass.cpp grammar Pass the generic-hardening-mode-debug cf and remove non-ascii Remove hide abi obsolete comment Add FIXME Apply cf cf add constexpr cf Move ReleaseNotes to Implemented papers Fix order of annotations node-handle doc unrelated defaulting undo previous unnecessary destructor for __tree_node_base Remove constexpr from cpp03 code Unnecessary annotation on deleted function simplify type_trait Allow runtime decision for __insert_unique_from_orphaned_node Allow runtime decision for __assign_value local cf Simplify at.pass.cpp use TEST_IS_CONSTANT_EVALUATED over libcxx function Remove extra arm CI hack missing space Avoid creating a __tmp explicit copy Remove constexpr annotations from multimap CI fix for clang <=20 Check clang<20 only for clang based compilers Fix apple-clang macro lookup Fixme, not todo Updated FIXME Remove assert(test()); clang-format? Synopsis attach: // constexpr since C++26 Revert "Remove assert(test());" This reverts commit 9f931f59588b2d1a4deaaafc8dcde8420ed23f3b. Fix the sed script --- libcxx/docs/FeatureTestMacroTable.rst | 18 +- libcxx/docs/ReleaseNotes/22.rst | 13 +- .../include/__iterator/erase_if_container.h | 3 +- libcxx/include/__node_handle | 46 +- libcxx/include/__tree | 876 ++++++++++-------- .../lazy_synth_three_way_comparator.h | 33 +- libcxx/include/map | 714 +++++++------- libcxx/include/version | 39 +- libcxx/test/std/containers/Emplaceable.h | 22 +- .../from_range_associative_containers.h | 18 +- .../associative/map/compare.pass.cpp | 15 +- .../associative/map/get_allocator.pass.cpp | 11 +- .../associative/map/incomplete_type.pass.cpp | 17 +- .../associative/map/map.access/at.pass.cpp | 66 +- .../associative/map/map.access/empty.pass.cpp | 11 +- .../map/map.access/index_key.pass.cpp | 14 +- .../map/map.access/index_rv_key.pass.cpp | 16 +- .../map/map.access/index_tuple.pass.cpp | 14 +- .../map/map.access/iterator.pass.cpp | 33 +- .../map/map.access/max_size.pass.cpp | 11 +- .../associative/map/map.access/size.pass.cpp | 11 +- .../associative/map/map.cons/alloc.pass.cpp | 11 +- .../map.cons/assign_initializer_list.pass.cpp | 17 +- .../associative/map/map.cons/compare.pass.cpp | 11 +- .../map/map.cons/compare_alloc.pass.cpp | 11 +- .../associative/map/map.cons/copy.pass.cpp | 12 +- .../map/map.cons/copy_alloc.pass.cpp | 13 +- .../map/map.cons/copy_assign.pass.cpp | 43 +- .../associative/map/map.cons/deduct.pass.cpp | 11 +- .../map/map.cons/deduct_const.pass.cpp | 11 +- .../associative/map/map.cons/default.pass.cpp | 11 +- .../map/map.cons/default_noexcept.pass.cpp | 11 +- .../map/map.cons/dtor_noexcept.pass.cpp | 11 +- .../map/map.cons/from_range.pass.cpp | 15 +- .../map/map.cons/initializer_list.pass.cpp | 11 +- .../initializer_list_compare.pass.cpp | 11 +- .../initializer_list_compare_alloc.pass.cpp | 11 +- .../map/map.cons/iter_iter.pass.cpp | 11 +- .../map/map.cons/iter_iter_comp.pass.cpp | 11 +- .../map.cons/iter_iter_comp_alloc.pass.cpp | 11 +- .../associative/map/map.cons/move.pass.cpp | 11 +- .../map/map.cons/move_alloc.pass.cpp | 12 +- .../map/map.cons/move_assign.pass.cpp | 13 +- .../map/map.cons/move_noexcept.pass.cpp | 12 +- .../map/map.erasure/erase_if.pass.cpp | 29 +- .../map/map.modifiers/clear.pass.cpp | 11 +- .../map/map.modifiers/emplace.pass.cpp | 122 +-- .../map/map.modifiers/emplace_hint.pass.cpp | 111 ++- .../map/map.modifiers/erase_iter.pass.cpp | 13 +- .../map.modifiers/erase_iter_iter.pass.cpp | 11 +- .../map/map.modifiers/erase_key.pass.cpp | 11 +- .../map.modifiers/extract_iterator.pass.cpp | 25 +- .../map/map.modifiers/extract_key.pass.cpp | 24 +- .../map/map.modifiers/insert_cv.pass.cpp | 15 +- .../insert_initializer_list.pass.cpp | 11 +- .../map/map.modifiers/insert_iter_cv.pass.cpp | 15 +- .../map.modifiers/insert_iter_iter.pass.cpp | 11 +- .../map/map.modifiers/insert_iter_rv.pass.cpp | 15 +- .../map.modifiers/insert_or_assign.pass.cpp | 35 +- .../map/map.modifiers/insert_range.pass.cpp | 12 +- .../map/map.modifiers/insert_rv.pass.cpp | 15 +- .../map/map.modifiers/try.emplace.pass.cpp | 39 +- .../map.nonmember/compare.three_way.pass.cpp | 7 +- .../map/map.nonmember/op_compare.pass.cpp | 12 +- .../map/map.observers/key_comp.pass.cpp | 13 +- .../map/map.observers/value_comp.pass.cpp | 13 +- .../associative/map/map.ops/contains.pass.cpp | 20 +- .../map/map.ops/contains_transparent.pass.cpp | 31 +- .../associative/map/map.ops/count.pass.cpp | 19 +- .../associative/map/map.ops/count0.pass.cpp | 11 +- .../map/map.ops/count_transparent.pass.cpp | 22 +- .../map/map.ops/equal_range.pass.cpp | 13 +- .../map/map.ops/equal_range0.pass.cpp | 13 +- .../map.ops/equal_range_transparent.pass.cpp | 23 +- .../associative/map/map.ops/find.pass.cpp | 14 +- .../associative/map/map.ops/find0.pass.cpp | 13 +- .../map/map.ops/lower_bound.pass.cpp | 13 +- .../map/map.ops/lower_bound0.pass.cpp | 13 +- .../map/map.ops/upper_bound.pass.cpp | 13 +- .../map/map.ops/upper_bound0.pass.cpp | 14 +- .../map/map.special/member_swap.pass.cpp | 11 +- .../map/map.special/non_member_swap.pass.cpp | 11 +- .../map/map.special/swap_noexcept.pass.cpp | 13 +- .../map/map.value_compare/invoke.pass.cpp | 17 +- .../containers/associative/map/types.pass.cpp | 9 +- .../container.node/node_handle.pass.cpp | 52 +- .../std/containers/insert_range_maps_sets.h | 13 +- libcxx/test/std/containers/test_compare.h | 18 +- .../map.version.compile.pass.cpp | 626 +++++++------ .../version.version.compile.pass.cpp | 356 +++---- libcxx/test/support/is_transparent.h | 13 +- libcxx/test/support/private_constructor.h | 18 +- .../generate_feature_test_macro_components.py | 66 +- 93 files changed, 2504 insertions(+), 1824 deletions(-) diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 8fba6db871f08..1e096bcb325d1 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -198,10 +198,6 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_char8_t`` ``201907L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_common_reference`` ``202302L`` - ---------------------------------------------------------- ----------------- - ``__cpp_lib_common_reference_wrapper`` ``202302L`` - ---------------------------------------------------------- ----------------- ``__cpp_lib_concepts`` ``202002L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_algorithms`` ``201806L`` @@ -380,7 +376,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_ranges_iota`` ``202202L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_ranges_join_with`` ``202202L`` + ``__cpp_lib_ranges_join_with`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_ranges_repeat`` ``202207L`` ---------------------------------------------------------- ----------------- @@ -418,8 +414,6 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_atomic_min_max`` *unimplemented* ---------------------------------------------------------- ----------------- - ``__cpp_lib_atomic_ref`` ``202411L`` - ---------------------------------------------------------- ----------------- ``__cpp_lib_bind_front`` ``202306L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_bitset`` ``202306L`` @@ -430,11 +424,13 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_list`` ``202502L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_map`` ``202502L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_new`` ``202406L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_queue`` ``202502L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_constrained_equality`` ``202411L`` + ``__cpp_lib_constrained_equality`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_copyable_function`` *unimplemented* ---------------------------------------------------------- ----------------- @@ -482,7 +478,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_not_fn`` ``202306L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_optional_range_support`` ``202406L`` + ``__cpp_lib_optional_range_support`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_out_ptr`` ``202311L`` ---------------------------------------------------------- ----------------- @@ -490,8 +486,6 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_ranges_concat`` *unimplemented* ---------------------------------------------------------- ----------------- - ``__cpp_lib_ranges_indices`` ``202506L`` - ---------------------------------------------------------- ----------------- ``__cpp_lib_ratio`` ``202306L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_rcu`` *unimplemented* @@ -510,8 +504,6 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_sstream_from_string_view`` ``202306L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_string_subview`` ``202506L`` - ---------------------------------------------------------- ----------------- ``__cpp_lib_string_view`` ``202403L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_submdspan`` *unimplemented* diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index 0fd7e53aed158..c6ee41bccdb30 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -40,11 +40,8 @@ Implemented Papers - P2321R2: ``zip`` (`Github `__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release) -- P3044R2: sub-``string_view`` from ``string`` (`Github `__) -- P3223R2: Making ``std::istream::ignore`` less surprising (`Github `__) -- P3060R3: Add ``std::views::indices(n)`` (`Github `__) -- P2835R7: Expose ``std::atomic_ref``'s object address (`Github `__) - P3168R2: Give ``std::optional`` Range Support (`Github `__) +- P3372R3: ``constexpr map`` (`Github `__) (The paper is partially implemented. ``constexpr map`` is implemented in this release) Improvements and New Features ----------------------------- @@ -67,14 +64,6 @@ Improvements and New Features - Multiple internal types have been refactored to use ``[[no_unique_address]]``, resulting in faster compile times and reduced debug information. -- The performance of ``std::find`` has been improved by up to 2x for integral types -- The ``std::distance`` and ``std::ranges::distance`` algorithms have been optimized for segmented iterators (e.g., - ``std::join_view`` iterators), reducing the complexity from ``O(n)`` to ``O(n / segment_size)``. Benchmarks show - performance improvements of over 1600x in favorable cases with large segment sizes (e.g., 1024). -- The ``std::{fill, fill_n}`` and ``std::ranges::{fill, fill_n}`` algorithms have been optimized for segmented iterators, - resulting in a performance improvement of at least 10x for ``std::deque`` iterators and - ``std::join_view>>`` iterators. - Deprecations and Removals ------------------------- diff --git a/libcxx/include/__iterator/erase_if_container.h b/libcxx/include/__iterator/erase_if_container.h index 0f87f50cd1c16..8d92d3f1b9dbe 100644 --- a/libcxx/include/__iterator/erase_if_container.h +++ b/libcxx/include/__iterator/erase_if_container.h @@ -22,7 +22,8 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_HIDE_FROM_ABI typename _Container::size_type __libcpp_erase_if_container(_Container& __c, _Predicate& __pred) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename _Container::size_type +__libcpp_erase_if_container(_Container& __c, _Predicate& __pred) { typename _Container::size_type __old_size = __c.size(); const typename _Container::iterator __last = __c.end(); diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle index b20b0c73a0518..83dfe146a0f61 100644 --- a/libcxx/include/__node_handle +++ b/libcxx/include/__node_handle @@ -30,30 +30,30 @@ private: public: // [container.node.cons], constructors, copy, and assignment - constexpr node-handle() noexcept : ptr_(), alloc_() {} - node-handle(node-handle&&) noexcept; - node-handle& operator=(node-handle&&); + constexpr node-handle() noexcept : ptr_(), alloc_() {} // constexpr since C++26 + node-handle(node-handle&&) noexcept; // constexpr since C++26 + node-handle& operator=(node-handle&&); // constexpr since C++26 // [container.node.dtor], destructor - ~node-handle(); + ~node-handle(); // constexpr since C++26 // [container.node.observers], observers value_type& value() const; // not present for map containers key_type& key() const; // not present for set containers - mapped_type& mapped() const; // not present for set containers + mapped_type& mapped() const; // not present for set containers // constexpr since C++26 - allocator_type get_allocator() const; - explicit operator bool() const noexcept; - [[nodiscard]] bool empty() const noexcept; // nodiscard since C++20 + allocator_type get_allocator() const; // constexpr since C++26 + explicit operator bool() const noexcept; // constexpr since C++26 + [[nodiscard]] bool empty() const noexcept; // nodiscard since C++20 // constexpr since C++26 // [container.node.modifiers], modifiers void swap(node-handle&) noexcept(ator_traits::propagate_on_container_swap::value || - ator_traits::is_always_equal::value); + ator_traits::is_always_equal::value); // constexpr since C++26 friend void swap(node-handle& x, node-handle& y) noexcept(noexcept(x.swap(y))) { x.swap(y); - } + } // constexpr since C++26 }; */ @@ -99,12 +99,12 @@ private: __node_pointer_type __ptr_ = nullptr; optional __alloc_; - _LIBCPP_HIDE_FROM_ABI void __release_ptr() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __release_ptr() { __ptr_ = nullptr; __alloc_ = std::nullopt; } - _LIBCPP_HIDE_FROM_ABI void __destroy_node_pointer() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __destroy_node_pointer() { if (__ptr_ != nullptr) { typedef typename __allocator_traits_rebind< allocator_type, _NodeType>::type __node_alloc_type; __node_alloc_type __alloc(*__alloc_); @@ -113,19 +113,20 @@ private: } } - _LIBCPP_HIDE_FROM_ABI __basic_node_handle(__node_pointer_type __ptr, allocator_type const& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __basic_node_handle(__node_pointer_type __ptr, allocator_type const& __alloc) : __ptr_(__ptr), __alloc_(__alloc) {} public: - _LIBCPP_HIDE_FROM_ABI __basic_node_handle() = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __basic_node_handle() = default; - _LIBCPP_HIDE_FROM_ABI __basic_node_handle(__basic_node_handle&& __other) noexcept + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __basic_node_handle(__basic_node_handle&& __other) noexcept : __ptr_(__other.__ptr_), __alloc_(std::move(__other.__alloc_)) { __other.__ptr_ = nullptr; __other.__alloc_ = std::nullopt; } - _LIBCPP_HIDE_FROM_ABI __basic_node_handle& operator=(__basic_node_handle&& __other) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __basic_node_handle& operator=(__basic_node_handle&& __other) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __alloc_ == std::nullopt || __alloc_traits::propagate_on_container_move_assignment::value || __alloc_ == __other.__alloc_, @@ -144,13 +145,13 @@ public: return *this; } - _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return *__alloc_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 allocator_type get_allocator() const { return *__alloc_; } - _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ptr_ != nullptr; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit operator bool() const { return __ptr_ != nullptr; } - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const { return __ptr_ == nullptr; } - _LIBCPP_HIDE_FROM_ABI void swap(__basic_node_handle& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(__basic_node_handle& __other) noexcept( __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value) { using std::swap; swap(__ptr_, __other.__ptr_); @@ -159,12 +160,12 @@ public: swap(__alloc_, __other.__alloc_); } - _LIBCPP_HIDE_FROM_ABI friend void + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend void swap(__basic_node_handle& __a, __basic_node_handle& __b) noexcept(noexcept(__a.swap(__b))) { __a.swap(__b); } - _LIBCPP_HIDE_FROM_ABI ~__basic_node_handle() { __destroy_node_pointer(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~__basic_node_handle() { __destroy_node_pointer(); } }; template @@ -179,6 +180,7 @@ struct __map_node_handle_specifics { using key_type = __remove_const_t; using mapped_type = typename _NodeType::__node_value_type::second_type; + // This method is not constexpr as per the standard. _LIBCPP_HIDE_FROM_ABI key_type& key() const { return const_cast(static_cast<_Derived const*>(this)->__ptr_->__get_value().first); } diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 0738c8c6a5e2b..ecaa72f591622 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -28,13 +28,14 @@ #include <__type_traits/copy_cvref.h> #include <__type_traits/enable_if.h> #include <__type_traits/invoke.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_same.h> #include <__type_traits/is_specialization.h> #include <__type_traits/is_swappable.h> -#include <__type_traits/make_transparent.h> #include <__type_traits/remove_const.h> #include <__utility/forward.h> #include <__utility/lazy_synth_three_way_comparator.h> @@ -111,7 +112,7 @@ __root, have a non-null __parent_ field. // Returns: true if __x is a left child of its parent, else false // Precondition: __x != nullptr. template -inline _LIBCPP_HIDE_FROM_ABI bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT { return __x == __x->__parent_->__left_; } @@ -119,7 +120,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT { // __x is a proper subtree, returns the black height (null counts as 1). If // __x is an improper subtree, returns 0. template -unsigned __tree_sub_invariant(_NodePtr __x) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 unsigned __tree_sub_invariant(_NodePtr __x) { if (__x == nullptr) return 1; // parent consistency checked by caller @@ -151,7 +152,7 @@ unsigned __tree_sub_invariant(_NodePtr __x) { // __root == nullptr is a proper tree. Returns true if __root is a proper // red black tree, else returns false. template -_LIBCPP_HIDE_FROM_ABI bool __tree_invariant(_NodePtr __root) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __tree_invariant(_NodePtr __root) { if (__root == nullptr) return true; // check __x->__parent_ consistency @@ -168,7 +169,7 @@ _LIBCPP_HIDE_FROM_ABI bool __tree_invariant(_NodePtr __root) { // Returns: pointer to the left-most node under __x. template -inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null"); while (__x->__left_ != nullptr) __x = __x->__left_; @@ -177,7 +178,7 @@ inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT { // Returns: pointer to the right-most node under __x. template -inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null"); while (__x->__right_ != nullptr) __x = __x->__right_; @@ -186,7 +187,7 @@ inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT { // Returns: pointer to the next in-order node after __x. template -_LIBCPP_HIDE_FROM_ABI _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); if (__x->__right_ != nullptr) return std::__tree_min(__x->__right_); @@ -201,10 +202,10 @@ _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT { // to the actual root of the tree through a __left_ pointer. Incrementing the end() pointer is UB, so we can assume that // never happens. template -inline _LIBCPP_HIDE_FROM_ABI _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); if (__x->__right_ != nullptr) - return static_cast<_EndNodePtr>(std::__tree_min(__x->__right_)); + return std::__static_fancy_pointer_cast<_EndNodePtr>(std::__tree_min(__x->__right_)); while (!std::__tree_is_left_child(__x)) __x = __x->__parent_unsafe(); return static_cast<_EndNodePtr>(__x->__parent_); @@ -213,11 +214,11 @@ inline _LIBCPP_HIDE_FROM_ABI _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEP // Returns: pointer to the previous in-order node before __x. // Note: __x may be the end node. template -inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); if (__x->__left_ != nullptr) return std::__tree_max(__x->__left_); - _NodePtr __xx = static_cast<_NodePtr>(__x); + _NodePtr __xx = std::__static_fancy_pointer_cast<_NodePtr>(__x); while (std::__tree_is_left_child(__xx)) __xx = __xx->__parent_unsafe(); return __xx->__parent_unsafe(); @@ -225,7 +226,7 @@ inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEP // Returns: pointer to a node which has no children template -_LIBCPP_HIDE_FROM_ABI _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); while (true) { if (__x->__left_ != nullptr) { @@ -244,7 +245,7 @@ _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT { // Effects: Makes __x->__right_ the subtree root with __x as its left child // while preserving in-order order. template -_LIBCPP_HIDE_FROM_ABI void __tree_left_rotate(_NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree_left_rotate(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); _LIBCPP_ASSERT_INTERNAL(__x->__right_ != nullptr, "node should have a right child"); _NodePtr __y = __x->__right_; @@ -263,7 +264,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree_left_rotate(_NodePtr __x) _NOEXCEPT { // Effects: Makes __x->__left_ the subtree root with __x as its right child // while preserving in-order order. template -_LIBCPP_HIDE_FROM_ABI void __tree_right_rotate(_NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree_right_rotate(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); _LIBCPP_ASSERT_INTERNAL(__x->__left_ != nullptr, "node should have a left child"); _NodePtr __y = __x->__left_; @@ -287,7 +288,8 @@ _LIBCPP_HIDE_FROM_ABI void __tree_right_rotate(_NodePtr __x) _NOEXCEPT { // Postcondition: __tree_invariant(end_node->__left_) == true. end_node->__left_ // may be different than the value passed in as __root. template -_LIBCPP_HIDE_FROM_ABI void __tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void +__tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root of the tree shouldn't be null"); _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Can't attach null node to a leaf"); __x->__is_black_ = __x == __root; @@ -343,7 +345,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree_balance_after_insert(_NodePtr __root, _NodePtr // nor any of its children refer to __z. end_node->__left_ // may be different than the value passed in as __root. template -_LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root node should not be null"); _LIBCPP_ASSERT_INTERNAL(__z != nullptr, "The node to remove should not be null"); _LIBCPP_ASSERT_INTERNAL(std::__tree_invariant(__root), "The tree invariants should hold"); @@ -558,7 +560,7 @@ public: using pointer = _Pointer; pointer __left_; - _LIBCPP_HIDE_FROM_ABI __tree_end_node() _NOEXCEPT : __left_() {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_end_node() _NOEXCEPT : __left_(nullptr) {} }; template @@ -571,11 +573,15 @@ public: __end_node_pointer __parent_; bool __is_black_; - _LIBCPP_HIDE_FROM_ABI pointer __parent_unsafe() const { return static_cast(__parent_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer __parent_unsafe() const { + return std::__static_fancy_pointer_cast(__parent_); + } - _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = static_cast<__end_node_pointer>(__p); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __set_parent(pointer __p) { + __parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__p); + } - _LIBCPP_HIDE_FROM_ABI __tree_node_base() = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_node_base() = default; __tree_node_base(__tree_node_base const&) = delete; __tree_node_base& operator=(__tree_node_base const&) = delete; }; @@ -596,7 +602,7 @@ private: }; public: - _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_value_type& __get_value() { return __value_; } #else private: @@ -607,10 +613,27 @@ public: #endif template - _LIBCPP_HIDE_FROM_ABI explicit __tree_node(_Alloc& __na, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_node(_Alloc& __na, _Args&&... __args) { allocator_traits<_Alloc>::construct(__na, std::addressof(__get_value()), std::forward<_Args>(__args)...); } + +// This line fails with: +// libcxx/test-suite-install/include/c++/v1/__memory/construct_at.h:38:49: note: non-literal type +// 'std::__tree_node, void *>' cannot be used in a constant expression +// +// during constant evaluation as part of P3372 +// on: +// 1. Arm CI which is on clang 19.x (will be fixed in: https://github.com/llvm/llvm-project/issues/161159 ) +// 2. AppleClang is not yet using clang >= 20.x, which has "fixed" this issue +// 3. A few others like FreeBSD/amd64, AArch64, AIX +// FIXME: when AppleClang is based off of clang >= 20.x +// FIXME: when Clang-based CI is using clang >= 20.x +#if (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 2000) || \ + (defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 2000) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~__tree_node() {} +#else ~__tree_node() = delete; +#endif __tree_node(__tree_node const&) = delete; __tree_node& operator=(__tree_node const&) = delete; }; @@ -629,14 +652,15 @@ private: public: bool __value_constructed; - _LIBCPP_HIDE_FROM_ABI __tree_node_destructor(const __tree_node_destructor&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_node_destructor(const __tree_node_destructor&) = default; __tree_node_destructor& operator=(const __tree_node_destructor&) = delete; - _LIBCPP_HIDE_FROM_ABI explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT : __na_(__na), __value_constructed(__val) {} - _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void operator()(pointer __p) _NOEXCEPT { if (__value_constructed) __alloc_traits::destroy(__na_, std::addressof(__p->__get_value())); if (__p) @@ -673,44 +697,50 @@ public: using reference = value_type&; using pointer = __rebind_pointer_t<_NodePtr, value_type>; - _LIBCPP_HIDE_FROM_ABI __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return __get_np()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__get_value()); } - _LIBCPP_HIDE_FROM_ABI __tree_iterator& operator++() { - __ptr_ = std::__tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator& operator++() { + __ptr_ = std::__tree_next_iter<__end_node_pointer>(std::__static_fancy_pointer_cast<__node_base_pointer>(__ptr_)); return *this; } - _LIBCPP_HIDE_FROM_ABI __tree_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator operator++(int) { __tree_iterator __t(*this); ++(*this); return __t; } - _LIBCPP_HIDE_FROM_ABI __tree_iterator& operator--() { - __ptr_ = static_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator& operator--() { + __ptr_ = std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_)); return *this; } - _LIBCPP_HIDE_FROM_ABI __tree_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator operator--(int) { __tree_iterator __t(*this); --(*this); return __t; } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __tree_iterator& __x, const __tree_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const __tree_iterator& __x, const __tree_iterator& __y) { return __x.__ptr_ == __y.__ptr_; } - friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator!=(const __tree_iterator& __x, const __tree_iterator& __y) { return !(__x == __y); } private: - _LIBCPP_HIDE_FROM_ABI explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} - _LIBCPP_HIDE_FROM_ABI explicit __tree_iterator(__end_node_pointer __p) _NOEXCEPT : __ptr_(__p) {} - _LIBCPP_HIDE_FROM_ABI __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_iterator(__node_pointer __p) _NOEXCEPT + : __ptr_(std::__static_fancy_pointer_cast<__end_node_pointer>(__p)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_iterator(__end_node_pointer __p) _NOEXCEPT + : __ptr_(__p) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __get_np() const { + return std::__static_fancy_pointer_cast<__node_pointer>(__ptr_); + } template friend class __tree; template @@ -735,48 +765,55 @@ public: using pointer = __rebind_pointer_t<_NodePtr, const value_type>; using __non_const_iterator _LIBCPP_NODEBUG = __tree_iterator<_Tp, __node_pointer, difference_type>; - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator() _NOEXCEPT : __ptr_(nullptr) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator() _NOEXCEPT : __ptr_(nullptr) {} - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT : __ptr_(__p.__ptr_) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT + : __ptr_(__p.__ptr_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return __get_np()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__get_value()); } - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator& operator++() { - __ptr_ = std::__tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator& operator++() { + __ptr_ = std::__tree_next_iter<__end_node_pointer>(std::__static_fancy_pointer_cast<__node_base_pointer>(__ptr_)); return *this; } - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator operator++(int) { __tree_const_iterator __t(*this); ++(*this); return __t; } - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator& operator--() { - __ptr_ = static_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator& operator--() { + __ptr_ = std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_)); return *this; } - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator operator--(int) { __tree_const_iterator __t(*this); --(*this); return __t; } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y) { return __x.__ptr_ == __y.__ptr_; } - friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y) { return !(__x == __y); } private: - _LIBCPP_HIDE_FROM_ABI explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} - _LIBCPP_HIDE_FROM_ABI explicit __tree_const_iterator(__end_node_pointer __p) _NOEXCEPT : __ptr_(__p) {} - _LIBCPP_HIDE_FROM_ABI __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT + : __ptr_(std::__static_fancy_pointer_cast<__end_node_pointer>(__p)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_const_iterator(__end_node_pointer __p) _NOEXCEPT + : __ptr_(std::__static_fancy_pointer_cast<__end_node_pointer>(__p)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __get_np() const { + return std::__static_fancy_pointer_cast<__node_pointer>(__ptr_); + } template friend class __tree; @@ -852,63 +889,73 @@ private: _LIBCPP_COMPRESSED_PAIR(size_type, __size_, value_compare, __value_comp_); public: - _LIBCPP_HIDE_FROM_ABI __end_node_pointer __end_node() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __end_node_pointer __end_node() _NOEXCEPT { return pointer_traits<__end_node_pointer>::pointer_to(__end_node_); } - _LIBCPP_HIDE_FROM_ABI __end_node_pointer __end_node() const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __end_node_pointer __end_node() const _NOEXCEPT { return pointer_traits<__end_node_pointer>::pointer_to(const_cast<__end_node_t&>(__end_node_)); } - _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __node_alloc_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_allocator& __node_alloc() _NOEXCEPT { + return __node_alloc_; + } private: - _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __node_alloc_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const __node_allocator& __node_alloc() const _NOEXCEPT { + return __node_alloc_; + } public: - _LIBCPP_HIDE_FROM_ABI allocator_type __alloc() const _NOEXCEPT { return allocator_type(__node_alloc()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 allocator_type __alloc() const _NOEXCEPT { + return allocator_type(__node_alloc()); + } - _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; } - _LIBCPP_HIDE_FROM_ABI value_compare& value_comp() _NOEXCEPT { return __value_comp_; } - _LIBCPP_HIDE_FROM_ABI const value_compare& value_comp() const _NOEXCEPT { return __value_comp_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const _NOEXCEPT { return __size_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare& value_comp() _NOEXCEPT { return __value_comp_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const value_compare& value_comp() const _NOEXCEPT { + return __value_comp_; + } public: - _LIBCPP_HIDE_FROM_ABI __node_pointer __root() const _NOEXCEPT { - return static_cast<__node_pointer>(__end_node()->__left_); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __root() const _NOEXCEPT { + return std::__static_fancy_pointer_cast<__node_pointer>(__end_node()->__left_); } - _LIBCPP_HIDE_FROM_ABI __node_base_pointer* __root_ptr() const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer* __root_ptr() const _NOEXCEPT { return std::addressof(__end_node()->__left_); } using iterator = __tree_iterator<_Tp, __node_pointer, difference_type>; using const_iterator = __tree_const_iterator<_Tp, __node_pointer, difference_type>; - _LIBCPP_HIDE_FROM_ABI explicit __tree(const value_compare& __comp) _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree(const value_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_copy_constructible::value) : __size_(0), __value_comp_(__comp) { __begin_node_ = __end_node(); } - _LIBCPP_HIDE_FROM_ABI explicit __tree(const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree(const allocator_type& __a) : __begin_node_(), __node_alloc_(__node_allocator(__a)), __size_(0) { __begin_node_ = __end_node(); } - _LIBCPP_HIDE_FROM_ABI __tree(const value_compare& __comp, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(const value_compare& __comp, const allocator_type& __a) : __begin_node_(), __node_alloc_(__node_allocator(__a)), __size_(0), __value_comp_(__comp) { __begin_node_ = __end_node(); } - _LIBCPP_HIDE_FROM_ABI __tree(const __tree& __t); - _LIBCPP_HIDE_FROM_ABI __tree& operator=(const __tree& __t); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(const __tree& __t); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree& operator=(const __tree& __t); template - _LIBCPP_HIDE_FROM_ABI void __assign_unique(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_unique(_ForwardIterator __first, _ForwardIterator __last); template - _LIBCPP_HIDE_FROM_ABI void __assign_multi(_InputIterator __first, _InputIterator __last); - _LIBCPP_HIDE_FROM_ABI __tree(__tree&& __t) _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_multi(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(__tree&& __t) _NOEXCEPT_( is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible::value); - _LIBCPP_HIDE_FROM_ABI __tree(__tree&& __t, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(__tree&& __t, const allocator_type& __a); - _LIBCPP_HIDE_FROM_ABI __tree& operator=(__tree&& __t) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree& operator=(__tree&& __t) _NOEXCEPT_(is_nothrow_move_assignable::value && ((__node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable<__node_allocator>::value) || @@ -917,23 +964,27 @@ public: return *this; } - _LIBCPP_HIDE_FROM_ABI ~__tree() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~__tree() { static_assert(is_copy_constructible::value, "Comparator must be copy-constructible."); destroy(__root()); } - _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__begin_node_); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return const_iterator(__begin_node_); } - _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return iterator(__end_node()); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return const_iterator(__end_node()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() _NOEXCEPT { return iterator(__begin_node_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const _NOEXCEPT { + return const_iterator(__begin_node_); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() _NOEXCEPT { return iterator(__end_node()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const _NOEXCEPT { + return const_iterator(__end_node()); + } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const _NOEXCEPT { return std::min(__node_traits::max_size(__node_alloc()), numeric_limits::max()); } - _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI void swap(__tree& __t) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(__tree& __t) #if _LIBCPP_STD_VER <= 11 _NOEXCEPT_(__is_nothrow_swappable_v && (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>)); @@ -942,21 +993,22 @@ public: #endif template - _LIBCPP_HIDE_FROM_ABI iterator __emplace_multi(_Args&&... __args); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_multi(_Args&&... __args); template - _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __emplace_hint_multi(const_iterator __p, _Args&&... __args); template - _LIBCPP_HIDE_FROM_ABI pair __emplace_unique(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __emplace_unique(_Args&&... __args) { return std::__try_key_extraction( [this](const key_type& __key, _Args&&... __args2) { auto [__parent, __child] = __find_equal(__key); - __node_pointer __r = static_cast<__node_pointer>(__child); + __node_pointer __r = std::__static_fancy_pointer_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __node_holder __h = __construct_node(std::forward<_Args>(__args2)...); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); __r = __h.release(); __inserted = true; } @@ -965,10 +1017,10 @@ public: [this](_Args&&... __args2) { __node_holder __h = __construct_node(std::forward<_Args>(__args2)...); auto [__parent, __child] = __find_equal(__h->__get_value()); - __node_pointer __r = static_cast<__node_pointer>(__child); + __node_pointer __r = std::__static_fancy_pointer_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); __r = __h.release(); __inserted = true; } @@ -978,16 +1030,17 @@ public: } template - _LIBCPP_HIDE_FROM_ABI pair __emplace_hint_unique(const_iterator __p, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_hint_unique(const_iterator __p, _Args&&... __args) { return std::__try_key_extraction( [this, __p](const key_type& __key, _Args&&... __args2) { __node_base_pointer __dummy; auto [__parent, __child] = __find_equal(__p, __dummy, __key); - __node_pointer __r = static_cast<__node_pointer>(__child); + __node_pointer __r = std::__static_fancy_pointer_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __node_holder __h = __construct_node(std::forward<_Args>(__args2)...); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); __r = __h.release(); __inserted = true; } @@ -997,9 +1050,9 @@ public: __node_holder __h = __construct_node(std::forward<_Args>(__args2)...); __node_base_pointer __dummy; auto [__parent, __child] = __find_equal(__p, __dummy, __h->__get_value()); - __node_pointer __r = static_cast<__node_pointer>(__child); + __node_pointer __r = std::__static_fancy_pointer_cast<__node_pointer>(__child); if (__child == nullptr) { - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); __r = __h.release(); } return pair(iterator(__r), __child == nullptr); @@ -1007,29 +1060,62 @@ public: std::forward<_Args>(__args)...); } + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_hint_unique__sfinae(true_type, const_iterator __p, _Args&&... __args) { + return __emplace_hint_unique(__p, __args...); + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_hint_unique__sfinae(false_type, const_iterator, _Args&&...) { + // This method body should never be run. It only exists to allow for compilation. See note in + // __insert_unique_from_orphaned_node for more information. + return pair(iterator(__node_pointer()), false); + } + template , int> = 0> - _LIBCPP_HIDE_FROM_ABI void + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insert_unique_from_orphaned_node(const_iterator __p, __get_node_value_type_t<_Tp>&& __value) { - __emplace_hint_unique(__p, const_cast(__value.first), std::move(__value.second)); +#if _LIBCPP_STD_VER >= 26 + if (std::is_constant_evaluated() && std::is_copy_constructible_v) { + // We create a sfinae wrapper method here, because if the __emplace_hint_unique method gets template instantiated + // within __insert_unique_from_orphaned_node, the code will fail to compile where the value is not + // copy_constructible for runtime execution as well; unless we use `if constexpr`. Given the copy-constructible + // code path will be a performance regression, we want to restrict it to only execute during constant evaluation + //, we need to delay the template instantiation + __emplace_hint_unique__sfinae( + integral_constant< bool, std::is_copy_constructible_v >(), + __p, + __value.first, + std::move(__value.second)); + } else +#endif + { + __emplace_hint_unique(__p, const_cast(__value.first), std::move(__value.second)); + } } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(const_iterator __p, _Tp&& __value) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __insert_unique_from_orphaned_node(const_iterator __p, _Tp&& __value) { __emplace_hint_unique(__p, std::move(__value)); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(const_iterator __p, value_type&& __value) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __insert_multi_from_orphaned_node(const_iterator __p, value_type&& __value) { __emplace_hint_multi(__p, const_cast(__value.first), std::move(__value.second)); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(const_iterator __p, _Tp&& __value) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __insert_multi_from_orphaned_node(const_iterator __p, _Tp&& __value) { __emplace_hint_multi(__p, std::move(__value)); } template - _LIBCPP_HIDE_FROM_ABI void __insert_range_multi(_InIter __first, _Sent __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insert_range_multi(_InIter __first, _Sent __last) { if (__first == __last) return; @@ -1057,23 +1143,27 @@ public: } } - _LIBCPP_HIDE_FROM_ABI pair __node_assign_unique(const value_type& __v, __node_pointer __dest); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __node_assign_unique(const value_type& __v, __node_pointer __dest); - _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd); - _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(const_iterator __p, __node_pointer __nd); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __node_insert_multi(__node_pointer __nd); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __node_insert_multi(const_iterator __p, __node_pointer __nd); template - _LIBCPP_HIDE_FROM_ABI void __insert_range_unique(_InIter __first, _Sent __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insert_range_unique(_InIter __first, _Sent __last) { if (__first == __last) return; if (__root() == nullptr) { - __insert_node_at( - __end_node(), __end_node()->__left_, static_cast<__node_base_pointer>(__construct_node(*__first).release())); + __insert_node_at(__end_node(), + __end_node()->__left_, + std::__static_fancy_pointer_cast<__node_base_pointer>(__construct_node(*__first).release())); ++__first; } - auto __max_node = static_cast<__node_pointer>(std::__tree_max(static_cast<__node_base_pointer>(__root()))); + auto __max_node = std::__static_fancy_pointer_cast<__node_pointer>( + std::__tree_max(std::__static_fancy_pointer_cast<__node_base_pointer>(__root()))); using __reference = decltype(*__first); @@ -1082,29 +1172,31 @@ public: [this, &__max_node](const key_type& __key, __reference&& __val) { if (value_comp()(__max_node->__get_value(), __key)) { // __key > __max_node __node_holder __nd = __construct_node(std::forward<__reference>(__val)); - __insert_node_at(static_cast<__end_node_pointer>(__max_node), + __insert_node_at(std::__static_fancy_pointer_cast<__end_node_pointer>(__max_node), __max_node->__right_, - static_cast<__node_base_pointer>(__nd.get())); + std::__static_fancy_pointer_cast<__node_base_pointer>(__nd.get())); __max_node = __nd.release(); } else { auto [__parent, __child] = __find_equal(__key); if (__child == nullptr) { __node_holder __nd = __construct_node(std::forward<__reference>(__val)); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd.release())); + __insert_node_at( + __parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd.release())); } } }, [this, &__max_node](__reference&& __val) { __node_holder __nd = __construct_node(std::forward<__reference>(__val)); if (value_comp()(__max_node->__get_value(), __nd->__get_value())) { // __node > __max_node - __insert_node_at(static_cast<__end_node_pointer>(__max_node), + __insert_node_at(std::__static_fancy_pointer_cast<__end_node_pointer>(__max_node), __max_node->__right_, - static_cast<__node_base_pointer>(__nd.get())); + std::__static_fancy_pointer_cast<__node_base_pointer>(__nd.get())); __max_node = __nd.release(); } else { auto [__parent, __child] = __find_equal(__nd->__get_value()); if (__child == nullptr) { - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd.release())); + __insert_node_at( + __parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd.release())); } } }, @@ -1112,219 +1204,220 @@ public: } } - _LIBCPP_HIDE_FROM_ABI iterator __remove_node_pointer(__node_pointer) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __remove_node_pointer(__node_pointer) _NOEXCEPT; #if _LIBCPP_STD_VER >= 17 template - _LIBCPP_HIDE_FROM_ABI _InsertReturnType __node_handle_insert_unique(_NodeHandle&&); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _InsertReturnType __node_handle_insert_unique(_NodeHandle&&); template - _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_unique(const_iterator, _NodeHandle&&); - template - _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_unique(__tree<_Tp, _Comp2, _Allocator>& __source); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __node_handle_insert_unique(const_iterator, _NodeHandle&&); + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __node_handle_merge_unique(_Tree& __source); template - _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_multi(_NodeHandle&&); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __node_handle_insert_multi(_NodeHandle&&); template - _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_multi(const_iterator, _NodeHandle&&); - template - _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_multi(__tree<_Tp, _Comp2, _Allocator>& __source); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __node_handle_insert_multi(const_iterator, _NodeHandle&&); + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __node_handle_merge_multi(_Tree& __source); template - _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(key_type const&); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodeHandle __node_handle_extract(key_type const&); template - _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const_iterator); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodeHandle __node_handle_extract(const_iterator); #endif - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p); - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __p); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __f, const_iterator __l); template - _LIBCPP_HIDE_FROM_ABI size_type __erase_unique(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type __erase_unique(const _Key& __k); template - _LIBCPP_HIDE_FROM_ABI size_type __erase_multi(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type __erase_multi(const _Key& __k); - _LIBCPP_HIDE_FROM_ABI void + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insert_node_at(__end_node_pointer __parent, __node_base_pointer& __child, __node_base_pointer __new_node) _NOEXCEPT; template - _LIBCPP_HIDE_FROM_ABI iterator find(const _Key& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Key& __key) { auto [__, __match] = __find_equal(__key); if (__match == nullptr) return end(); - return iterator(static_cast<__node_pointer>(__match)); + return iterator(std::__static_fancy_pointer_cast<__node_pointer>(__match)); } template - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Key& __key) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Key& __key) const { auto [__, __match] = __find_equal(__key); if (__match == nullptr) return end(); - return const_iterator(static_cast<__node_pointer>(__match)); + return const_iterator(std::__static_fancy_pointer_cast<__node_pointer>(__match)); } template - _LIBCPP_HIDE_FROM_ABI size_type __count_unique(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type __count_unique(const _Key& __k) const; template - _LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const; - - template - _LIBCPP_HIDE_FROM_ABI __end_node_pointer __lower_upper_bound_unique_impl(const _Key& __v) const { - auto __rt = __root(); - auto __result = __end_node(); - auto __comp = __lazy_synth_three_way_comparator<_Compare, _Key, value_type>(value_comp()); - while (__rt != nullptr) { - auto __comp_res = __comp(__v, __rt->__get_value()); - - if (__comp_res.__less()) { - __result = static_cast<__end_node_pointer>(__rt); - __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (__comp_res.__greater()) { - __rt = static_cast<__node_pointer>(__rt->__right_); - } else if _LIBCPP_CONSTEXPR (_LowerBound) { - return static_cast<__end_node_pointer>(__rt); - } else { - return __rt->__right_ ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) : __result; - } - } - return __result; - } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type __count_multi(const _Key& __k) const; template - _LIBCPP_HIDE_FROM_ABI iterator __lower_bound_unique(const _Key& __v) { - return iterator(__lower_upper_bound_unique_impl(__v)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Key& __v) { + return __lower_bound(__v, __root(), __end_node()); } - template - _LIBCPP_HIDE_FROM_ABI const_iterator __lower_bound_unique(const _Key& __v) const { - return const_iterator(__lower_upper_bound_unique_impl(__v)); - } - - template - _LIBCPP_HIDE_FROM_ABI iterator __upper_bound_unique(const _Key& __v) { - return iterator(__lower_upper_bound_unique_impl(__v)); - } - + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result); template - _LIBCPP_HIDE_FROM_ABI const_iterator __upper_bound_unique(const _Key& __v) const { - return iterator(__lower_upper_bound_unique_impl(__v)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Key& __v) const { + return __lower_bound(__v, __root(), __end_node()); } - -private: template - _LIBCPP_HIDE_FROM_ABI iterator - __lower_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result); - + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator + __lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const; template - _LIBCPP_HIDE_FROM_ABI const_iterator - __lower_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const; - -public: - template - _LIBCPP_HIDE_FROM_ABI iterator __lower_bound_multi(const _Key& __v) { - return __lower_bound_multi(__v, __root(), __end_node()); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Key& __v) { + return __upper_bound(__v, __root(), __end_node()); } template - _LIBCPP_HIDE_FROM_ABI const_iterator __lower_bound_multi(const _Key& __v) const { - return __lower_bound_multi(__v, __root(), __end_node()); - } - + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result); template - _LIBCPP_HIDE_FROM_ABI iterator __upper_bound_multi(const _Key& __v) { - return __upper_bound_multi(__v, __root(), __end_node()); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Key& __v) const { + return __upper_bound(__v, __root(), __end_node()); } - template - _LIBCPP_HIDE_FROM_ABI const_iterator __upper_bound_multi(const _Key& __v) const { - return __upper_bound_multi(__v, __root(), __end_node()); - } - -private: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator + __upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const; template - _LIBCPP_HIDE_FROM_ABI iterator - __upper_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result); - + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __equal_range_unique(const _Key& __k); template - _LIBCPP_HIDE_FROM_ABI const_iterator - __upper_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __equal_range_unique(const _Key& __k) const; -public: template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_unique(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __equal_range_multi(const _Key& __k); template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_unique(const _Key& __k) const; - - template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_multi(const _Key& __k); - template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_multi(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __equal_range_multi(const _Key& __k) const; using _Dp _LIBCPP_NODEBUG = __tree_node_destructor<__node_allocator>; using __node_holder _LIBCPP_NODEBUG = unique_ptr<__node, _Dp>; - _LIBCPP_HIDE_FROM_ABI __node_holder remove(const_iterator __p) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_holder remove(const_iterator __p) _NOEXCEPT; // FIXME: Make this function const qualified. Unfortunately doing so // breaks existing code which uses non-const callable comparators. template - _LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> __find_equal(const _Key& __v); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<__end_node_pointer, __node_base_pointer&> + __find_equal(const _Key& __v); template - _LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> __find_equal(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<__end_node_pointer, __node_base_pointer&> + __find_equal(const _Key& __v) const { return const_cast<__tree*>(this)->__find_equal(__v); } template - _LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<__end_node_pointer, __node_base_pointer&> __find_equal(const_iterator __hint, __node_base_pointer& __dummy, const _Key& __v); - _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __tree& __t) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __copy_assign_alloc(const __tree& __t) { __copy_assign_alloc(__t, integral_constant()); } - _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __tree& __t, true_type) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __copy_assign_alloc(const __tree& __t, true_type) { if (__node_alloc() != __t.__node_alloc()) clear(); __node_alloc() = __t.__node_alloc(); } - _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __tree&, false_type) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __copy_assign_alloc(const __tree&, false_type) {} private: - _LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_leaf_low(__end_node_pointer& __parent, const value_type& __v); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer& + __find_leaf_low(__end_node_pointer& __parent, const value_type& __v); - _LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_leaf_high(__end_node_pointer& __parent, const value_type& __v); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer& + __find_leaf_high(__end_node_pointer& __parent, const value_type& __v); - _LIBCPP_HIDE_FROM_ABI __node_base_pointer& + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer& __find_leaf(const_iterator __hint, __end_node_pointer& __parent, const value_type& __v); template - _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&&... __args); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_holder __construct_node(_Args&&... __args); // TODO: Make this _LIBCPP_HIDE_FROM_ABI - _LIBCPP_HIDDEN void destroy(__node_pointer __nd) _NOEXCEPT { (__tree_deleter(__node_alloc_))(__nd); } + _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX26 void destroy(__node_pointer __nd) _NOEXCEPT { + (__tree_deleter(__node_alloc_))(__nd); + } - _LIBCPP_HIDE_FROM_ABI void __move_assign(__tree& __t, false_type); - _LIBCPP_HIDE_FROM_ABI void __move_assign(__tree& __t, true_type) _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign(__tree& __t, false_type); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign(__tree& __t, true_type) _NOEXCEPT_( is_nothrow_move_assignable::value&& is_nothrow_move_assignable<__node_allocator>::value); - _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree& __t) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign_alloc(__tree& __t) _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<__node_allocator>::value) { __move_assign_alloc(__t, integral_constant()); } - _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree& __t, true_type) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign_alloc(__tree& __t, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) { __node_alloc() = std::move(__t.__node_alloc()); } - _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {} + + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_value__sfinae(true_type, __get_node_value_type_t& __lhs, _From&& __rhs) { + __node_allocator& __na = __node_alloc(); + __node_traits::destroy(__na, std::addressof(__lhs)); + __node_traits::construct(__na, std::addressof(__lhs), __rhs.first, __rhs.second); + } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI static void __assign_value(__get_node_value_type_t& __lhs, _From&& __rhs) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_value__sfinae(false_type, __get_node_value_type_t&, _From&&) { + // This method body should never be run. It only exists to allow for compilation. See note in __assign_value for + // more information + } + + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_value(__get_node_value_type_t& __lhs, _From&& __rhs) { using __key_type = __remove_const_t; - // This is technically UB, since the object was constructed as `const`. - // Clang doesn't optimize on this currently though. - const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first); - __lhs.second = std::forward<_From>(__rhs).second; +#if _LIBCPP_STD_VER >= 26 + + if (std::is_constant_evaluated() && std::is_copy_constructible_v) { + // we use copy, and not "move" as the constraint + // because we can NOT move from `const key_type`, which is how `value_type` is defined + // atleast for map + // typedef pair value_type; + // so we must copy it + + // const_cast is not allowed at constexpr time. + // we get around this by deleting __lhs and creating a new node in-place + // to avoid const_cast __lhs.first + + // We create a sfinae wrapper method here, because if the body of the true_type overload for + // __assign_value__sfinae() gets template instantiated within __assign_value, the code will fail to compile where + // the value is not copy_constructible for runtime execution as well; unless we use `if constexpr`. Given the + // copy-constructible code path will be a performance regression, we want to restrict it to only execute during + // constant evaluation + //, we need to delay the template instantiation + + __assign_value__sfinae(std::integral_constant>(), + std::forward(__lhs), + std::forward(__rhs)); + + } else +#endif + { + // This is technically UB, since the object was constructed as `const`. + // Clang doesn't optimize on this currently though. + const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first); + __lhs.second = std::forward<_From>(__rhs).second; + } } template , int> = 0> @@ -1333,22 +1426,22 @@ private: } struct _DetachedTreeCache { - _LIBCPP_HIDE_FROM_ABI explicit _DetachedTreeCache(__tree* __t) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit _DetachedTreeCache(__tree* __t) _NOEXCEPT : __t_(__t), __cache_root_(__detach_from_tree(__t)) { __advance(); } - _LIBCPP_HIDE_FROM_ABI __node_pointer __get() const _NOEXCEPT { return __cache_elem_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __get() const _NOEXCEPT { return __cache_elem_; } - _LIBCPP_HIDE_FROM_ABI void __advance() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __advance() _NOEXCEPT { __cache_elem_ = __cache_root_; if (__cache_root_) { __cache_root_ = __detach_next(__cache_root_); } } - _LIBCPP_HIDE_FROM_ABI ~_DetachedTreeCache() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~_DetachedTreeCache() { __t_->destroy(__cache_elem_); if (__cache_root_) { while (__cache_root_->__parent_ != nullptr) @@ -1361,8 +1454,8 @@ private: _DetachedTreeCache& operator=(_DetachedTreeCache const&) = delete; private: - _LIBCPP_HIDE_FROM_ABI static __node_pointer __detach_from_tree(__tree* __t) _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI static __node_pointer __detach_next(__node_pointer) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static __node_pointer __detach_from_tree(__tree* __t) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static __node_pointer __detach_next(__node_pointer) _NOEXCEPT; __tree* __t_; __node_pointer __cache_root_; @@ -1375,24 +1468,23 @@ private: public: using pointer = __node_pointer; - _LIBCPP_HIDE_FROM_ABI __tree_deleter(__node_allocator& __alloc) : __alloc_(__alloc) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_deleter(__node_allocator& __alloc) : __alloc_(__alloc) {} #ifdef _LIBCPP_COMPILER_CLANG_BASED // FIXME: GCC complains about not being able to always_inline a recursive function _LIBCPP_HIDE_FROM_ABI #endif - void - operator()(__node_pointer __ptr) { + _LIBCPP_CONSTEXPR_SINCE_CXX26 void operator()(__node_pointer __ptr) { if (!__ptr) return; - (*this)(static_cast<__node_pointer>(__ptr->__left_)); + (*this)(std::__static_fancy_pointer_cast<__node_pointer>(__ptr->__left_)); auto __right = __ptr->__right_; __node_traits::destroy(__alloc_, std::addressof(__ptr->__get_value())); __node_traits::deallocate(__alloc_, __ptr, 1); - (*this)(static_cast<__node_pointer>(__right)); + (*this)(std::__static_fancy_pointer_cast<__node_pointer>(__right)); } }; @@ -1403,26 +1495,25 @@ private: #ifdef _LIBCPP_COMPILER_CLANG_BASED // FIXME: GCC complains about not being able to always_inline a recursive function _LIBCPP_HIDE_FROM_ABI #endif - __node_pointer - __copy_construct_tree(__node_pointer __src) { + _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __copy_construct_tree(__node_pointer __src) { if (!__src) return nullptr; __node_holder __new_node = __construct_node(__src->__get_value()); unique_ptr<__node, __tree_deleter> __left( - __copy_construct_tree(static_cast<__node_pointer>(__src->__left_)), __node_alloc_); - __node_pointer __right = __copy_construct_tree(static_cast<__node_pointer>(__src->__right_)); + __copy_construct_tree(std::__static_fancy_pointer_cast<__node_pointer>(__src->__left_)), __node_alloc_); + __node_pointer __right = __copy_construct_tree(std::__static_fancy_pointer_cast<__node_pointer>(__src->__right_)); __node_pointer __new_node_ptr = __new_node.release(); __new_node_ptr->__is_black_ = __src->__is_black_; - __new_node_ptr->__left_ = static_cast<__node_base_pointer>(__left.release()); - __new_node_ptr->__right_ = static_cast<__node_base_pointer>(__right); + __new_node_ptr->__left_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__left.release()); + __new_node_ptr->__right_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__right); if (__new_node_ptr->__left_) - __new_node_ptr->__left_->__parent_ = static_cast<__end_node_pointer>(__new_node_ptr); + __new_node_ptr->__left_->__parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__new_node_ptr); if (__new_node_ptr->__right_) - __new_node_ptr->__right_->__parent_ = static_cast<__end_node_pointer>(__new_node_ptr); + __new_node_ptr->__right_->__parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__new_node_ptr); return __new_node_ptr; } @@ -1432,8 +1523,7 @@ private: #ifdef _LIBCPP_COMPILER_CLANG_BASED // FIXME: GCC complains about not being able to always_inline a recursive function _LIBCPP_HIDE_FROM_ABI #endif - __node_pointer - __copy_assign_tree(__node_pointer __dest, __node_pointer __src) { + _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __copy_assign_tree(__node_pointer __dest, __node_pointer __src) { if (!__src) { destroy(__dest); return nullptr; @@ -1444,24 +1534,26 @@ private: // If we already have a left node in the destination tree, reuse it and copy-assign recursively if (__dest->__left_) { - __dest->__left_ = static_cast<__node_base_pointer>(__copy_assign_tree( - static_cast<__node_pointer>(__dest->__left_), static_cast<__node_pointer>(__src->__left_))); + __dest->__left_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_assign_tree( + std::__static_fancy_pointer_cast<__node_pointer>(__dest->__left_), + std::__static_fancy_pointer_cast<__node_pointer>(__src->__left_))); // Otherwise, we must create new nodes; copy-construct from here on } else if (__src->__left_) { - auto __new_left = __copy_construct_tree(static_cast<__node_pointer>(__src->__left_)); - __dest->__left_ = static_cast<__node_base_pointer>(__new_left); - __new_left->__parent_ = static_cast<__end_node_pointer>(__dest); + auto __new_left = __copy_construct_tree(std::__static_fancy_pointer_cast<__node_pointer>(__src->__left_)); + __dest->__left_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__new_left); + __new_left->__parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__dest); } // Identical to the left case above, just for the right nodes if (__dest->__right_) { - __dest->__right_ = static_cast<__node_base_pointer>(__copy_assign_tree( - static_cast<__node_pointer>(__dest->__right_), static_cast<__node_pointer>(__src->__right_))); + __dest->__right_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_assign_tree( + std::__static_fancy_pointer_cast<__node_pointer>(__dest->__right_), + std::__static_fancy_pointer_cast<__node_pointer>(__src->__right_))); } else if (__src->__right_) { - auto __new_right = __copy_construct_tree(static_cast<__node_pointer>(__src->__right_)); - __dest->__right_ = static_cast<__node_base_pointer>(__new_right); - __new_right->__parent_ = static_cast<__end_node_pointer>(__dest); + auto __new_right = __copy_construct_tree(std::__static_fancy_pointer_cast<__node_pointer>(__src->__right_)); + __dest->__right_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__new_right); + __new_right->__parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__dest); } return __dest; @@ -1470,16 +1562,16 @@ private: // Precondition: __size_ != 0 template -typename __tree<_Tp, _Compare, _Allocator>::__node_pointer +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_pointer __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_from_tree(__tree* __t) _NOEXCEPT { - __node_pointer __cache = static_cast<__node_pointer>(__t->__begin_node_); + __node_pointer __cache = std::__static_fancy_pointer_cast<__node_pointer>(__t->__begin_node_); __t->__begin_node_ = __t->__end_node(); __t->__end_node()->__left_->__parent_ = nullptr; __t->__end_node()->__left_ = nullptr; __t->__size_ = 0; // __cache->__left_ == nullptr if (__cache->__right_ != nullptr) - __cache = static_cast<__node_pointer>(__cache->__right_); + __cache = std::__static_fancy_pointer_cast<__node_pointer>(__cache->__right_); // __cache->__left_ == nullptr // __cache->__right_ == nullptr return __cache; @@ -1490,27 +1582,28 @@ __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_from_tree(__tree // __cache->right_ == nullptr // This is no longer a red-black tree template -typename __tree<_Tp, _Compare, _Allocator>::__node_pointer +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_pointer __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_next(__node_pointer __cache) _NOEXCEPT { if (__cache->__parent_ == nullptr) return nullptr; - if (std::__tree_is_left_child(static_cast<__node_base_pointer>(__cache))) { + if (std::__tree_is_left_child(std::__static_fancy_pointer_cast<__node_base_pointer>(__cache))) { __cache->__parent_->__left_ = nullptr; - __cache = static_cast<__node_pointer>(__cache->__parent_); + __cache = std::__static_fancy_pointer_cast<__node_pointer>(__cache->__parent_); if (__cache->__right_ == nullptr) return __cache; return static_cast<__node_pointer>(std::__tree_leaf(__cache->__right_)); } // __cache is right child __cache->__parent_unsafe()->__right_ = nullptr; - __cache = static_cast<__node_pointer>(__cache->__parent_); + __cache = std::__static_fancy_pointer_cast<__node_pointer>(__cache->__parent_); if (__cache->__left_ == nullptr) return __cache; return static_cast<__node_pointer>(std::__tree_leaf(__cache->__left_)); } template -__tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>& +__tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t) { if (this == std::addressof(__t)) return *this; @@ -1518,14 +1611,15 @@ __tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=( __copy_assign_alloc(__t); if (__size_ != 0) { - *__root_ptr() = static_cast<__node_base_pointer>(__copy_assign_tree(__root(), __t.__root())); + *__root_ptr() = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_assign_tree(__root(), __t.__root())); } else { - *__root_ptr() = static_cast<__node_base_pointer>(__copy_construct_tree(__t.__root())); + *__root_ptr() = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_construct_tree(__t.__root())); if (__root()) __root()->__parent_ = __end_node(); } - __begin_node_ = - __end_node()->__left_ ? static_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_)) : __end_node(); + __begin_node_ = __end_node()->__left_ + ? std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_)) + : __end_node(); __size_ = __t.size(); return *this; @@ -1533,7 +1627,8 @@ __tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=( template template -void __tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first, _ForwardIterator __last) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 void +__tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first, _ForwardIterator __last) { using _ITraits = iterator_traits<_ForwardIterator>; using _ItValueType = typename _ITraits::value_type; static_assert( @@ -1553,7 +1648,8 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first template template -void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 void +__tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last) { using _ITraits = iterator_traits<_InputIterator>; using _ItValueType = typename _ITraits::value_type; static_assert( @@ -1572,7 +1668,7 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _ } template -__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) : __begin_node_(__end_node()), __node_alloc_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())), __size_(0), @@ -1580,14 +1676,14 @@ __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) if (__t.size() == 0) return; - *__root_ptr() = static_cast<__node_base_pointer>(__copy_construct_tree(__t.__root())); + *__root_ptr() = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_construct_tree(__t.__root())); __root()->__parent_ = __end_node(); - __begin_node_ = static_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_)); + __begin_node_ = std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_)); __size_ = __t.size(); } template -__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_( +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_( is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible::value) : __begin_node_(std::move(__t.__begin_node_)), __end_node_(std::move(__t.__end_node_)), @@ -1605,7 +1701,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_( } template -__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a) +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a) : __node_alloc_(__node_allocator(__a)), __size_(0), __value_comp_(std::move(__t.value_comp())) { if (__a == __t.__alloc()) { if (__t.__size_ == 0) @@ -1625,7 +1721,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __ } template -void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value&& is_nothrow_move_assignable<__node_allocator>::value) { destroy(static_cast<__node_pointer>(__end_node()->__left_)); __begin_node_ = __t.__begin_node_; @@ -1644,7 +1740,7 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) } template -void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { if (__node_alloc() == __t.__node_alloc()) __move_assign(__t, true_type()); else { @@ -1665,7 +1761,7 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { } template -void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) #if _LIBCPP_STD_VER <= 11 _NOEXCEPT_(__is_nothrow_swappable_v && (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>)) @@ -1690,7 +1786,7 @@ void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) } template -void __tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT { +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT { destroy(__root()); __size_ = 0; __begin_node_ = __end_node(); @@ -1701,7 +1797,7 @@ void __tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT { // Set __parent to parent of null leaf // Return reference to null leaf template -typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__end_node_pointer& __parent, const value_type& __v) { __node_pointer __nd = __root(); if (__nd != nullptr) { @@ -1731,7 +1827,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__end_node_pointer& __parent, // Set __parent to parent of null leaf // Return reference to null leaf template -typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__end_node_pointer& __parent, const value_type& __v) { __node_pointer __nd = __root(); if (__nd != nullptr) { @@ -1747,7 +1843,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__end_node_pointer& __parent if (__nd->__right_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__right_); else { - __parent = static_cast<__end_node_pointer>(__nd); + __parent = std::__static_fancy_pointer_cast<__end_node_pointer>(__nd); return __nd->__right_; } } @@ -1764,7 +1860,8 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__end_node_pointer& __parent // Set __parent to parent of null leaf // Return reference to null leaf template -typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_leaf( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_leaf( const_iterator __hint, __end_node_pointer& __parent, const value_type& __v) { if (__hint == end() || !value_comp()(*__hint, __v)) // check before { @@ -1777,7 +1874,7 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co return __parent->__left_; } else { __parent = static_cast<__end_node_pointer>(__prior.__ptr_); - return static_cast<__node_base_pointer>(__prior.__ptr_)->__right_; + return std::__static_fancy_pointer_cast<__node_base_pointer>(__prior.__ptr_)->__right_; } } // __v < *prev(__hint) @@ -1792,8 +1889,9 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co // If __v doesn't exist, return the parent of the null leaf and a reference to the pointer to the null leaf. template template -_LIBCPP_HIDE_FROM_ABI pair::__end_node_pointer, - typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::__end_node_pointer, + typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> __tree<_Tp, _Compare, _Allocator>::__find_equal(const _Key& __v) { using _Pair = pair<__end_node_pointer, __node_base_pointer&>; @@ -1805,26 +1903,25 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const _Key& __v) { } __node_base_pointer* __node_ptr = __root_ptr(); - auto&& __transparent = std::__as_transparent(value_comp()); - auto __comp = __lazy_synth_three_way_comparator<__make_transparent_t<_Compare>, _Key, value_type>(__transparent); + auto __comp = __lazy_synth_three_way_comparator<_Compare, _Key, value_type>(value_comp()); while (true) { auto __comp_res = __comp(__v, __nd->__get_value()); if (__comp_res.__less()) { if (__nd->__left_ == nullptr) - return _Pair(static_cast<__end_node_pointer>(__nd), __nd->__left_); + return _Pair(std::__static_fancy_pointer_cast<__end_node_pointer>(__nd), __nd->__left_); __node_ptr = std::addressof(__nd->__left_); - __nd = static_cast<__node_pointer>(__nd->__left_); + __nd = std::__static_fancy_pointer_cast<__node_pointer>(__nd->__left_); } else if (__comp_res.__greater()) { if (__nd->__right_ == nullptr) - return _Pair(static_cast<__end_node_pointer>(__nd), __nd->__right_); + return _Pair(std::__static_fancy_pointer_cast<__end_node_pointer>(__nd), __nd->__right_); __node_ptr = std::addressof(__nd->__right_); - __nd = static_cast<__node_pointer>(__nd->__right_); + __nd = std::__static_fancy_pointer_cast<__node_pointer>(__nd->__right_); } else { - return _Pair(static_cast<__end_node_pointer>(__nd), *__node_ptr); + return _Pair(std::__static_fancy_pointer_cast<__end_node_pointer>(__nd), *__node_ptr); } } } @@ -1837,8 +1934,9 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const _Key& __v) { // If __v doesn't exist, return the parent of the null leaf and a reference to the pointer to the null leaf. template template -_LIBCPP_HIDE_FROM_ABI pair::__end_node_pointer, - typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::__end_node_pointer, + typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_base_pointer& __dummy, const _Key& __v) { using _Pair = pair<__end_node_pointer, __node_base_pointer&>; @@ -1849,7 +1947,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_ba // *prev(__hint) < __v < *__hint if (__hint.__ptr_->__left_ == nullptr) return _Pair(__hint.__ptr_, __hint.__ptr_->__left_); - return _Pair(__prior.__ptr_, static_cast<__node_pointer>(__prior.__ptr_)->__right_); + return _Pair(__prior.__ptr_, std::__static_fancy_pointer_cast<__node_pointer>(__prior.__ptr_)->__right_); } // __v <= *prev(__hint) return __find_equal(__v); @@ -1874,7 +1972,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_ba } template -void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( __end_node_pointer __parent, __node_base_pointer& __child, __node_base_pointer __new_node) _NOEXCEPT { __new_node->__left_ = nullptr; __new_node->__right_ = nullptr; @@ -1882,14 +1980,14 @@ void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( // __new_node->__is_black_ is initialized in __tree_balance_after_insert __child = __new_node; if (__begin_node_->__left_ != nullptr) - __begin_node_ = static_cast<__end_node_pointer>(__begin_node_->__left_); + __begin_node_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__begin_node_->__left_); std::__tree_balance_after_insert(__end_node()->__left_, __child); ++__size_; } template template -typename __tree<_Tp, _Compare, _Allocator>::__node_holder +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); @@ -1900,7 +1998,7 @@ __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator +typename __tree<_Tp, _Compare, _Allocator>::iterator _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; @@ -1911,24 +2009,24 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator +typename __tree<_Tp, _Compare, _Allocator>::iterator _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, _Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__get_value()); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); return iterator(static_cast<__node_pointer>(__h.release())); } template -pair::iterator, bool> +pair::iterator, bool> _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, __node_pointer __nd) { auto [__parent, __child] = __find_equal(__v); __node_pointer __r = static_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __assign_value(__nd->__get_value(), __v); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd)); __r = __nd; __inserted = true; } @@ -1936,16 +2034,16 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, _ } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd) { __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__get_value()); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd)); return iterator(__nd); } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, __node_pointer __nd) { __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__get_value()); @@ -1954,21 +2052,21 @@ __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, __nod } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr) _NOEXCEPT { iterator __r(__ptr); ++__r; if (__begin_node_ == __ptr) __begin_node_ = __r.__ptr_; --__size_; - std::__tree_remove(__end_node()->__left_, static_cast<__node_base_pointer>(__ptr)); + std::__tree_remove(__end_node()->__left_, std::__static_fancy_pointer_cast<__node_base_pointer>(__ptr)); return __r; } #if _LIBCPP_STD_VER >= 17 template template -_LIBCPP_HIDE_FROM_ABI _InsertReturnType +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _InsertReturnType __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __nh) { if (__nh.empty()) return _InsertReturnType{end(), false, _NodeHandle()}; @@ -1985,7 +2083,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __n template template -_LIBCPP_HIDE_FROM_ABI typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __hint, _NodeHandle&& __nh) { if (__nh.empty()) return end(); @@ -2004,7 +2102,8 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __ template template -_LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodeHandle +__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key) { iterator __it = find(__key); if (__it == end()) return _NodeHandle(); @@ -2013,17 +2112,20 @@ _LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_hand template template -_LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const_iterator __p) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodeHandle +__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const_iterator __p) { __node_pointer __np = __p.__get_np(); __remove_node_pointer(__np); return _NodeHandle(__np, __alloc()); } template -template -_LIBCPP_HIDE_FROM_ABI void -__tree<_Tp, _Compare, _Allocator>::__node_handle_merge_unique(__tree<_Tp, _Comp2, _Allocator>& __source) { - for (iterator __i = __source.begin(); __i != __source.end();) { +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void +__tree<_Tp, _Compare, _Allocator>::__node_handle_merge_unique(_Tree& __source) { + static_assert(is_same::value, ""); + + for (typename _Tree::iterator __i = __source.begin(); __i != __source.end();) { __node_pointer __src_ptr = __i.__get_np(); auto [__parent, __child] = __find_equal(__src_ptr->__get_value()); ++__i; @@ -2036,7 +2138,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_merge_unique(__tree<_Tp, _Comp2 template template -_LIBCPP_HIDE_FROM_ABI typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(_NodeHandle&& __nh) { if (__nh.empty()) return end(); @@ -2050,7 +2152,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(_NodeHandle&& __nh template template -_LIBCPP_HIDE_FROM_ABI typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh) { if (__nh.empty()) return end(); @@ -2064,10 +2166,12 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(const_iterator __h } template -template -_LIBCPP_HIDE_FROM_ABI void -__tree<_Tp, _Compare, _Allocator>::__node_handle_merge_multi(__tree<_Tp, _Comp2, _Allocator>& __source) { - for (iterator __i = __source.begin(); __i != __source.end();) { +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void +__tree<_Tp, _Compare, _Allocator>::__node_handle_merge_multi(_Tree& __source) { + static_assert(is_same::value, ""); + + for (typename _Tree::iterator __i = __source.begin(); __i != __source.end();) { __node_pointer __src_ptr = __i.__get_np(); __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf_high(__parent, __src_ptr->__get_value()); @@ -2080,7 +2184,8 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_merge_multi(__tree<_Tp, _Comp2, #endif // _LIBCPP_STD_VER >= 17 template -typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 + typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p) { __node_pointer __np = __p.__get_np(); iterator __r = __remove_node_pointer(__np); __node_allocator& __na = __node_alloc(); @@ -2090,7 +2195,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allo } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l) { while (__f != __l) __f = erase(__f); @@ -2099,7 +2204,7 @@ __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l) template template -typename __tree<_Tp, _Compare, _Allocator>::size_type +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k) { iterator __i = find(__k); if (__i == end()) @@ -2110,7 +2215,7 @@ __tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k) { template template -typename __tree<_Tp, _Compare, _Allocator>::size_type +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k) { pair __p = __equal_range_multi(__k); size_type __r = 0; @@ -2121,16 +2226,16 @@ __tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k) { template template -typename __tree<_Tp, _Compare, _Allocator>::size_type +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const { __node_pointer __rt = __root(); auto __comp = __lazy_synth_three_way_comparator(value_comp()); while (__rt != nullptr) { auto __comp_res = __comp(__k, __rt->__get_value()); if (__comp_res.__less()) { - __rt = static_cast<__node_pointer>(__rt->__left_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return 1; } @@ -2139,7 +2244,7 @@ __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const { template template -typename __tree<_Tp, _Compare, _Allocator>::size_type +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const { __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); @@ -2153,72 +2258,75 @@ __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const { __rt = static_cast<__node_pointer>(__rt->__right_); else return std::distance( - __lower_bound_multi(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)), - __upper_bound_multi(__k, static_cast<__node_pointer>(__rt->__right_), __result)); + __lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)), + __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result)); } return 0; } template template -typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__lower_bound_multi( - const _Key& __v, __node_pointer __root, __end_node_pointer __result) { +typename __tree<_Tp, _Compare, _Allocator>::iterator _LIBCPP_CONSTEXPR_SINCE_CXX26 +__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) { while (__root != nullptr) { if (!value_comp()(__root->__get_value(), __v)) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return iterator(__result); } template template -typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::__lower_bound_multi( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::const_iterator +__tree<_Tp, _Compare, _Allocator>::__lower_bound( const _Key& __v, __node_pointer __root, __end_node_pointer __result) const { while (__root != nullptr) { if (!value_comp()(__root->__get_value(), __v)) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return const_iterator(__result); } template template -typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound_multi( - const _Key& __v, __node_pointer __root, __end_node_pointer __result) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) { while (__root != nullptr) { if (value_comp()(__v, __root->__get_value())) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return iterator(__result); } template template -typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound_multi( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::const_iterator +__tree<_Tp, _Compare, _Allocator>::__upper_bound( const _Key& __v, __node_pointer __root, __end_node_pointer __result) const { while (__root != nullptr) { if (value_comp()(__v, __root->__get_value())) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return const_iterator(__result); } template template -pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> -__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 + pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> + __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { using _Pp = pair; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); @@ -2226,22 +2334,23 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { while (__rt != nullptr) { auto __comp_res = __comp(__k, __rt->__get_value()); if (__comp_res.__less()) { - __result = static_cast<__end_node_pointer>(__rt); - __rt = static_cast<__node_pointer>(__rt->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__rt); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return _Pp(iterator(__rt), - iterator(__rt->__right_ != nullptr ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) - : __result)); + iterator(__rt->__right_ != nullptr + ? std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) + : __result)); } return _Pp(iterator(__result), iterator(__result)); } template template -pair::const_iterator, - typename __tree<_Tp, _Compare, _Allocator>::const_iterator> +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::const_iterator, + typename __tree<_Tp, _Compare, _Allocator>::const_iterator> __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const { using _Pp = pair; __end_node_pointer __result = __end_node(); @@ -2250,23 +2359,25 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const { while (__rt != nullptr) { auto __comp_res = __comp(__k, __rt->__get_value()); if (__comp_res.__less()) { - __result = static_cast<__end_node_pointer>(__rt); - __rt = static_cast<__node_pointer>(__rt->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__rt); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return _Pp( const_iterator(__rt), - const_iterator( - __rt->__right_ != nullptr ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) : __result)); + const_iterator(__rt->__right_ != nullptr + ? std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) + : __result)); } return _Pp(const_iterator(__result), const_iterator(__result)); } template template -pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> -__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 + pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> + __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { using _Pp = pair; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); @@ -2279,17 +2390,16 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { } else if (__comp_res.__greater()) __rt = static_cast<__node_pointer>(__rt->__right_); else - return _Pp( - __lower_bound_multi(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)), - __upper_bound_multi(__k, static_cast<__node_pointer>(__rt->__right_), __result)); + return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)), + __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result)); } return _Pp(iterator(__result), iterator(__result)); } template template -pair::const_iterator, - typename __tree<_Tp, _Compare, _Allocator>::const_iterator> +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::const_iterator, + typename __tree<_Tp, _Compare, _Allocator>::const_iterator> __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const { using _Pp = pair; __end_node_pointer __result = __end_node(); @@ -2303,15 +2413,14 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const { } else if (__comp_res.__greater()) __rt = static_cast<__node_pointer>(__rt->__right_); else - return _Pp( - __lower_bound_multi(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)), - __upper_bound_multi(__k, static_cast<__node_pointer>(__rt->__right_), __result)); + return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)), + __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result)); } return _Pp(const_iterator(__result), const_iterator(__result)); } template -typename __tree<_Tp, _Compare, _Allocator>::__node_holder +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT { __node_pointer __np = __p.__get_np(); if (__begin_node_ == __p.__ptr_) { @@ -2326,7 +2435,8 @@ __tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT { } template -inline _LIBCPP_HIDE_FROM_ABI void swap(__tree<_Tp, _Compare, _Allocator>& __x, __tree<_Tp, _Compare, _Allocator>& __y) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void +swap(__tree<_Tp, _Compare, _Allocator>& __x, __tree<_Tp, _Compare, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } diff --git a/libcxx/include/__utility/lazy_synth_three_way_comparator.h b/libcxx/include/__utility/lazy_synth_three_way_comparator.h index 8c78742ccb4e3..3b2c7aa4de83f 100644 --- a/libcxx/include/__utility/lazy_synth_three_way_comparator.h +++ b/libcxx/include/__utility/lazy_synth_three_way_comparator.h @@ -34,14 +34,14 @@ struct __lazy_compare_result { const _LHS& __lhs_; const _RHS& __rhs_; - _LIBCPP_HIDE_FROM_ABI - __lazy_compare_result(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp, - _LIBCPP_CTOR_LIFETIMEBOUND const _LHS& __lhs, - _LIBCPP_CTOR_LIFETIMEBOUND const _RHS& __rhs) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __lazy_compare_result( + _LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp, + _LIBCPP_CTOR_LIFETIMEBOUND const _LHS& __lhs, + _LIBCPP_CTOR_LIFETIMEBOUND const _RHS& __rhs) : __comp_(__comp), __lhs_(__lhs), __rhs_(__rhs) {} - _LIBCPP_HIDE_FROM_ABI bool __less() const { return __comp_(__lhs_, __rhs_); } - _LIBCPP_HIDE_FROM_ABI bool __greater() const { return __comp_(__rhs_, __lhs_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __less() const { return __comp_(__lhs_, __rhs_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __greater() const { return __comp_(__rhs_, __lhs_); } }; // This class provides three way comparison between _LHS and _RHS as efficiently as possible. This can be specialized if @@ -51,10 +51,11 @@ template struct __lazy_synth_three_way_comparator { const _Comparator& __comp_; - _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp) : __comp_(__comp) {} - _LIBCPP_HIDE_FROM_ABI __lazy_compare_result<_Comparator, _LHS, _RHS> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __lazy_compare_result<_Comparator, _LHS, _RHS> operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) const { return __lazy_compare_result<_Comparator, _LHS, _RHS>(__comp_, __lhs, __rhs); } @@ -63,10 +64,10 @@ struct __lazy_synth_three_way_comparator { struct __eager_compare_result { int __res_; - _LIBCPP_HIDE_FROM_ABI explicit __eager_compare_result(int __res) : __res_(__res) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __eager_compare_result(int __res) : __res_(__res) {} - _LIBCPP_HIDE_FROM_ABI bool __less() const { return __res_ < 0; } - _LIBCPP_HIDE_FROM_ABI bool __greater() const { return __res_ > 0; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __less() const { return __res_ < 0; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __greater() const { return __res_ > 0; } }; template @@ -77,10 +78,11 @@ struct __lazy_synth_three_way_comparator<_Comparator, __has_default_three_way_comparator<_LHS, _RHS> >::value> > { // This lifetimebound annotation is technically incorrect, but other specializations actually capture the lifetime of // the comparator. - _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} // Same comment as above. - _LIBCPP_HIDE_FROM_ABI static __eager_compare_result + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static __eager_compare_result operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) { return __eager_compare_result(__default_three_way_comparator<_LHS, _RHS>()(__lhs, __rhs)); } @@ -94,10 +96,11 @@ struct __lazy_synth_three_way_comparator<_Comparator, __has_default_three_way_comparator<_LHS, _RHS> >::value> > { // This lifetimebound annotation is technically incorrect, but other specializations actually capture the lifetime of // the comparator. - _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} // Same comment as above. - _LIBCPP_HIDE_FROM_ABI static __eager_compare_result + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static __eager_compare_result operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) { return __eager_compare_result(-__default_three_way_comparator<_LHS, _RHS>()(__lhs, __rhs)); } diff --git a/libcxx/include/map b/libcxx/include/map index 3ff849afcde09..b2c71d265c218 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -61,173 +61,175 @@ public: noexcept( is_nothrow_default_constructible::value && is_nothrow_default_constructible::value && - is_nothrow_copy_constructible::value); - explicit map(const key_compare& comp); - map(const key_compare& comp, const allocator_type& a); + is_nothrow_copy_constructible::value); // constexpr since C++26 + explicit map(const key_compare& comp); // constexpr since C++26 + map(const key_compare& comp, const allocator_type& a); // constexpr since C++26 template map(InputIterator first, InputIterator last, - const key_compare& comp = key_compare()); + const key_compare& comp = key_compare()); // constexpr since C++26 template map(InputIterator first, InputIterator last, - const key_compare& comp, const allocator_type& a); + const key_compare& comp, const allocator_type& a); // constexpr since C++26 template R> - map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 - map(const map& m); + map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 // constexpr +since C++26 + + map(const map& m); // constexpr since C++26 map(map&& m) noexcept( is_nothrow_move_constructible::value && - is_nothrow_move_constructible::value); - explicit map(const allocator_type& a); - map(const map& m, const allocator_type& a); - map(map&& m, const allocator_type& a); - map(initializer_list il, const key_compare& comp = key_compare()); - map(initializer_list il, const key_compare& comp, const allocator_type& a); + is_nothrow_move_constructible::value); // constexpr since C++26 + explicit map(const allocator_type& a); // constexpr since C++26 + map(const map& m, const allocator_type& a); // constexpr since C++26 + map(map&& m, const allocator_type& a); // constexpr since C++26 + map(initializer_list il, const key_compare& comp = key_compare()); // constexpr since C++26 + map(initializer_list il, const key_compare& comp, const allocator_type& a); // constexpr since C++26 template map(InputIterator first, InputIterator last, const allocator_type& a) - : map(first, last, Compare(), a) {} // C++14 + : map(first, last, Compare(), a) {} // C++14 // constexpr since C++26 template R> map(from_range_t, R&& rg, const Allocator& a)) - : map(from_range, std::forward(rg), Compare(), a) { } // C++23 + : map(from_range, std::forward(rg), Compare(), a) { } // C++23 // constexpr since C++26 map(initializer_list il, const allocator_type& a) - : map(il, Compare(), a) {} // C++14 - ~map(); + : map(il, Compare(), a) {} // C++14 // constexpr since C++26 + ~map(); // constexpr since C++26 - map& operator=(const map& m); + map& operator=(const map& m); // constexpr since C++26 map& operator=(map&& m) noexcept( allocator_type::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value && - is_nothrow_move_assignable::value); - map& operator=(initializer_list il); + is_nothrow_move_assignable::value); // constexpr since C++26 + map& operator=(initializer_list il); // constexpr since C++26 // iterators: - iterator begin() noexcept; - const_iterator begin() const noexcept; - iterator end() noexcept; - const_iterator end() const noexcept; + iterator begin() noexcept; // constexpr since C++26 + const_iterator begin() const noexcept; // constexpr since C++26 + iterator end() noexcept; // constexpr since C++26 + const_iterator end() const noexcept; // constexpr since C++26 - reverse_iterator rbegin() noexcept; - const_reverse_iterator rbegin() const noexcept; - reverse_iterator rend() noexcept; - const_reverse_iterator rend() const noexcept; + reverse_iterator rbegin() noexcept; // constexpr since C++26 + const_reverse_iterator rbegin() const noexcept; // constexpr since C++26 + reverse_iterator rend() noexcept; // constexpr since C++26 + const_reverse_iterator rend() const noexcept; // constexpr since C++26 - const_iterator cbegin() const noexcept; - const_iterator cend() const noexcept; - const_reverse_iterator crbegin() const noexcept; - const_reverse_iterator crend() const noexcept; + const_iterator cbegin() const noexcept; // constexpr since C++26 + const_iterator cend() const noexcept; // constexpr since C++26 + const_reverse_iterator crbegin() const noexcept; // constexpr since C++26 + const_reverse_iterator crend() const noexcept; // constexpr since C++26 // capacity: - bool empty() const noexcept; - size_type size() const noexcept; - size_type max_size() const noexcept; + bool empty() const noexcept; // constexpr since C++26 + size_type size() const noexcept; // constexpr since C++26 + size_type max_size() const noexcept; // constexpr since C++26 // element access: - mapped_type& operator[](const key_type& k); - mapped_type& operator[](key_type&& k); + mapped_type& operator[](const key_type& k); // constexpr since C++26 + mapped_type& operator[](key_type&& k); // constexpr since C++26 - mapped_type& at(const key_type& k); - const mapped_type& at(const key_type& k) const; + mapped_type& at(const key_type& k); // constexpr since C++26 + const mapped_type& at(const key_type& k) const; // constexpr since C++26 // modifiers: template - pair emplace(Args&&... args); + pair emplace(Args&&... args); // constexpr since C++26 template - iterator emplace_hint(const_iterator position, Args&&... args); - pair insert(const value_type& v); - pair insert( value_type&& v); // C++17 + iterator emplace_hint(const_iterator position, Args&&... args); // constexpr since C++26 + pair insert(const value_type& v); // constexpr since C++26 + pair insert( value_type&& v); // C++17 // constexpr since C++26 template - pair insert(P&& p); - iterator insert(const_iterator position, const value_type& v); - iterator insert(const_iterator position, value_type&& v); // C++17 + pair insert(P&& p); // constexpr since C++26 + iterator insert(const_iterator position, const value_type& v); // constexpr since C++26 + iterator insert(const_iterator position, value_type&& v); // C++17 // constexpr since C++26 template - iterator insert(const_iterator position, P&& p); + iterator insert(const_iterator position, P&& p); // constexpr since C++26 template - void insert(InputIterator first, InputIterator last); + void insert(InputIterator first, InputIterator last); // constexpr since C++26 template R> - void insert_range(R&& rg); // C++23 - void insert(initializer_list il); + void insert_range(R&& rg); // C++23 // constexpr since C++26 + void insert(initializer_list il); // constexpr since C++26 - node_type extract(const_iterator position); // C++17 - node_type extract(const key_type& x); // C++17 - insert_return_type insert(node_type&& nh); // C++17 - iterator insert(const_iterator hint, node_type&& nh); // C++17 + node_type extract(const_iterator position); // C++17 // constexpr since C++26 + node_type extract(const key_type& x); // C++17 // constexpr since C++26 + insert_return_type insert(node_type&& nh); // C++17 // constexpr since C++26 + iterator insert(const_iterator hint, node_type&& nh); // C++17 // constexpr since C++26 template - pair try_emplace(const key_type& k, Args&&... args); // C++17 + pair try_emplace(const key_type& k, Args&&... args); // C++17 // constexpr since C++26 template - pair try_emplace(key_type&& k, Args&&... args); // C++17 + pair try_emplace(key_type&& k, Args&&... args); // C++17 // constexpr since C++26 template - iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17 + iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17 // constexpr since C++26 template - iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); // C++17 + iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); // C++17 // constexpr since C++26 template - pair insert_or_assign(const key_type& k, M&& obj); // C++17 + pair insert_or_assign(const key_type& k, M&& obj); // C++17 // constexpr since C++26 template - pair insert_or_assign(key_type&& k, M&& obj); // C++17 + pair insert_or_assign(key_type&& k, M&& obj); // C++17 // constexpr since C++26 template - iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); // C++17 + iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); // C++17 // constexpr since C++26 template - iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17 + iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17 // constexpr since C++26 - iterator erase(const_iterator position); - iterator erase(iterator position); // C++14 - size_type erase(const key_type& k); - iterator erase(const_iterator first, const_iterator last); - void clear() noexcept; + iterator erase(const_iterator position); // constexpr since C++26 + iterator erase(iterator position); // C++14 // constexpr since C++26 + size_type erase(const key_type& k); // constexpr since C++26 + iterator erase(const_iterator first, const_iterator last); // constexpr since C++26 + void clear() noexcept; // constexpr since C++26 template - void merge(map& source); // C++17 + void merge(map& source); // C++17 // constexpr since C++26 template - void merge(map&& source); // C++17 + void merge(map&& source); // C++17 // constexpr since C++26 template - void merge(multimap& source); // C++17 + void merge(multimap& source); // C++17 // constexpr since C++26 template - void merge(multimap&& source); // C++17 + void merge(multimap&& source); // C++17 // constexpr since C++26 void swap(map& m) noexcept(allocator_traits::is_always_equal::value && - is_nothrow_swappable::value); // C++17 + is_nothrow_swappable::value); // C++17 // constexpr since C++26 // observers: - allocator_type get_allocator() const noexcept; - key_compare key_comp() const; - value_compare value_comp() const; + allocator_type get_allocator() const noexcept; // constexpr since C++26 + key_compare key_comp() const; // constexpr since C++26 + value_compare value_comp() const; // constexpr since C++26 // map operations: - iterator find(const key_type& k); - const_iterator find(const key_type& k) const; + iterator find(const key_type& k); // constexpr since C++26 + const_iterator find(const key_type& k) const; // constexpr since C++26 template - iterator find(const K& x); // C++14 + iterator find(const K& x); // C++14 // constexpr since C++26 template - const_iterator find(const K& x) const; // C++14 + const_iterator find(const K& x) const; // C++14 // constexpr since C++26 template - size_type count(const K& x) const; // C++14 - size_type count(const key_type& k) const; + size_type count(const K& x) const; // C++14 // constexpr since C++26 + size_type count(const key_type& k) const; // constexpr since C++26 - bool contains(const key_type& x) const; // C++20 - template bool contains(const K& x) const; // C++20 + bool contains(const key_type& x) const; // C++20 // constexpr since C++26 + template bool contains(const K& x) const; // C++20 // constexpr since C++26 - iterator lower_bound(const key_type& k); - const_iterator lower_bound(const key_type& k) const; + iterator lower_bound(const key_type& k); // constexpr since C++26 + const_iterator lower_bound(const key_type& k) const; // constexpr since C++26 template - iterator lower_bound(const K& x); // C++14 + iterator lower_bound(const K& x); // C++14 // constexpr since C++26 template - const_iterator lower_bound(const K& x) const; // C++14 + const_iterator lower_bound(const K& x) const; // C++14 // constexpr since C++26 - iterator upper_bound(const key_type& k); - const_iterator upper_bound(const key_type& k) const; + iterator upper_bound(const key_type& k); // constexpr since C++26 + const_iterator upper_bound(const key_type& k) const; // constexpr since C++26 template - iterator upper_bound(const K& x); // C++14 + iterator upper_bound(const K& x); // C++14 // constexpr since C++26 template - const_iterator upper_bound(const K& x) const; // C++14 + const_iterator upper_bound(const K& x) const; // C++14 // constexpr since C++26 - pair equal_range(const key_type& k); - pair equal_range(const key_type& k) const; + pair equal_range(const key_type& k); // constexpr since C++26 + pair equal_range(const key_type& k) const; // constexpr since C++26 template - pair equal_range(const K& x); // C++14 + pair equal_range(const K& x); // C++14 // constexpr since C++26 template - pair equal_range(const K& x) const; // C++14 + pair equal_range(const K& x) const; // C++14 // constexpr since C++26 }; template >, Allocator) -> map, A template bool operator==(const map& x, - const map& y); + const map& y); // constexpr since C++26 template bool @@ -297,11 +299,11 @@ template template void swap(map& x, map& y) - noexcept(noexcept(x.swap(y))); + noexcept(noexcept(x.swap(y))); // constexpr since C++26 template typename map::size_type -erase_if(map& c, Predicate pred); // C++20 +erase_if(map& c, Predicate pred); // C++20 // constexpr since C++26 template , @@ -600,10 +602,7 @@ erase_if(multimap& c, Predicate pred); // C++20 # include <__ranges/from_range.h> # include <__tree> # include <__type_traits/container_traits.h> -# include <__type_traits/desugars_to.h> # include <__type_traits/is_allocator.h> -# include <__type_traits/is_convertible.h> -# include <__type_traits/make_transparent.h> # include <__type_traits/remove_const.h> # include <__type_traits/type_identity.h> # include <__utility/forward.h> @@ -642,48 +641,52 @@ class __map_value_compare { _LIBCPP_COMPRESSED_ELEMENT(_Compare, __comp_); public: - _LIBCPP_HIDE_FROM_ABI __map_value_compare() _NOEXCEPT_(is_nothrow_default_constructible<_Compare>::value) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_value_compare() + _NOEXCEPT_(is_nothrow_default_constructible<_Compare>::value) : __comp_() {} - _LIBCPP_HIDE_FROM_ABI __map_value_compare(_Compare __c) _NOEXCEPT_(is_nothrow_copy_constructible<_Compare>::value) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_value_compare(_Compare __c) + _NOEXCEPT_(is_nothrow_copy_constructible<_Compare>::value) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return __comp_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const _Compare& key_comp() const _NOEXCEPT { return __comp_; } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const { return __comp_(__x.first, __y.first); } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const { return __comp_(__x.first, __y); } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const { return __comp_(__x, __y.first); } - _LIBCPP_HIDE_FROM_ABI void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _CP& __x, const _CP& __y) const { + return __comp_(__x.first, __y.first); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _CP& __x, const _Key& __y) const { + return __comp_(__x.first, __y); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _Key& __x, const _CP& __y) const { + return __comp_(__x, __y.first); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(__map_value_compare& __y) + _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) { using std::swap; swap(__comp_, __y.__comp_); } # if _LIBCPP_STD_VER >= 14 template - _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _K2& __x, const _CP& __y) const { return __comp_(__x, __y.first); } template - _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _CP& __x, const _K2& __y) const { return __comp_(__x.first, __y); } # endif }; -template -struct __make_transparent<__map_value_compare<_Key, _MapValueT, _Compare> > { - using type _LIBCPP_NODEBUG = __map_value_compare<_Key, _MapValueT, __make_transparent_t<_Compare> >; -}; - # if _LIBCPP_STD_VER >= 14 template struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _Compare>, _MapValueT, _MapValueT> { __lazy_synth_three_way_comparator<_Compare, _Key, _Key> __comp_; - __lazy_synth_three_way_comparator( + _LIBCPP_CONSTEXPR_SINCE_CXX26 __lazy_synth_three_way_comparator( _LIBCPP_CTOR_LIFETIMEBOUND const __map_value_compare<_Key, _MapValueT, _Compare>& __comp) : __comp_(__comp.key_comp()) {} - _LIBCPP_HIDE_FROM_ABI auto + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto operator()(_LIBCPP_LIFETIMEBOUND const _MapValueT& __lhs, _LIBCPP_LIFETIMEBOUND const _MapValueT& __rhs) const { return __comp_(__lhs.first, __rhs.first); } @@ -693,11 +696,11 @@ template struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _Compare>, _TransparentKey, _MapValueT> { __lazy_synth_three_way_comparator<_Compare, _TransparentKey, _Key> __comp_; - __lazy_synth_three_way_comparator( + _LIBCPP_CONSTEXPR_SINCE_CXX26 __lazy_synth_three_way_comparator( _LIBCPP_CTOR_LIFETIMEBOUND const __map_value_compare<_Key, _MapValueT, _Compare>& __comp) : __comp_(__comp.key_comp()) {} - _LIBCPP_HIDE_FROM_ABI auto + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto operator()(_LIBCPP_LIFETIMEBOUND const _TransparentKey& __lhs, _LIBCPP_LIFETIMEBOUND const _MapValueT& __rhs) const { return __comp_(__lhs, __rhs.first); } @@ -719,7 +722,7 @@ struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _ # endif // _LIBCPP_STD_VER >= 14 template -inline _LIBCPP_HIDE_FROM_ABI void +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(__map_value_compare<_Key, _CP, _Compare>& __x, __map_value_compare<_Key, _CP, _Compare>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); @@ -780,37 +783,41 @@ public: using reference = value_type&; using pointer = typename _TreeIterator::pointer; - _LIBCPP_HIDE_FROM_ABI __map_iterator() _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator() _NOEXCEPT {} - _LIBCPP_HIDE_FROM_ABI __map_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *__i_; } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(*__i_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return *__i_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { + return pointer_traits::pointer_to(*__i_); + } - _LIBCPP_HIDE_FROM_ABI __map_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator& operator++() { ++__i_; return *this; } - _LIBCPP_HIDE_FROM_ABI __map_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator operator++(int) { __map_iterator __t(*this); ++(*this); return __t; } - _LIBCPP_HIDE_FROM_ABI __map_iterator& operator--() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator& operator--() { --__i_; return *this; } - _LIBCPP_HIDE_FROM_ABI __map_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator operator--(int) { __map_iterator __t(*this); --(*this); return __t; } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __map_iterator& __x, const __map_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const __map_iterator& __x, const __map_iterator& __y) { return __x.__i_ == __y.__i_; } - friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __map_iterator& __x, const __map_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator!=(const __map_iterator& __x, const __map_iterator& __y) { return __x.__i_ != __y.__i_; } @@ -833,39 +840,43 @@ public: using reference = const value_type&; using pointer = typename _TreeIterator::pointer; - _LIBCPP_HIDE_FROM_ABI __map_const_iterator() _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator() _NOEXCEPT {} - _LIBCPP_HIDE_FROM_ABI __map_const_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator(__map_iterator< typename _TreeIterator::__non_const_iterator> __i) _NOEXCEPT : __i_(__i.__i_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *__i_; } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(*__i_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return *__i_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { + return pointer_traits::pointer_to(*__i_); + } - _LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator& operator++() { ++__i_; return *this; } - _LIBCPP_HIDE_FROM_ABI __map_const_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator operator++(int) { __map_const_iterator __t(*this); ++(*this); return __t; } - _LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator--() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator& operator--() { --__i_; return *this; } - _LIBCPP_HIDE_FROM_ABI __map_const_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator operator--(int) { __map_const_iterator __t(*this); --(*this); return __t; } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __map_const_iterator& __x, const __map_const_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const __map_const_iterator& __x, const __map_const_iterator& __y) { return __x.__i_ == __y.__i_; } - friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __map_const_iterator& __x, const __map_const_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator!=(const __map_const_iterator& __x, const __map_const_iterator& __y) { return __x.__i_ != __y.__i_; } @@ -901,10 +912,11 @@ public: protected: key_compare comp; - _LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : comp(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare(key_compare __c) : comp(__c) {} public: - _LIBCPP_HIDE_FROM_ABI bool operator()(const value_type& __x, const value_type& __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const value_type& __x, const value_type& __y) const { return comp(__x.first, __y.first); } }; @@ -940,26 +952,27 @@ public: template friend class multimap; - _LIBCPP_HIDE_FROM_ABI map() _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map() _NOEXCEPT_( is_nothrow_default_constructible::value&& is_nothrow_default_constructible::value&& is_nothrow_copy_constructible::value) : __tree_(__vc(key_compare())) {} - _LIBCPP_HIDE_FROM_ABI explicit map(const key_compare& __comp) _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit map(const key_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible::value&& is_nothrow_copy_constructible::value) : __tree_(__vc(__comp)) {} - _LIBCPP_HIDE_FROM_ABI explicit map(const key_compare& __comp, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit map(const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), typename __base::allocator_type(__a)) {} template - _LIBCPP_HIDE_FROM_ABI map(_InputIterator __f, _InputIterator __l, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + map(_InputIterator __f, _InputIterator __l, const key_compare& __comp = key_compare()) : __tree_(__vc(__comp)) { insert(__f, __l); } template - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(_InputIterator __f, _InputIterator __l, const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), typename __base::allocator_type(__a)) { insert(__f, __l); @@ -967,7 +980,7 @@ public: # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(from_range_t, _Range&& __range, const key_compare& __comp = key_compare(), @@ -979,157 +992,169 @@ public: # if _LIBCPP_STD_VER >= 14 template - _LIBCPP_HIDE_FROM_ABI map(_InputIterator __f, _InputIterator __l, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 map(_InputIterator __f, _InputIterator __l, const allocator_type& __a) : map(__f, __l, key_compare(), __a) {} # endif # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI map(from_range_t, _Range&& __range, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(from_range_t, _Range&& __range, const allocator_type& __a) : map(from_range, std::forward<_Range>(__range), key_compare(), __a) {} # endif - _LIBCPP_HIDE_FROM_ABI map(const map& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(const map& __m) = default; - _LIBCPP_HIDE_FROM_ABI map& operator=(const map& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map& operator=(const map& __m) = default; # ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI map(map&& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(map&& __m) = default; - _LIBCPP_HIDE_FROM_ABI map(map&& __m, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(map&& __m, const allocator_type& __a); - _LIBCPP_HIDE_FROM_ABI map& operator=(map&& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map& operator=(map&& __m) = default; - _LIBCPP_HIDE_FROM_ABI map(initializer_list __il, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + map(initializer_list __il, const key_compare& __comp = key_compare()) : __tree_(__vc(__comp)) { insert(__il.begin(), __il.end()); } - _LIBCPP_HIDE_FROM_ABI map(initializer_list __il, const key_compare& __comp, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + map(initializer_list __il, const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), typename __base::allocator_type(__a)) { insert(__il.begin(), __il.end()); } # if _LIBCPP_STD_VER >= 14 - _LIBCPP_HIDE_FROM_ABI map(initializer_list __il, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(initializer_list __il, const allocator_type& __a) : map(__il, key_compare(), __a) {} # endif - _LIBCPP_HIDE_FROM_ABI map& operator=(initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map& operator=(initializer_list __il) { __tree_.__assign_unique(__il.begin(), __il.end()); return *this; } # endif // _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI explicit map(const allocator_type& __a) : __tree_(typename __base::allocator_type(__a)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit map(const allocator_type& __a) + : __tree_(typename __base::allocator_type(__a)) {} - _LIBCPP_HIDE_FROM_ABI map(const map& __m, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(const map& __m, const allocator_type& __a) : __tree_(__m.__tree_.value_comp(), typename __base::allocator_type(__a)) { insert(__m.begin(), __m.end()); } - _LIBCPP_HIDE_FROM_ABI ~map() { static_assert(sizeof(std::__diagnose_non_const_comparator<_Key, _Compare>()), ""); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~map() { + static_assert(sizeof(std::__diagnose_non_const_comparator<_Key, _Compare>()), ""); + } - _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); } - _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() _NOEXCEPT { return __tree_.begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const _NOEXCEPT { return __tree_.begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() _NOEXCEPT { return __tree_.end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const _NOEXCEPT { return __tree_.end(); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() _NOEXCEPT { + return reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const _NOEXCEPT { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() _NOEXCEPT { + return reverse_iterator(begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const _NOEXCEPT { + return const_reverse_iterator(begin()); + } - _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const _NOEXCEPT { return begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const _NOEXCEPT { return end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const _NOEXCEPT { + return rbegin(); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const _NOEXCEPT { return rend(); } - [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __tree_.size() == 0; } - _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const _NOEXCEPT { + return __tree_.size() == 0; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const _NOEXCEPT { return __tree_.size(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const _NOEXCEPT { + return __tree_.max_size(); + } - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](const key_type& __k); # ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](key_type&& __k); # endif - template >, int> = 0> - _LIBCPP_HIDE_FROM_ABI mapped_type& at(_Arg&& __arg) { - auto [_, __child] = __tree_.__find_equal(__arg); - if (__child == nullptr) - std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__get_value().second; - } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& at(const key_type& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_type& at(const key_type& __k) const; - template >, int> = 0> - _LIBCPP_HIDE_FROM_ABI const mapped_type& at(_Arg&& __arg) const { - auto [_, __child] = __tree_.__find_equal(__arg); - if (__child == nullptr) - std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__get_value().second; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 allocator_type get_allocator() const _NOEXCEPT { + return allocator_type(__tree_.__alloc()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { + return __tree_.value_comp().key_comp(); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const { + return value_compare(__tree_.value_comp().key_comp()); } - - _LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __k); - _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __k) const; - - _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { return allocator_type(__tree_.__alloc()); } - _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __tree_.value_comp().key_comp(); } - _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__tree_.value_comp().key_comp()); } # ifndef _LIBCPP_CXX03_LANG template - _LIBCPP_HIDE_FROM_ABI pair emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair emplace(_Args&&... __args) { return __tree_.__emplace_unique(std::forward<_Args>(__args)...); } template - _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __p, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __p, _Args&&... __args) { return __tree_.__emplace_hint_unique(__p.__i_, std::forward<_Args>(__args)...).first; } template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI pair insert(_Pp&& __p) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(_Pp&& __p) { return __tree_.__emplace_unique(std::forward<_Pp>(__p)); } template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __pos, _Pp&& __p) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __pos, _Pp&& __p) { return __tree_.__emplace_hint_unique(__pos.__i_, std::forward<_Pp>(__p)).first; } # endif // _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI pair insert(const value_type& __v) { return __tree_.__emplace_unique(__v); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(const value_type& __v) { + return __tree_.__emplace_unique(__v); + } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, const value_type& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __p, const value_type& __v) { return __tree_.__emplace_hint_unique(__p.__i_, __v).first; } # ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI pair insert(value_type&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(value_type&& __v) { return __tree_.__emplace_unique(std::move(__v)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, value_type&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __p, value_type&& __v) { return __tree_.__emplace_hint_unique(__p.__i_, std::move(__v)).first; } - _LIBCPP_HIDE_FROM_ABI void insert(initializer_list __il) { insert(__il.begin(), __il.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list __il) { + insert(__il.begin(), __il.end()); + } # endif template - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) { __tree_.__insert_range_unique(__first, __last); } # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) { __tree_.__insert_range_unique(ranges::begin(__range), ranges::end(__range)); } # endif @@ -1137,13 +1162,15 @@ public: # if _LIBCPP_STD_VER >= 17 template - _LIBCPP_HIDE_FROM_ABI pair try_emplace(const key_type& __k, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + try_emplace(const key_type& __k, _Args&&... __args) { return __tree_.__emplace_unique( std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple(std::forward<_Args>(__args)...)); } template - _LIBCPP_HIDE_FROM_ABI pair try_emplace(key_type&& __k, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + try_emplace(key_type&& __k, _Args&&... __args) { return __tree_.__emplace_unique( std::piecewise_construct, std::forward_as_tuple(std::move(__k)), @@ -1151,7 +1178,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args) { return __tree_ .__emplace_hint_unique( __h.__i_, @@ -1162,7 +1190,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args) { return __tree_ .__emplace_hint_unique( __h.__i_, @@ -1173,7 +1202,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(const key_type& __k, _Vp&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + insert_or_assign(const key_type& __k, _Vp&& __v) { auto __result = __tree_.__emplace_unique(__k, std::forward<_Vp>(__v)); auto& [__iter, __inserted] = __result; if (!__inserted) @@ -1182,7 +1212,7 @@ public: } template - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(key_type&& __k, _Vp&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert_or_assign(key_type&& __k, _Vp&& __v) { auto __result = __tree_.__emplace_unique(std::move(__k), std::forward<_Vp>(__v)); auto& [__iter, __inserted] = __result; if (!__inserted) @@ -1191,7 +1221,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __h, const key_type& __k, _Vp&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __h, const key_type& __k, _Vp&& __v) { auto [__r, __inserted] = __tree_.__emplace_hint_unique(__h.__i_, __k, std::forward<_Vp>(__v)); if (!__inserted) @@ -1201,7 +1232,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __h, key_type&& __k, _Vp&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __h, key_type&& __k, _Vp&& __v) { auto [__r, __inserted] = __tree_.__emplace_hint_unique(__h.__i_, std::move(__k), std::forward<_Vp>(__v)); if (!__inserted) @@ -1212,39 +1244,45 @@ public: # endif // _LIBCPP_STD_VER >= 17 - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __tree_.erase(__p.__i_); } - _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __p) { return __tree_.erase(__p.__i_); } - _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __tree_.__erase_unique(__k); } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __p) { + return __tree_.erase(__p.__i_); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __p) { return __tree_.erase(__p.__i_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __k) { + return __tree_.__erase_unique(__k); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __f, const_iterator __l) { return __tree_.erase(__f.__i_, __l.__i_); } - _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __tree_.clear(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() _NOEXCEPT { __tree_.clear(); } # if _LIBCPP_STD_VER >= 17 - _LIBCPP_HIDE_FROM_ABI insert_return_type insert(node_type&& __nh) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 insert_return_type insert(node_type&& __nh) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to map::insert()"); return __tree_.template __node_handle_insert_unique< node_type, insert_return_type>(std::move(__nh)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, node_type&& __nh) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, node_type&& __nh) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to map::insert()"); return __tree_.template __node_handle_insert_unique(__hint.__i_, std::move(__nh)); } - _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(key_type const& __key) { return __tree_.template __node_handle_extract(__key); } - _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(const_iterator __it) { return __tree_.template __node_handle_extract(__it.__i_); } template - _LIBCPP_HIDE_FROM_ABI void merge(map& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(map& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } template - _LIBCPP_HIDE_FROM_ABI void merge(map&& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(map&& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); @@ -1263,101 +1301,95 @@ public: } # endif - _LIBCPP_HIDE_FROM_ABI void swap(map& __m) _NOEXCEPT_(__is_nothrow_swappable_v<__base>) { __tree_.swap(__m.__tree_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(map& __m) _NOEXCEPT_(__is_nothrow_swappable_v<__base>) { + __tree_.swap(__m.__tree_); + } - _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); } - _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __k) { return __tree_.find(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __k) const { + return __tree_.find(__k); + } # if _LIBCPP_STD_VER >= 14 - template || __is_transparently_comparable_v<_Compare, key_type, _K2>, - int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) { + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _K2& __k) { return __tree_.find(__k); } - template || __is_transparently_comparable_v<_Compare, key_type, _K2>, - int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const { + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _K2& __k) const { return __tree_.find(__k); } # endif - _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __tree_.__count_unique(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __k) const { + return __tree_.__count_unique(__k); + } # if _LIBCPP_STD_VER >= 14 template , int> = 0> - _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _K2& __k) const { return __tree_.__count_multi(__k); } # endif # if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); } - template || __is_transparently_comparable_v<_Compare, key_type, _K2>, - int> = 0> - _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __k) const { + return find(__k) != end(); + } + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _K2& __k) const { return find(__k) != end(); } # endif // _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_unique(__k); } - - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { - return __tree_.__lower_bound_unique(__k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __k) { + return __tree_.lower_bound(__k); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __k) const { + return __tree_.lower_bound(__k); } - - // The transparent versions of the lookup functions use the _multi version, since a non-element key is allowed to - // match multiple elements. # if _LIBCPP_STD_VER >= 14 - template || __is_transparently_comparable_v<_Compare, key_type, _K2>, - int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) { - return __tree_.__lower_bound_multi(__k); + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _K2& __k) { + return __tree_.lower_bound(__k); } - template || __is_transparently_comparable_v<_Compare, key_type, _K2>, - int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const { - return __tree_.__lower_bound_multi(__k); + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _K2& __k) const { + return __tree_.lower_bound(__k); } # endif - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_unique(__k); } - - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { - return __tree_.__upper_bound_unique(__k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __k) { + return __tree_.upper_bound(__k); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __k) const { + return __tree_.upper_bound(__k); } - # if _LIBCPP_STD_VER >= 14 - template || __is_transparently_comparable_v<_Compare, key_type, _K2>, - int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) { - return __tree_.__upper_bound_multi(__k); + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _K2& __k) { + return __tree_.upper_bound(__k); } - template || __is_transparently_comparable_v<_Compare, key_type, _K2>, - int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const { - return __tree_.__upper_bound_multi(__k); + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _K2& __k) const { + return __tree_.upper_bound(__k); } # endif - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const key_type& __k) { return __tree_.__equal_range_unique(__k); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const key_type& __k) const { return __tree_.__equal_range_unique(__k); } # if _LIBCPP_STD_VER >= 14 template , int> = 0> - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const _K2& __k) { return __tree_.__equal_range_multi(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const _K2& __k) const { return __tree_.__equal_range_multi(__k); } # endif @@ -1382,8 +1414,8 @@ template >, class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, - class = enable_if_t>, - class = enable_if_t<__is_allocator_v<_Allocator>>> + class = enable_if_t::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> map(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) -> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare, _Allocator>; @@ -1391,8 +1423,8 @@ map(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocat template >, class _Allocator = allocator<__range_to_alloc_type<_Range>>, - class = enable_if_t>, - class = enable_if_t<__is_allocator_v<_Allocator>>> + class = enable_if_t::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> map<__range_key_type<_Range>, __range_mapped_type<_Range>, _Compare, _Allocator>; # endif @@ -1401,15 +1433,16 @@ template >, class _Allocator = allocator>, - class = enable_if_t>, - class = enable_if_t<__is_allocator_v<_Allocator>>> -map(initializer_list>, _Compare = _Compare(), _Allocator = _Allocator()) - -> map, _Tp, _Compare, _Allocator>; + class = enable_if_t::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +map(initializer_list>, + _Compare = _Compare(), + _Allocator = _Allocator()) -> map, _Tp, _Compare, _Allocator>; template ::value, void>, - class = enable_if_t<__is_allocator_v<_Allocator>>> + class = enable_if_t<__is_allocator<_Allocator>::value, void>> map(_InputIterator, _InputIterator, _Allocator) -> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, @@ -1417,19 +1450,19 @@ map(_InputIterator, _InputIterator, _Allocator) _Allocator>; # if _LIBCPP_STD_VER >= 23 -template >> +template ::value, void>> map(from_range_t, _Range&&, _Allocator) -> map<__range_key_type<_Range>, __range_mapped_type<_Range>, less<__range_key_type<_Range>>, _Allocator>; # endif -template >> -map(initializer_list>, _Allocator) - -> map, _Tp, less>, _Allocator>; +template ::value, void>> +map(initializer_list>, + _Allocator) -> map, _Tp, less>, _Allocator>; # endif # ifndef _LIBCPP_CXX03_LANG template -map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) +_LIBCPP_CONSTEXPR_SINCE_CXX26 map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) : __tree_(std::move(__m.__tree_), typename __base::allocator_type(__a)) { if (__a != __m.get_allocator()) { const_iterator __e = cend(); @@ -1441,13 +1474,13 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) } template -_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { return __tree_.__emplace_unique(std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple()) .first->second; } template -_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k) { return __tree_ .__emplace_unique(std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple()) .first->second; @@ -1482,23 +1515,23 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { # endif // _LIBCPP_CXX03_LANG template -_Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) { auto [_, __child] = __tree_.__find_equal(__k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__get_value().second; + return std::__static_fancy_pointer_cast<__node_pointer>(__child)->__get_value().second; } template -const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const { +_LIBCPP_CONSTEXPR_SINCE_CXX26 const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const { auto [_, __child] = __tree_.__find_equal(__k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__get_value().second; + return std::__static_fancy_pointer_cast<__node_pointer>(__child)->__get_value().second; } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator==(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return __x.size() == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin()); } @@ -1506,31 +1539,31 @@ operator==(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, # if _LIBCPP_STD_VER <= 17 template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator<(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return std::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator!=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__x == __y); } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator>(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return __y < __x; } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator>=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__x < __y); } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__y < __x); } @@ -1538,7 +1571,7 @@ operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, # else // #if _LIBCPP_STD_VER <= 17 template -_LIBCPP_HIDE_FROM_ABI __synth_three_way_result> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __synth_three_way_result> operator<=>(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); } @@ -1546,7 +1579,7 @@ operator<=>(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp # endif // #if _LIBCPP_STD_VER <= 17 template -inline _LIBCPP_HIDE_FROM_ABI void +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(map<_Key, _Tp, _Compare, _Allocator>& __x, map<_Key, _Tp, _Compare, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); @@ -1554,7 +1587,7 @@ swap(map<_Key, _Tp, _Compare, _Allocator>& __x, map<_Key, _Tp, _Compare, _Alloca # if _LIBCPP_STD_VER >= 20 template -inline _LIBCPP_HIDE_FROM_ABI typename map<_Key, _Tp, _Compare, _Allocator>::size_type +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename map<_Key, _Tp, _Compare, _Allocator>::size_type erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) { return std::__libcpp_erase_if_container(__c, __pred); } @@ -1881,38 +1914,30 @@ public: } # endif // _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_multi(__k); } - - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { - return __tree_.__lower_bound_multi(__k); - } - + _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.lower_bound(__k); } + _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__k); } # if _LIBCPP_STD_VER >= 14 template , int> = 0> _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) { - return __tree_.__lower_bound_multi(__k); + return __tree_.lower_bound(__k); } template , int> = 0> _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const { - return __tree_.__lower_bound_multi(__k); + return __tree_.lower_bound(__k); } # endif - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_multi(__k); } - - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { - return __tree_.__upper_bound_multi(__k); - } - + _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.upper_bound(__k); } + _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__k); } # if _LIBCPP_STD_VER >= 14 template , int> = 0> _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) { - return __tree_.__upper_bound_multi(__k); + return __tree_.upper_bound(__k); } template , int> = 0> _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const { - return __tree_.__upper_bound_multi(__k); + return __tree_.upper_bound(__k); } # endif @@ -1947,8 +1972,8 @@ template >, class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, - class = enable_if_t>, - class = enable_if_t<__is_allocator_v<_Allocator>>> + class = enable_if_t::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> multimap(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) -> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare, _Allocator>; @@ -1956,8 +1981,8 @@ multimap(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Al template >, class _Allocator = allocator<__range_to_alloc_type<_Range>>, - class = enable_if_t>, - class = enable_if_t<__is_allocator_v<_Allocator>>> + class = enable_if_t::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> multimap(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> multimap<__range_key_type<_Range>, __range_mapped_type<_Range>, _Compare, _Allocator>; # endif @@ -1966,15 +1991,16 @@ template >, class _Allocator = allocator>, - class = enable_if_t>, - class = enable_if_t<__is_allocator_v<_Allocator>>> -multimap(initializer_list>, _Compare = _Compare(), _Allocator = _Allocator()) - -> multimap, _Tp, _Compare, _Allocator>; + class = enable_if_t::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +multimap(initializer_list>, + _Compare = _Compare(), + _Allocator = _Allocator()) -> multimap, _Tp, _Compare, _Allocator>; template ::value, void>, - class = enable_if_t<__is_allocator_v<_Allocator>>> + class = enable_if_t<__is_allocator<_Allocator>::value, void>> multimap(_InputIterator, _InputIterator, _Allocator) -> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, @@ -1982,14 +2008,14 @@ multimap(_InputIterator, _InputIterator, _Allocator) _Allocator>; # if _LIBCPP_STD_VER >= 23 -template >> +template ::value, void>> multimap(from_range_t, _Range&&, _Allocator) -> multimap<__range_key_type<_Range>, __range_mapped_type<_Range>, less<__range_key_type<_Range>>, _Allocator>; # endif -template >> -multimap(initializer_list>, _Allocator) - -> multimap, _Tp, less>, _Allocator>; +template ::value, void>> +multimap(initializer_list>, + _Allocator) -> multimap, _Tp, less>, _Allocator>; # endif # ifndef _LIBCPP_CXX03_LANG diff --git a/libcxx/include/version b/libcxx/include/version index 0fef1bb87cf60..03d14bb146741 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -37,8 +37,7 @@ __cpp_lib_atomic_float 201711L __cpp_lib_atomic_is_always_lock_free 201603L __cpp_lib_atomic_lock_free_type_aliases 201907L __cpp_lib_atomic_min_max 202403L -__cpp_lib_atomic_ref 202411L - 201806L // C++20 +__cpp_lib_atomic_ref 201806L __cpp_lib_atomic_shared_ptr 201711L __cpp_lib_atomic_value_initialization 201911L __cpp_lib_atomic_wait 201907L @@ -60,8 +59,6 @@ __cpp_lib_char8_t 201907L __cpp_lib_chrono_udls 201304L __cpp_lib_clamp 201603L -__cpp_lib_common_reference 202302L -__cpp_lib_common_reference_wrapper 202302L __cpp_lib_complex_udls 201309L __cpp_lib_concepts 202002L __cpp_lib_constexpr_algorithms 202306L @@ -75,6 +72,7 @@ __cpp_lib_constexpr_forward_list 202502L __cpp_lib_constexpr_functional 201907L __cpp_lib_constexpr_iterator 201811L __cpp_lib_constexpr_list 202502L +__cpp_lib_constexpr_map 202502L __cpp_lib_constexpr_memory 202202L 201811L // C++20 __cpp_lib_constexpr_new 202406L @@ -86,8 +84,8 @@ __cpp_lib_constexpr_tuple 201811L __cpp_lib_constexpr_typeinfo 202106L __cpp_lib_constexpr_utility 201811L __cpp_lib_constexpr_vector 201907L -__cpp_lib_constrained_equality 202411L - +__cpp_lib_constrained_equality 202403L + __cpp_lib_containers_ranges 202202L @@ -206,7 +204,6 @@ __cpp_lib_ranges_chunk_by 202202L __cpp_lib_ranges_concat 202403L __cpp_lib_ranges_contains 202207L __cpp_lib_ranges_find_last 202207L -__cpp_lib_ranges_indices 202506L __cpp_lib_ranges_iota 202202L __cpp_lib_ranges_join_with 202202L __cpp_lib_ranges_repeat 202207L @@ -247,7 +244,6 @@ __cpp_lib_starts_ends_with 201711L __cpp_lib_string_contains 202011L __cpp_lib_string_resize_and_overwrite 202110L -__cpp_lib_string_subview 202506L __cpp_lib_string_udls 201304L __cpp_lib_string_view 202403L 201803L // C++20 @@ -336,7 +332,7 @@ __cpp_lib_void_t 201411L # define __cpp_lib_clamp 201603L # define __cpp_lib_enable_shared_from_this 201603L // # define __cpp_lib_execution 201603L -# if _LIBCPP_HAS_FILESYSTEM +# if _LIBCPP_HAS_FILESYSTEM && _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY # define __cpp_lib_filesystem 201703L # endif # define __cpp_lib_gcd_lcm 201606L @@ -394,8 +390,10 @@ __cpp_lib_void_t 201411L # define __cpp_lib_atomic_ref 201806L // # define __cpp_lib_atomic_shared_ptr 201711L # define __cpp_lib_atomic_value_initialization 201911L -# define __cpp_lib_atomic_wait 201907L -# if _LIBCPP_HAS_THREADS +# if _LIBCPP_AVAILABILITY_HAS_SYNC +# define __cpp_lib_atomic_wait 201907L +# endif +# if _LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC # define __cpp_lib_barrier 201907L # endif # define __cpp_lib_bind_front 201907L @@ -405,8 +403,6 @@ __cpp_lib_void_t 201411L # if _LIBCPP_HAS_CHAR8_T # define __cpp_lib_char8_t 201907L # endif -# define __cpp_lib_common_reference 202302L -# define __cpp_lib_common_reference_wrapper 202302L # define __cpp_lib_concepts 202002L # define __cpp_lib_constexpr_algorithms 201806L # define __cpp_lib_constexpr_complex 201711L @@ -440,10 +436,10 @@ __cpp_lib_void_t 201411L // # define __cpp_lib_is_layout_compatible 201907L # define __cpp_lib_is_nothrow_convertible 201806L // # define __cpp_lib_is_pointer_interconvertible 201907L -# if _LIBCPP_HAS_THREADS +# if _LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC # define __cpp_lib_jthread 201911L # endif -# if _LIBCPP_HAS_THREADS +# if _LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC # define __cpp_lib_latch 201907L # endif # define __cpp_lib_list_remove_return_type 201806L @@ -456,7 +452,7 @@ __cpp_lib_void_t 201411L # endif # define __cpp_lib_ranges 202110L # define __cpp_lib_remove_cvref 201711L -# if _LIBCPP_HAS_THREADS +# if _LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC # define __cpp_lib_semaphore 201907L # endif # undef __cpp_lib_shared_ptr_arrays @@ -524,7 +520,7 @@ __cpp_lib_void_t 201411L # define __cpp_lib_ranges_contains 202207L # define __cpp_lib_ranges_find_last 202207L # define __cpp_lib_ranges_iota 202202L -# define __cpp_lib_ranges_join_with 202202L +// # define __cpp_lib_ranges_join_with 202202L # define __cpp_lib_ranges_repeat 202207L // # define __cpp_lib_ranges_slide 202202L # define __cpp_lib_ranges_starts_ends_with 202106L @@ -545,8 +541,6 @@ __cpp_lib_void_t 201411L # define __cpp_lib_aligned_accessor 202411L // # define __cpp_lib_associative_heterogeneous_insertion 202306L // # define __cpp_lib_atomic_min_max 202403L -# undef __cpp_lib_atomic_ref -# define __cpp_lib_atomic_ref 202411L # undef __cpp_lib_bind_front # define __cpp_lib_bind_front 202306L # define __cpp_lib_bitset 202306L @@ -554,11 +548,12 @@ __cpp_lib_void_t 201411L # define __cpp_lib_constexpr_algorithms 202306L # define __cpp_lib_constexpr_forward_list 202502L # define __cpp_lib_constexpr_list 202502L +# define __cpp_lib_constexpr_map 202502L # if !defined(_LIBCPP_ABI_VCRUNTIME) # define __cpp_lib_constexpr_new 202406L # endif # define __cpp_lib_constexpr_queue 202502L -# define __cpp_lib_constrained_equality 202411L +// # define __cpp_lib_constrained_equality 202403L // # define __cpp_lib_copyable_function 202306L // # define __cpp_lib_debugging 202311L // # define __cpp_lib_default_template_type_for_algorithm_values 202403L @@ -588,12 +583,11 @@ __cpp_lib_void_t 201411L # define __cpp_lib_mdspan 202406L # undef __cpp_lib_not_fn # define __cpp_lib_not_fn 202306L -# define __cpp_lib_optional_range_support 202406L +// # define __cpp_lib_optional_range_support 202406L # undef __cpp_lib_out_ptr # define __cpp_lib_out_ptr 202311L // # define __cpp_lib_philox_engine 202406L // # define __cpp_lib_ranges_concat 202403L -# define __cpp_lib_ranges_indices 202506L # define __cpp_lib_ratio 202306L // # define __cpp_lib_rcu 202306L # define __cpp_lib_reference_wrapper 202403L @@ -603,7 +597,6 @@ __cpp_lib_void_t 201411L # define __cpp_lib_span_at 202311L # define __cpp_lib_span_initializer_list 202311L # define __cpp_lib_sstream_from_string_view 202306L -# define __cpp_lib_string_subview 202506L # undef __cpp_lib_string_view # define __cpp_lib_string_view 202403L // # define __cpp_lib_submdspan 202306L diff --git a/libcxx/test/std/containers/Emplaceable.h b/libcxx/test/std/containers/Emplaceable.h index d8d3407791731..d9d0965fa64cb 100644 --- a/libcxx/test/std/containers/Emplaceable.h +++ b/libcxx/test/std/containers/Emplaceable.h @@ -15,20 +15,20 @@ #if TEST_STD_VER >= 11 class Emplaceable { - TEST_CONSTEXPR Emplaceable(const Emplaceable&); - TEST_CONSTEXPR_CXX14 Emplaceable& operator=(const Emplaceable&); + Emplaceable(const Emplaceable&); + Emplaceable& operator=(const Emplaceable&); int int_; double double_; public: - TEST_CONSTEXPR_CXX20 Emplaceable() : int_(0), double_(0) {} - TEST_CONSTEXPR_CXX20 Emplaceable(int i, double d) : int_(i), double_(d) {} - TEST_CONSTEXPR_CXX20 Emplaceable(Emplaceable&& x) : int_(x.int_), double_(x.double_) { + TEST_CONSTEXPR_CXX26 Emplaceable() : int_(0), double_(0) {} + TEST_CONSTEXPR_CXX26 Emplaceable(int i, double d) : int_(i), double_(d) {} + TEST_CONSTEXPR_CXX26 Emplaceable(Emplaceable&& x) : int_(x.int_), double_(x.double_) { x.int_ = 0; x.double_ = 0; } - TEST_CONSTEXPR_CXX20 Emplaceable& operator=(Emplaceable&& x) { + TEST_CONSTEXPR_CXX26 Emplaceable& operator=(Emplaceable&& x) { int_ = x.int_; x.int_ = 0; double_ = x.double_; @@ -36,12 +36,10 @@ class Emplaceable { return *this; } - TEST_CONSTEXPR_CXX20 bool operator==(const Emplaceable& x) const { return int_ == x.int_ && double_ == x.double_; } - TEST_CONSTEXPR_CXX20 bool operator<(const Emplaceable& x) const { - return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_); - } + TEST_CONSTEXPR_CXX26 bool operator==(const Emplaceable& x) const { return int_ == x.int_ && double_ == x.double_; } + TEST_CONSTEXPR_CXX26 bool operator<(const Emplaceable& x) const { return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_); } - TEST_CONSTEXPR_CXX20 int get() const { return int_; } + TEST_CONSTEXPR_CXX26 int get() const { return int_; } }; template <> @@ -49,7 +47,7 @@ struct std::hash { typedef Emplaceable argument_type; typedef std::size_t result_type; - TEST_CONSTEXPR_CXX20 std::size_t operator()(const Emplaceable& x) const { return static_cast(x.get()); } + std::size_t operator()(const Emplaceable& x) const { return static_cast(x.get()); } }; #endif // TEST_STD_VER >= 11 diff --git a/libcxx/test/std/containers/associative/from_range_associative_containers.h b/libcxx/test/std/containers/associative/from_range_associative_containers.h index cb3646d738968..943b79f5211fc 100644 --- a/libcxx/test/std/containers/associative/from_range_associative_containers.h +++ b/libcxx/test/std/containers/associative/from_range_associative_containers.h @@ -60,7 +60,7 @@ template