diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index a36848ebd24b4..07ec543c008ce 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -428,6 +428,8 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_list`` ``202502L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_map`` ``202502L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_new`` ``202406L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_queue`` ``202502L`` diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index 8b8dce5083149..41239be9c9ba8 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -45,6 +45,7 @@ Improvements and New Features - The performance of ``map::map(const map&)`` has been improved up to 2.3x - The performance of ``map::operator=(const map&)`` has been improved by up to 11x +- P3372R3: ``constexpr map``(`Github `__) (The paper is partially implemented. ``constexpr map`` is implemented in this release) 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/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h index 8c7f8dff1b76b..62fcd93263b02 100644 --- a/libcxx/include/__memory/pointer_traits.h +++ b/libcxx/include/__memory/pointer_traits.h @@ -255,7 +255,7 @@ concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p // This function ensures safe conversions between fancy pointers at compile-time, where we avoid casts from/to // `__void_pointer` by obtaining the underlying raw pointer from the fancy pointer using `std::to_address`, // then dereferencing it to retrieve the pointed-to object, and finally constructing the target fancy pointer -// to that object using the `std::pointer_traits<>::pinter_to` function. +// to that object using the `std::pointer_traits<>::pointer_to` function. template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _PtrTo __static_fancy_pointer_cast(const _PtrFrom& __p) { using __ptr_traits = pointer_traits<_PtrTo>; diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle index b20b0c73a0518..6ce2e1b7d459c 100644 --- a/libcxx/include/__node_handle +++ b/libcxx/include/__node_handle @@ -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,8 @@ struct __map_node_handle_specifics { using key_type = __remove_const_t; using mapped_type = typename _NodeType::__node_value_type::second_type; + // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3372r3.html#node-handle-key + // https://cplusplus.github.io/CWG/issues/2514.html _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 6dadd0915c984..ac7e878922510 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -20,6 +20,7 @@ #include <__memory/addressof.h> #include <__memory/allocator_traits.h> #include <__memory/compressed_pair.h> +#include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include <__memory/swap_allocator.h> #include <__memory/unique_ptr.h> @@ -27,6 +28,8 @@ #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> @@ -83,7 +86,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_; } @@ -140,7 +143,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_; @@ -149,7 +152,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_; @@ -158,7 +161,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_); @@ -168,10 +171,10 @@ _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT { } 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_); @@ -180,11 +183,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(); @@ -192,7 +195,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) { @@ -211,7 +214,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_; @@ -230,7 +233,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_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI 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_; @@ -254,7 +257,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; @@ -310,7 +314,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"); @@ -525,7 +529,7 @@ public: typedef _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_() {} }; template @@ -539,11 +543,16 @@ 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); + } - ~__tree_node_base() = delete; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __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; }; @@ -557,6 +566,9 @@ public: _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_node(_Args&&... __args) + : __value_(std::forward<_Args>(__args)...) {} ~__tree_node() = delete; __tree_node(__tree_node const&) = delete; __tree_node& operator=(__tree_node const&) = delete; @@ -576,14 +588,15 @@ private: public: bool __value_constructed; - _LIBCPP_HIDE_FROM_ABI __tree_node_destructor(const __tree_node_destructor&) = default; - __tree_node_destructor& operator=(const __tree_node_destructor&) = delete; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_node_destructor(const __tree_node_destructor&) = default; + _LIBCPP_CONSTEXPR_SINCE_CXX26 __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->__value_)); if (__p) @@ -619,42 +632,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()->__value_; } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__value_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return __get_np()->__value_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { + return pointer_traits::pointer_to(__get_np()->__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 @@ -679,46 +700,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()->__value_; } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__value_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return __get_np()->__value_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { + return pointer_traits::pointer_to(__get_np()->__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; @@ -795,69 +825,83 @@ 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_); } typedef __tree_iterator<_Tp, __node_pointer, difference_type> iterator; typedef __tree_const_iterator<_Tp, __node_pointer, difference_type> const_iterator; - _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); - _LIBCPP_HIDE_FROM_ABI explicit __tree(const allocator_type& __a); - _LIBCPP_HIDE_FROM_ABI __tree(const value_compare& __comp, const allocator_type& __a); - _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 explicit __tree(const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(const value_compare& __comp, const allocator_type& __a); + _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 __tree& operator=(__tree&& __t) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(__tree&& __t, const allocator_type& __a); + _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) || allocator_traits<__node_allocator>::is_always_equal::value)); - _LIBCPP_HIDE_FROM_ABI ~__tree(); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~__tree(); - _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>)); @@ -866,260 +910,318 @@ public: #endif template - _LIBCPP_HIDE_FROM_ABI pair __emplace_unique_key_args(_Key const&, _Args&&... __args); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_unique_key_args(_Key const&, _Args&&... __args); template - _LIBCPP_HIDE_FROM_ABI pair __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&&...); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&&...); template - _LIBCPP_HIDE_FROM_ABI pair __emplace_unique_impl(_Args&&... __args); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __emplace_unique_impl(_Args&&... __args); template - _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_unique_impl(const_iterator __p, _Args&&... __args); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __emplace_hint_unique_impl(const_iterator __p, _Args&&... __args); 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(_Pp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __emplace_unique(_Pp&& __x) { return __emplace_unique_extract_key(std::forward<_Pp>(__x), __can_extract_key<_Pp, key_type>()); } template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI pair __emplace_unique(_First&& __f, _Second&& __s) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_unique(_First&& __f, _Second&& __s) { return __emplace_unique_key_args(__f, std::forward<_First>(__f), std::forward<_Second>(__s)); } template - _LIBCPP_HIDE_FROM_ABI pair __emplace_unique(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __emplace_unique(_Args&&... __args) { return __emplace_unique_impl(std::forward<_Args>(__args)...); } template - _LIBCPP_HIDE_FROM_ABI pair __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) { return __emplace_unique_impl(std::forward<_Pp>(__x)); } template - _LIBCPP_HIDE_FROM_ABI pair __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) { return __emplace_unique_key_args(__x, std::forward<_Pp>(__x)); } template - _LIBCPP_HIDE_FROM_ABI pair __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) { return __emplace_unique_key_args(__x.first, std::forward<_Pp>(__x)); } template - _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_unique(const_iterator __p, _Pp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_hint_unique(const_iterator __p, _Pp&& __x) { return __emplace_hint_unique_extract_key(__p, std::forward<_Pp>(__x), __can_extract_key<_Pp, key_type>()); } template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_unique(const_iterator __p, _First&& __f, _Second&& __s) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __emplace_hint_unique(const_iterator __p, _First&& __f, _Second&& __s) { return __emplace_hint_unique_key_args(__p, __f, std::forward<_First>(__f), std::forward<_Second>(__s)).first; } template - _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_unique(const_iterator __p, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __emplace_hint_unique(const_iterator __p, _Args&&... __args) { return __emplace_hint_unique_impl(__p, std::forward<_Args>(__args)...); } template - _LIBCPP_HIDE_FROM_ABI iterator + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_fail_tag) { return __emplace_hint_unique_impl(__p, std::forward<_Pp>(__x)); } template - _LIBCPP_HIDE_FROM_ABI iterator + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_self_tag) { return __emplace_hint_unique_key_args(__p, __x, std::forward<_Pp>(__x)).first; } template - _LIBCPP_HIDE_FROM_ABI iterator + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_first_tag) { return __emplace_hint_unique_key_args(__p, __x.first, std::forward<_Pp>(__x)).first; } 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 constexpr (integral_constant::value >()) { + __emplace_hint_unique(__p, std::move(__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)); } - _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); - _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&&); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __node_handle_insert_unique(const_iterator, _NodeHandle&&); template - _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_unique(_Tree& __source); + _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&&); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __node_handle_insert_multi(const_iterator, _NodeHandle&&); template - _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_multi(_Tree& __source); + _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& __v); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Key& __v); template - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Key& __v) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Key& __v) const; 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; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type __count_multi(const _Key& __k) const; template - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Key& __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 iterator __lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result); + _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 lower_bound(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Key& __v) const { return __lower_bound(__v, __root(), __end_node()); } template - _LIBCPP_HIDE_FROM_ABI const_iterator + _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 iterator upper_bound(const _Key& __v) { + _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 iterator __upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result); + _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 const_iterator upper_bound(const _Key& __v) const { + _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 + _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 pair __equal_range_unique(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __equal_range_unique(const _Key& __k); template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_unique(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __equal_range_unique(const _Key& __k) const; template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_multi(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_multi(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __equal_range_multi(const _Key& __k) const; typedef __tree_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; - _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 __node_base_pointer& __find_equal(__end_node_pointer& __parent, const _Key& __v); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer& + __find_equal(__end_node_pointer& __parent, const _Key& __v); template - _LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_equal(__end_node_pointer& __parent, const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer& + __find_equal(__end_node_pointer& __parent, const _Key& __v) const { return const_cast<__tree*>(this)->__find_equal(__parent, __v); } template - _LIBCPP_HIDE_FROM_ABI __node_base_pointer& + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer& __find_equal(const_iterator __hint, __end_node_pointer& __parent, __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; + _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX26 void destroy(__node_pointer __nd) _NOEXCEPT; - _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 static void __assign_value(__get_node_value_type_t& __lhs, _From&& __rhs) { + _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 constexpr (integral_constant::value >()) { + // 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 + + __node_allocator& __na = __node_alloc(); + __node_traits::destroy(__na, std::addressof(__lhs)); + + using __node_value_type = __get_node_value_type_t; + __node_value_type __tmp(__rhs.first, __rhs.second); + + __node_traits::construct(__na, std::addressof(__lhs), std::move(__tmp)); + + } 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> @@ -1128,22 +1230,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) @@ -1156,8 +1258,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_; @@ -1170,24 +1272,24 @@ 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 + _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->__value_)); __node_traits::deallocate(__alloc_, __ptr, 1); - (*this)(static_cast<__node_pointer>(__right)); + (*this)(std::__static_fancy_pointer_cast<__node_pointer>(__right)); } }; @@ -1198,7 +1300,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 + _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __copy_construct_tree(__node_pointer __src) { if (!__src) return nullptr; @@ -1206,18 +1308,18 @@ private: __node_holder __new_node = __construct_node(__src->__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; } @@ -1227,7 +1329,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 + _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __copy_assign_tree(__node_pointer __dest, __node_pointer __src) { if (!__src) { destroy(__dest); @@ -1239,24 +1341,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; @@ -1264,19 +1368,20 @@ private: }; template -__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp) _NOEXCEPT_( +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__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(); } template -__tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a) +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a) : __begin_node_(), __node_alloc_(__node_allocator(__a)), __size_(0) { __begin_node_ = __end_node(); } template +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__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(); @@ -1284,16 +1389,16 @@ __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp, const all // 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; @@ -1304,27 +1409,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; @@ -1332,14 +1438,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; @@ -1347,7 +1454,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) { typedef iterator_traits<_ForwardIterator> _ITraits; typedef typename _ITraits::value_type _ItValueType; static_assert( @@ -1367,7 +1475,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) { typedef iterator_traits<_InputIterator> _ITraits; typedef typename _ITraits::value_type _ItValueType; static_assert( @@ -1386,7 +1495,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), @@ -1394,14 +1503,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_)), @@ -1419,7 +1528,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) @@ -1439,7 +1548,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_; @@ -1458,7 +1567,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 { @@ -1479,7 +1588,8 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { } template -__tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t) +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>& +__tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t) _NOEXCEPT_(is_nothrow_move_assignable::value && ((__node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable<__node_allocator>::value) || @@ -1489,18 +1599,18 @@ __tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=( } template -__tree<_Tp, _Compare, _Allocator>::~__tree() { +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::~__tree() { static_assert(is_copy_constructible::value, "Comparator must be copy-constructible."); destroy(__root()); } template -void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT { +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT { (__tree_deleter(__node_alloc_))(__nd); } 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>)) @@ -1525,7 +1635,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(); @@ -1536,7 +1646,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) { @@ -1566,7 +1676,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) { @@ -1582,7 +1692,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_; } } @@ -1599,7 +1709,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 { @@ -1612,7 +1723,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) @@ -1628,7 +1739,7 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co // If __v exists, set parent to node of __v and return reference to node of __v template 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_equal(__end_node_pointer& __parent, const _Key& __v) { __node_pointer __nd = __root(); __node_base_pointer* __nd_ptr = __root_ptr(); @@ -1637,21 +1748,21 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(__end_node_pointer& __parent, co if (value_comp()(__v, __nd->__value_)) { if (__nd->__left_ != nullptr) { __nd_ptr = std::addressof(__nd->__left_); - __nd = static_cast<__node_pointer>(__nd->__left_); + __nd = std::__static_fancy_pointer_cast<__node_pointer>(__nd->__left_); } else { - __parent = static_cast<__end_node_pointer>(__nd); + __parent = std::__static_fancy_pointer_cast<__end_node_pointer>(__nd); return __parent->__left_; } } else if (value_comp()(__nd->__value_, __v)) { if (__nd->__right_ != nullptr) { __nd_ptr = std::addressof(__nd->__right_); - __nd = static_cast<__node_pointer>(__nd->__right_); + __nd = std::__static_fancy_pointer_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_; } } else { - __parent = static_cast<__end_node_pointer>(__nd); + __parent = std::__static_fancy_pointer_cast<__end_node_pointer>(__nd); return *__nd_ptr; } } @@ -1669,7 +1780,8 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(__end_node_pointer& __parent, co // If __v exists, set parent to node of __v and return reference to node of __v template template -typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_equal( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_equal( const_iterator __hint, __end_node_pointer& __parent, __node_base_pointer& __dummy, const _Key& __v) { if (__hint == end() || value_comp()(__v, *__hint)) // check before { @@ -1682,7 +1794,7 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co return __parent->__left_; } else { __parent = __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) @@ -1711,7 +1823,7 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co } 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; @@ -1719,22 +1831,22 @@ 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 -pair::iterator, bool> +pair::iterator, bool> _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) { __end_node_pointer __parent; __node_base_pointer& __child = __find_equal(__parent, __k); - __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>(__args)...); - __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; } @@ -1744,16 +1856,16 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _A template template pair::iterator, bool> -__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args( - const_iterator __p, _Key const& __k, _Args&&... __args) { + _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args( + const_iterator __p, _Key const& __k, _Args&&... __args) { __end_node_pointer __parent; __node_base_pointer __dummy; __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __k); - __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>(__args)...); - __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; } @@ -1762,26 +1874,36 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args( 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)); - __node_traits::construct(__na, std::addressof(__h->__value_), std::forward<_Args>(__args)...); + +#if _LIBCPP_STD_VER >= 26 + if (__libcpp_is_constant_evaluated()) { + // note: construction of subobject of object outside its lifetime is not allowed in a constant expression + std::__construct_at(std::addressof(*__h), std::forward<_Args>(__args)...); + } else +#endif + { + __node_traits::construct(__na, std::addressof(__h->__value_), std::forward<_Args>(__args)...); + } + __h.get_deleter().__value_constructed = true; return __h; } template template -pair::iterator, bool> +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::iterator, bool> __tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; __node_base_pointer& __child = __find_equal(__parent, __h->__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; } @@ -1790,15 +1912,15 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_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_unique_impl(const_iterator __p, _Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; __node_base_pointer __dummy; __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __h->__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 iterator(__r); @@ -1806,7 +1928,7 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_impl(const_iterator __p 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; @@ -1817,17 +1939,17 @@ __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->__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) { __end_node_pointer __parent; __node_base_pointer& __child = __find_equal(__parent, __v); @@ -1835,7 +1957,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, _ bool __inserted = false; if (__child == nullptr) { __assign_value(__nd->__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; } @@ -1843,16 +1965,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->__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->__value_); @@ -1861,21 +1983,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()}; @@ -1893,7 +2015,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(); @@ -1913,7 +2035,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(); @@ -1922,7 +2045,8 @@ _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()); @@ -1930,7 +2054,8 @@ _LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_hand template template -_LIBCPP_HIDE_FROM_ABI void __tree<_Tp, _Compare, _Allocator>::__node_handle_merge_unique(_Tree& __source) { +_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();) { @@ -1947,7 +2072,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree<_Tp, _Compare, _Allocator>::__node_handle_merg 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(); @@ -1961,7 +2086,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(); @@ -1976,7 +2101,8 @@ __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& __source) { +_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();) { @@ -1992,7 +2118,8 @@ _LIBCPP_HIDE_FROM_ABI void __tree<_Tp, _Compare, _Allocator>::__node_handle_merg #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(); @@ -2002,7 +2129,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); @@ -2011,7 +2138,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()) @@ -2022,7 +2149,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; @@ -2033,7 +2160,8 @@ __tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k) { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) { iterator __p = __lower_bound(__v, __root(), __end_node()); if (__p != end() && !value_comp()(__v, *__p)) return __p; @@ -2042,7 +2170,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allo template template -typename __tree<_Tp, _Compare, _Allocator>::const_iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) const { const_iterator __p = __lower_bound(__v, __root(), __end_node()); if (__p != end() && !value_comp()(__v, *__p)) @@ -2052,14 +2180,14 @@ __tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) 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_unique(const _Key& __k) const { __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { - __rt = static_cast<__node_pointer>(__rt->__left_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (value_comp()(__rt->__value_, __k)) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return 1; } @@ -2068,7 +2196,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(); @@ -2088,108 +2216,114 @@ __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator +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->__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( +_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->__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 +_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->__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( +_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->__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) { typedef pair _Pp; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { - __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 (value_comp()(__rt->__value_, __k)) - __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 { typedef pair _Pp; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); while (__rt != nullptr) { if (value_comp()(__k, __rt->__value_)) { - __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 (value_comp()(__rt->__value_, __k)) - __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) { typedef pair _Pp; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); @@ -2208,8 +2342,8 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { 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 { typedef pair _Pp; __end_node_pointer __result = __end_node(); @@ -2228,7 +2362,7 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const { } 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_) { @@ -2243,7 +2377,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/map b/libcxx/include/map index 9f98abef9afe0..06e6867aa9fbc 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -637,33 +637,36 @@ template ::value && !__libcpp_is_final<_Compare>::value> class __map_value_compare : private _Compare { 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) : _Compare() {} - _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) : _Compare(__c) {} - _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return *this; } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const _Compare& key_comp() const _NOEXCEPT { return *this; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _CP& __x, const _CP& __y) const { return static_cast(*this)(__x.first, __y.first); } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _CP& __x, const _Key& __y) const { return static_cast(*this)(__x.first, __y); } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const { + _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX26 operator()(const _Key& __x, const _CP& __y) const { return static_cast(*this)(__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 void swap(__map_value_compare& __y) + _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) { using std::swap; swap(static_cast<_Compare&>(*this), static_cast<_Compare&>(__y)); } # 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 static_cast(*this)(__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 static_cast(*this)(__x.first, __y); } # endif @@ -674,35 +677,43 @@ class __map_value_compare<_Key, _CP, _Compare, false> { _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); } - 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_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 -inline _LIBCPP_HIDE_FROM_ABI void +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(__map_value_compare<_Key, _CP, _Compare, __b>& __x, __map_value_compare<_Key, _CP, _Compare, __b>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); @@ -763,37 +774,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_; } @@ -816,39 +831,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_; } @@ -884,10 +903,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); } }; @@ -923,26 +943,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); @@ -950,7 +971,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(), @@ -962,140 +983,172 @@ 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) noexcept(is_nothrow_move_constructible<__base>::value) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + map(map&& __m) noexcept(is_nothrow_move_constructible<__base>::value) = default; - _LIBCPP_HIDE_FROM_ABI map(map&& __m, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(map&& __m, const allocator_type& __a); - _LIBCPP_HIDE_FROM_ABI map& operator=(map&& __m) noexcept(is_nothrow_move_assignable<__base>::value) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map& + operator=(map&& __m) noexcept(is_nothrow_move_assignable<__base>::value) = 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 - _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 _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; - _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()); } + _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()); + } # 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)...); } 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)); } # 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); } # 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)); } - _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 __f, _InputIterator __l) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __f, _InputIterator __l) { for (const_iterator __e = cend(); __f != __l; ++__f) insert(__e.__i_, *__f); } # 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) { const_iterator __end = cend(); for (auto&& __element : __range) { insert(__end.__i_, std::forward(__element)); @@ -1106,7 +1159,8 @@ 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_key_args( __k, std::piecewise_construct, @@ -1115,7 +1169,8 @@ public: } 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_key_args( __k, std::piecewise_construct, @@ -1124,7 +1179,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_key_args( __h.__i_, @@ -1136,7 +1192,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_key_args( __h.__i_, @@ -1148,7 +1205,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) { iterator __p = lower_bound(__k); if (__p != end() && !key_comp()(__k, __p->first)) { __p->second = std::forward<_Vp>(__v); @@ -1158,7 +1216,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) { iterator __p = lower_bound(__k); if (__p != end() && !key_comp()(__k, __p->first)) { __p->second = std::forward<_Vp>(__v); @@ -1168,7 +1226,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_key_args(__h.__i_, __k, __k, std::forward<_Vp>(__v)); if (!__inserted) @@ -1178,7 +1237,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_key_args(__h.__i_, __k, std::move(__k), std::forward<_Vp>(__v)); @@ -1190,39 +1250,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_); @@ -1241,77 +1307,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 , int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _K2& __k) { return __tree_.find(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const { + _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(); } + _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 bool contains(const _K2& __k) const { + _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(__k); } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__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); + } # if _LIBCPP_STD_VER >= 14 template , int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _K2& __k) { return __tree_.lower_bound(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const { + _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(__k); } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__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 , int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _K2& __k) { return __tree_.upper_bound(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const { + _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 @@ -1384,7 +1468,7 @@ map(initializer_list>, # 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(); @@ -1395,14 +1479,14 @@ 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_key_args(__k, 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) { // TODO investigate this clang-tidy warning. // NOLINTBEGIN(bugprone-use-after-move) return __tree_ @@ -1442,25 +1526,25 @@ _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) { __parent_pointer __parent; __node_base_pointer& __child = __tree_.__find_equal(__parent, __k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__value_.second; + return std::__static_fancy_pointer_cast<__node_pointer>(__child)->__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 { __parent_pointer __parent; __node_base_pointer __child = __tree_.__find_equal(__parent, __k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__value_.second; + return std::__static_fancy_pointer_cast<__node_pointer>(__child)->__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()); } @@ -1468,31 +1552,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); } @@ -1500,7 +1584,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); } @@ -1508,7 +1592,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); @@ -1516,7 +1600,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); } @@ -1712,50 +1796,56 @@ public: # ifndef _LIBCPP_CXX03_LANG template - _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace(_Args&&... __args) { return __tree_.__emplace_multi(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_multi(__p.__i_, std::forward<_Args>(__args)...); } template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator insert(_Pp&& __p) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(_Pp&& __p) { return __tree_.__emplace_multi(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_multi(__pos.__i_, std::forward<_Pp>(__p)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __v) { return __tree_.__emplace_multi(std::move(__v)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(value_type&& __v) { + return __tree_.__emplace_multi(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_multi(__p.__i_, std::move(__v)); } - _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 // _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __v) { return __tree_.__emplace_multi(__v); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const value_type& __v) { + return __tree_.__emplace_multi(__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_multi(__p.__i_, __v); } template - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __f, _InputIterator __l) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __f, _InputIterator __l) { for (const_iterator __e = cend(); __f != __l; ++__f) __tree_.__emplace_hint_multi(__e.__i_, *__f); } # 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) { const_iterator __end = cend(); for (auto&& __element : __range) { __tree_.__emplace_hint_multi(__end.__i_, std::forward(__element)); @@ -1763,131 +1853,156 @@ public: } # endif - _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_multi(__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_multi(__k); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __f, const_iterator __l) { return __tree_.erase(__f.__i_, __l.__i_); } # if _LIBCPP_STD_VER >= 17 - _LIBCPP_HIDE_FROM_ABI iterator insert(node_type&& __nh) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(node_type&& __nh) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to multimap::insert()"); return __tree_.template __node_handle_insert_multi(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 multimap::insert()"); return __tree_.template __node_handle_insert_multi(__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(multimap& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(multimap& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__source.__tree_); } template - _LIBCPP_HIDE_FROM_ABI void merge(multimap&& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(multimap&& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__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"); return __tree_.__node_handle_merge_multi(__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"); return __tree_.__node_handle_merge_multi(__source.__tree_); } # endif - _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __tree_.clear(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() _NOEXCEPT { __tree_.clear(); } - _LIBCPP_HIDE_FROM_ABI void swap(multimap& __m) _NOEXCEPT_(__is_nothrow_swappable_v<__base>) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(multimap& __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 , int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _K2& __k) { return __tree_.find(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const { + _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_multi(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __k) const { + return __tree_.__count_multi(__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(); } + _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 bool contains(const _K2& __k) const { + _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(__k); } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__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); + } # if _LIBCPP_STD_VER >= 14 template , int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _K2& __k) { return __tree_.lower_bound(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const { + _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(__k); } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__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 , int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _K2& __k) { return __tree_.upper_bound(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const { + _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_multi(__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_multi(__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 diff --git a/libcxx/include/version b/libcxx/include/version index aae9277a7dfc6..e2b76e723a3e4 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -74,6 +74,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 @@ -551,6 +552,7 @@ __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 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..961b91dd6accc 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