diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index c7f01e6868395..d7c3c2ba666f1 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 ec23ba9d1e3a1..34f777e606ef0 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -44,6 +44,7 @@ Implemented Papers - P3223R2: Making ``std::istream::ignore`` less surprising (`Github `__) - P3060R3: Add ``std::views::indices(n)`` (`Github `__) - P3168R2: Give ``std::optional`` Range Support (`Github `__) +- P3372R3: ``constexpr map`` (`Github `__) (The paper is partially implemented. ``constexpr map`` is implemented in this release) Improvements and New Features ----------------------------- diff --git a/libcxx/include/__iterator/erase_if_container.h b/libcxx/include/__iterator/erase_if_container.h index 0f87f50cd1c16..8d92d3f1b9dbe 100644 --- a/libcxx/include/__iterator/erase_if_container.h +++ b/libcxx/include/__iterator/erase_if_container.h @@ -22,7 +22,8 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_HIDE_FROM_ABI typename _Container::size_type __libcpp_erase_if_container(_Container& __c, _Predicate& __pred) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename _Container::size_type +__libcpp_erase_if_container(_Container& __c, _Predicate& __pred) { typename _Container::size_type __old_size = __c.size(); const typename _Container::iterator __last = __c.end(); diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle index b20b0c73a0518..f4e617f1b5eee 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,7 @@ struct __map_node_handle_specifics { using key_type = __remove_const_t; using mapped_type = typename _NodeType::__node_value_type::second_type; + // This method is not constexpr as per the standard. _LIBCPP_HIDE_FROM_ABI key_type& key() const { return const_cast(static_cast<_Derived const*>(this)->__ptr_->__get_value().first); } diff --git a/libcxx/include/__tree b/libcxx/include/__tree index d7d074a00f555..667c7af590398 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -28,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> @@ -111,7 +113,7 @@ __root, have a non-null __parent_ field. // Returns: true if __x is a left child of its parent, else false // Precondition: __x != nullptr. template -inline _LIBCPP_HIDE_FROM_ABI bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT { return __x == __x->__parent_->__left_; } @@ -119,7 +121,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT { // __x is a proper subtree, returns the black height (null counts as 1). If // __x is an improper subtree, returns 0. template -unsigned __tree_sub_invariant(_NodePtr __x) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 unsigned __tree_sub_invariant(_NodePtr __x) { if (__x == nullptr) return 1; // parent consistency checked by caller @@ -151,7 +153,7 @@ unsigned __tree_sub_invariant(_NodePtr __x) { // __root == nullptr is a proper tree. Returns true if __root is a proper // red black tree, else returns false. template -_LIBCPP_HIDE_FROM_ABI bool __tree_invariant(_NodePtr __root) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __tree_invariant(_NodePtr __root) { if (__root == nullptr) return true; // check __x->__parent_ consistency @@ -168,7 +170,7 @@ _LIBCPP_HIDE_FROM_ABI bool __tree_invariant(_NodePtr __root) { // Returns: pointer to the left-most node under __x. template -inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null"); while (__x->__left_ != nullptr) __x = __x->__left_; @@ -177,7 +179,7 @@ inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT { // Returns: pointer to the right-most node under __x. template -inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null"); while (__x->__right_ != nullptr) __x = __x->__right_; @@ -186,7 +188,7 @@ inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT { // Returns: pointer to the next in-order node after __x. template -_LIBCPP_HIDE_FROM_ABI _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); if (__x->__right_ != nullptr) return std::__tree_min(__x->__right_); @@ -201,10 +203,10 @@ _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT { // to the actual root of the tree through a __left_ pointer. Incrementing the end() pointer is UB, so we can assume that // never happens. template -inline _LIBCPP_HIDE_FROM_ABI _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); if (__x->__right_ != nullptr) - return static_cast<_EndNodePtr>(std::__tree_min(__x->__right_)); + return std::__static_fancy_pointer_cast<_EndNodePtr>(std::__tree_min(__x->__right_)); while (!std::__tree_is_left_child(__x)) __x = __x->__parent_unsafe(); return static_cast<_EndNodePtr>(__x->__parent_); @@ -213,11 +215,11 @@ inline _LIBCPP_HIDE_FROM_ABI _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEP // Returns: pointer to the previous in-order node before __x. // Note: __x may be the end node. template -inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); if (__x->__left_ != nullptr) return std::__tree_max(__x->__left_); - _NodePtr __xx = static_cast<_NodePtr>(__x); + _NodePtr __xx = std::__static_fancy_pointer_cast<_NodePtr>(__x); while (std::__tree_is_left_child(__xx)) __xx = __xx->__parent_unsafe(); return __xx->__parent_unsafe(); @@ -225,7 +227,7 @@ inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEP // Returns: pointer to a node which has no children template -_LIBCPP_HIDE_FROM_ABI _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); while (true) { if (__x->__left_ != nullptr) { @@ -244,7 +246,7 @@ _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT { // Effects: Makes __x->__right_ the subtree root with __x as its left child // while preserving in-order order. template -_LIBCPP_HIDE_FROM_ABI void __tree_left_rotate(_NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree_left_rotate(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); _LIBCPP_ASSERT_INTERNAL(__x->__right_ != nullptr, "node should have a right child"); _NodePtr __y = __x->__right_; @@ -263,7 +265,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree_left_rotate(_NodePtr __x) _NOEXCEPT { // Effects: Makes __x->__left_ the subtree root with __x as its right child // while preserving in-order order. template -_LIBCPP_HIDE_FROM_ABI void __tree_right_rotate(_NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree_right_rotate(_NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); _LIBCPP_ASSERT_INTERNAL(__x->__left_ != nullptr, "node should have a left child"); _NodePtr __y = __x->__left_; @@ -287,7 +289,8 @@ _LIBCPP_HIDE_FROM_ABI void __tree_right_rotate(_NodePtr __x) _NOEXCEPT { // Postcondition: __tree_invariant(end_node->__left_) == true. end_node->__left_ // may be different than the value passed in as __root. template -_LIBCPP_HIDE_FROM_ABI void __tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void +__tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root of the tree shouldn't be null"); _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Can't attach null node to a leaf"); __x->__is_black_ = __x == __root; @@ -343,7 +346,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree_balance_after_insert(_NodePtr __root, _NodePtr // nor any of its children refer to __z. end_node->__left_ // may be different than the value passed in as __root. template -_LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root node should not be null"); _LIBCPP_ASSERT_INTERNAL(__z != nullptr, "The node to remove should not be null"); _LIBCPP_ASSERT_INTERNAL(std::__tree_invariant(__root), "The tree invariants should hold"); @@ -558,7 +561,7 @@ public: using pointer = _Pointer; pointer __left_; - _LIBCPP_HIDE_FROM_ABI __tree_end_node() _NOEXCEPT : __left_() {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_end_node() _NOEXCEPT : __left_(nullptr) {} }; template @@ -571,11 +574,15 @@ public: __end_node_pointer __parent_; bool __is_black_; - _LIBCPP_HIDE_FROM_ABI pointer __parent_unsafe() const { return static_cast(__parent_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer __parent_unsafe() const { + return std::__static_fancy_pointer_cast(__parent_); + } - _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = static_cast<__end_node_pointer>(__p); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __set_parent(pointer __p) { + __parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__p); + } - _LIBCPP_HIDE_FROM_ABI __tree_node_base() = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_node_base() = default; __tree_node_base(__tree_node_base const&) = delete; __tree_node_base& operator=(__tree_node_base const&) = delete; }; @@ -596,7 +603,7 @@ private: }; public: - _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_value_type& __get_value() { return __value_; } #else private: @@ -607,10 +614,27 @@ public: #endif template - _LIBCPP_HIDE_FROM_ABI explicit __tree_node(_Alloc& __na, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_node(_Alloc& __na, _Args&&... __args) { allocator_traits<_Alloc>::construct(__na, std::addressof(__get_value()), std::forward<_Args>(__args)...); } + +// This line fails with: +// libcxx/test-suite-install/include/c++/v1/__memory/construct_at.h:38:49: note: non-literal type +// 'std::__tree_node, void *>' cannot be used in a constant expression +// +// during constant evaluation as part of P3372 +// on: +// 1. Arm CI which is on clang 19.x (will be fixed in: https://github.com/llvm/llvm-project/issues/161159 ) +// 2. AppleClang is not yet using clang >= 20.x, which has "fixed" this issue +// 3. A few others like FreeBSD/amd64, AArch64, AIX +// FIXME: when AppleClang is based off of clang >= 20.x +// FIXME: when Clang-based CI is using clang >= 20.x +#if (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 2000) || \ + (defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 2000) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~__tree_node() {} +#else ~__tree_node() = delete; +#endif __tree_node(__tree_node const&) = delete; __tree_node& operator=(__tree_node const&) = delete; }; @@ -629,14 +653,15 @@ private: public: bool __value_constructed; - _LIBCPP_HIDE_FROM_ABI __tree_node_destructor(const __tree_node_destructor&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_node_destructor(const __tree_node_destructor&) = default; __tree_node_destructor& operator=(const __tree_node_destructor&) = delete; - _LIBCPP_HIDE_FROM_ABI explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT : __na_(__na), __value_constructed(__val) {} - _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void operator()(pointer __p) _NOEXCEPT { if (__value_constructed) __alloc_traits::destroy(__na_, std::addressof(__p->__get_value())); if (__p) @@ -673,44 +698,50 @@ public: using reference = value_type&; using pointer = __rebind_pointer_t<_NodePtr, value_type>; - _LIBCPP_HIDE_FROM_ABI __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return __get_np()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__get_value()); } - _LIBCPP_HIDE_FROM_ABI __tree_iterator& operator++() { - __ptr_ = std::__tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator& operator++() { + __ptr_ = std::__tree_next_iter<__end_node_pointer>(std::__static_fancy_pointer_cast<__node_base_pointer>(__ptr_)); return *this; } - _LIBCPP_HIDE_FROM_ABI __tree_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator operator++(int) { __tree_iterator __t(*this); ++(*this); return __t; } - _LIBCPP_HIDE_FROM_ABI __tree_iterator& operator--() { - __ptr_ = static_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator& operator--() { + __ptr_ = std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_)); return *this; } - _LIBCPP_HIDE_FROM_ABI __tree_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator operator--(int) { __tree_iterator __t(*this); --(*this); return __t; } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __tree_iterator& __x, const __tree_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const __tree_iterator& __x, const __tree_iterator& __y) { return __x.__ptr_ == __y.__ptr_; } - friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator!=(const __tree_iterator& __x, const __tree_iterator& __y) { return !(__x == __y); } private: - _LIBCPP_HIDE_FROM_ABI explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} - _LIBCPP_HIDE_FROM_ABI explicit __tree_iterator(__end_node_pointer __p) _NOEXCEPT : __ptr_(__p) {} - _LIBCPP_HIDE_FROM_ABI __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_iterator(__node_pointer __p) _NOEXCEPT + : __ptr_(std::__static_fancy_pointer_cast<__end_node_pointer>(__p)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_iterator(__end_node_pointer __p) _NOEXCEPT + : __ptr_(__p) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __get_np() const { + return std::__static_fancy_pointer_cast<__node_pointer>(__ptr_); + } template friend class __tree; template @@ -735,48 +766,55 @@ public: using pointer = __rebind_pointer_t<_NodePtr, const value_type>; using __non_const_iterator _LIBCPP_NODEBUG = __tree_iterator<_Tp, __node_pointer, difference_type>; - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator() _NOEXCEPT : __ptr_(nullptr) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator() _NOEXCEPT : __ptr_(nullptr) {} - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT : __ptr_(__p.__ptr_) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT + : __ptr_(__p.__ptr_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return __get_np()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { return pointer_traits::pointer_to(__get_np()->__get_value()); } - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator& operator++() { - __ptr_ = std::__tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator& operator++() { + __ptr_ = std::__tree_next_iter<__end_node_pointer>(std::__static_fancy_pointer_cast<__node_base_pointer>(__ptr_)); return *this; } - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator operator++(int) { __tree_const_iterator __t(*this); ++(*this); return __t; } - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator& operator--() { - __ptr_ = static_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_)); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator& operator--() { + __ptr_ = std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_)); return *this; } - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_const_iterator operator--(int) { __tree_const_iterator __t(*this); --(*this); return __t; } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y) { return __x.__ptr_ == __y.__ptr_; } - friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y) { return !(__x == __y); } private: - _LIBCPP_HIDE_FROM_ABI explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} - _LIBCPP_HIDE_FROM_ABI explicit __tree_const_iterator(__end_node_pointer __p) _NOEXCEPT : __ptr_(__p) {} - _LIBCPP_HIDE_FROM_ABI __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT + : __ptr_(std::__static_fancy_pointer_cast<__end_node_pointer>(__p)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_const_iterator(__end_node_pointer __p) _NOEXCEPT + : __ptr_(std::__static_fancy_pointer_cast<__end_node_pointer>(__p)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __get_np() const { + return std::__static_fancy_pointer_cast<__node_pointer>(__ptr_); + } template friend class __tree; @@ -852,63 +890,73 @@ private: _LIBCPP_COMPRESSED_PAIR(size_type, __size_, value_compare, __value_comp_); public: - _LIBCPP_HIDE_FROM_ABI __end_node_pointer __end_node() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __end_node_pointer __end_node() _NOEXCEPT { return pointer_traits<__end_node_pointer>::pointer_to(__end_node_); } - _LIBCPP_HIDE_FROM_ABI __end_node_pointer __end_node() const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __end_node_pointer __end_node() const _NOEXCEPT { return pointer_traits<__end_node_pointer>::pointer_to(const_cast<__end_node_t&>(__end_node_)); } - _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __node_alloc_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_allocator& __node_alloc() _NOEXCEPT { + return __node_alloc_; + } private: - _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __node_alloc_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const __node_allocator& __node_alloc() const _NOEXCEPT { + return __node_alloc_; + } public: - _LIBCPP_HIDE_FROM_ABI allocator_type __alloc() const _NOEXCEPT { return allocator_type(__node_alloc()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 allocator_type __alloc() const _NOEXCEPT { + return allocator_type(__node_alloc()); + } - _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; } - _LIBCPP_HIDE_FROM_ABI value_compare& value_comp() _NOEXCEPT { return __value_comp_; } - _LIBCPP_HIDE_FROM_ABI const value_compare& value_comp() const _NOEXCEPT { return __value_comp_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const _NOEXCEPT { return __size_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare& value_comp() _NOEXCEPT { return __value_comp_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const value_compare& value_comp() const _NOEXCEPT { + return __value_comp_; + } public: - _LIBCPP_HIDE_FROM_ABI __node_pointer __root() const _NOEXCEPT { - return static_cast<__node_pointer>(__end_node()->__left_); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __root() const _NOEXCEPT { + return std::__static_fancy_pointer_cast<__node_pointer>(__end_node()->__left_); } - _LIBCPP_HIDE_FROM_ABI __node_base_pointer* __root_ptr() const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer* __root_ptr() const _NOEXCEPT { return std::addressof(__end_node()->__left_); } using iterator = __tree_iterator<_Tp, __node_pointer, difference_type>; using const_iterator = __tree_const_iterator<_Tp, __node_pointer, difference_type>; - _LIBCPP_HIDE_FROM_ABI explicit __tree(const value_compare& __comp) _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree(const value_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_copy_constructible::value) : __size_(0), __value_comp_(__comp) { __begin_node_ = __end_node(); } - _LIBCPP_HIDE_FROM_ABI explicit __tree(const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree(const allocator_type& __a) : __begin_node_(), __node_alloc_(__node_allocator(__a)), __size_(0) { __begin_node_ = __end_node(); } - _LIBCPP_HIDE_FROM_ABI __tree(const value_compare& __comp, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(const value_compare& __comp, const allocator_type& __a) : __begin_node_(), __node_alloc_(__node_allocator(__a)), __size_(0), __value_comp_(__comp) { __begin_node_ = __end_node(); } - _LIBCPP_HIDE_FROM_ABI __tree(const __tree& __t); - _LIBCPP_HIDE_FROM_ABI __tree& operator=(const __tree& __t); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(const __tree& __t); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree& operator=(const __tree& __t); template - _LIBCPP_HIDE_FROM_ABI void __assign_unique(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_unique(_ForwardIterator __first, _ForwardIterator __last); template - _LIBCPP_HIDE_FROM_ABI void __assign_multi(_InputIterator __first, _InputIterator __last); - _LIBCPP_HIDE_FROM_ABI __tree(__tree&& __t) _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_multi(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(__tree&& __t) _NOEXCEPT_( is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible::value); - _LIBCPP_HIDE_FROM_ABI __tree(__tree&& __t, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree(__tree&& __t, const allocator_type& __a); - _LIBCPP_HIDE_FROM_ABI __tree& operator=(__tree&& __t) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree& operator=(__tree&& __t) _NOEXCEPT_(is_nothrow_move_assignable::value && ((__node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable<__node_allocator>::value) || @@ -917,23 +965,27 @@ public: return *this; } - _LIBCPP_HIDE_FROM_ABI ~__tree() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~__tree() { static_assert(is_copy_constructible::value, "Comparator must be copy-constructible."); destroy(__root()); } - _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__begin_node_); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return const_iterator(__begin_node_); } - _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return iterator(__end_node()); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return const_iterator(__end_node()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() _NOEXCEPT { return iterator(__begin_node_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const _NOEXCEPT { + return const_iterator(__begin_node_); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() _NOEXCEPT { return iterator(__end_node()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const _NOEXCEPT { + return const_iterator(__end_node()); + } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const _NOEXCEPT { return std::min(__node_traits::max_size(__node_alloc()), numeric_limits::max()); } - _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI void swap(__tree& __t) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(__tree& __t) #if _LIBCPP_STD_VER <= 11 _NOEXCEPT_(__is_nothrow_swappable_v && (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>)); @@ -942,21 +994,22 @@ public: #endif template - _LIBCPP_HIDE_FROM_ABI iterator __emplace_multi(_Args&&... __args); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_multi(_Args&&... __args); template - _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __emplace_hint_multi(const_iterator __p, _Args&&... __args); template - _LIBCPP_HIDE_FROM_ABI pair __emplace_unique(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __emplace_unique(_Args&&... __args) { return std::__try_key_extraction( [this](const key_type& __key, _Args&&... __args2) { auto [__parent, __child] = __find_equal(__key); - __node_pointer __r = static_cast<__node_pointer>(__child); + __node_pointer __r = std::__static_fancy_pointer_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __node_holder __h = __construct_node(std::forward<_Args>(__args2)...); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); __r = __h.release(); __inserted = true; } @@ -965,10 +1018,10 @@ public: [this](_Args&&... __args2) { __node_holder __h = __construct_node(std::forward<_Args>(__args2)...); auto [__parent, __child] = __find_equal(__h->__get_value()); - __node_pointer __r = static_cast<__node_pointer>(__child); + __node_pointer __r = std::__static_fancy_pointer_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); __r = __h.release(); __inserted = true; } @@ -978,16 +1031,17 @@ public: } template - _LIBCPP_HIDE_FROM_ABI pair __emplace_hint_unique(const_iterator __p, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_hint_unique(const_iterator __p, _Args&&... __args) { return std::__try_key_extraction( [this, __p](const key_type& __key, _Args&&... __args2) { __node_base_pointer __dummy; auto [__parent, __child] = __find_equal(__p, __dummy, __key); - __node_pointer __r = static_cast<__node_pointer>(__child); + __node_pointer __r = std::__static_fancy_pointer_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __node_holder __h = __construct_node(std::forward<_Args>(__args2)...); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); __r = __h.release(); __inserted = true; } @@ -997,9 +1051,9 @@ public: __node_holder __h = __construct_node(std::forward<_Args>(__args2)...); __node_base_pointer __dummy; auto [__parent, __child] = __find_equal(__p, __dummy, __h->__get_value()); - __node_pointer __r = static_cast<__node_pointer>(__child); + __node_pointer __r = std::__static_fancy_pointer_cast<__node_pointer>(__child); if (__child == nullptr) { - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); __r = __h.release(); } return pair(iterator(__r), __child == nullptr); @@ -1007,29 +1061,62 @@ public: std::forward<_Args>(__args)...); } + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_hint_unique__sfinae(true_type, const_iterator __p, _Args&&... __args) { + return __emplace_hint_unique(__p, __args...); + } + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __emplace_hint_unique__sfinae(false_type, const_iterator, _Args&&...) { + // This method body should never be run. It only exists to allow for compilation. See note in + // __insert_unique_from_orphaned_node for more information. + return pair(iterator(__node_pointer()), false); + } + template , int> = 0> - _LIBCPP_HIDE_FROM_ABI void + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insert_unique_from_orphaned_node(const_iterator __p, __get_node_value_type_t<_Tp>&& __value) { - __emplace_hint_unique(__p, const_cast(__value.first), std::move(__value.second)); +#if _LIBCPP_STD_VER >= 26 + if (std::is_constant_evaluated() && std::is_copy_constructible_v) { + // We create a sfinae wrapper method here, because if the __emplace_hint_unique method gets template instantiated + // within __insert_unique_from_orphaned_node, the code will fail to compile where the value is not + // copy_constructible for runtime execution as well; unless we use `if constexpr`. Given the copy-constructible + // code path will be a performance regression, we want to restrict it to only execute during constant evaluation + //, we need to delay the template instantiation + __emplace_hint_unique__sfinae( + integral_constant< bool, std::is_copy_constructible_v >(), + __p, + __value.first, + std::move(__value.second)); + } else +#endif + { + __emplace_hint_unique(__p, const_cast(__value.first), std::move(__value.second)); + } } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node(const_iterator __p, _Tp&& __value) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __insert_unique_from_orphaned_node(const_iterator __p, _Tp&& __value) { __emplace_hint_unique(__p, std::move(__value)); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(const_iterator __p, value_type&& __value) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __insert_multi_from_orphaned_node(const_iterator __p, value_type&& __value) { __emplace_hint_multi(__p, const_cast(__value.first), std::move(__value.second)); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node(const_iterator __p, _Tp&& __value) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __insert_multi_from_orphaned_node(const_iterator __p, _Tp&& __value) { __emplace_hint_multi(__p, std::move(__value)); } template - _LIBCPP_HIDE_FROM_ABI void __insert_range_multi(_InIter __first, _Sent __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insert_range_multi(_InIter __first, _Sent __last) { if (__first == __last) return; @@ -1057,23 +1144,27 @@ public: } } - _LIBCPP_HIDE_FROM_ABI pair __node_assign_unique(const value_type& __v, __node_pointer __dest); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __node_assign_unique(const value_type& __v, __node_pointer __dest); - _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd); - _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(const_iterator __p, __node_pointer __nd); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __node_insert_multi(__node_pointer __nd); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __node_insert_multi(const_iterator __p, __node_pointer __nd); template - _LIBCPP_HIDE_FROM_ABI void __insert_range_unique(_InIter __first, _Sent __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insert_range_unique(_InIter __first, _Sent __last) { if (__first == __last) return; if (__root() == nullptr) { - __insert_node_at( - __end_node(), __end_node()->__left_, static_cast<__node_base_pointer>(__construct_node(*__first).release())); + __insert_node_at(__end_node(), + __end_node()->__left_, + std::__static_fancy_pointer_cast<__node_base_pointer>(__construct_node(*__first).release())); ++__first; } - auto __max_node = static_cast<__node_pointer>(std::__tree_max(static_cast<__node_base_pointer>(__root()))); + auto __max_node = std::__static_fancy_pointer_cast<__node_pointer>( + std::__tree_max(std::__static_fancy_pointer_cast<__node_base_pointer>(__root()))); using __reference = decltype(*__first); @@ -1082,29 +1173,31 @@ public: [this, &__max_node](const key_type& __key, __reference&& __val) { if (value_comp()(__max_node->__get_value(), __key)) { // __key > __max_node __node_holder __nd = __construct_node(std::forward<__reference>(__val)); - __insert_node_at(static_cast<__end_node_pointer>(__max_node), + __insert_node_at(std::__static_fancy_pointer_cast<__end_node_pointer>(__max_node), __max_node->__right_, - static_cast<__node_base_pointer>(__nd.get())); + std::__static_fancy_pointer_cast<__node_base_pointer>(__nd.get())); __max_node = __nd.release(); } else { auto [__parent, __child] = __find_equal(__key); if (__child == nullptr) { __node_holder __nd = __construct_node(std::forward<__reference>(__val)); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd.release())); + __insert_node_at( + __parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd.release())); } } }, [this, &__max_node](__reference&& __val) { __node_holder __nd = __construct_node(std::forward<__reference>(__val)); if (value_comp()(__max_node->__get_value(), __nd->__get_value())) { // __node > __max_node - __insert_node_at(static_cast<__end_node_pointer>(__max_node), + __insert_node_at(std::__static_fancy_pointer_cast<__end_node_pointer>(__max_node), __max_node->__right_, - static_cast<__node_base_pointer>(__nd.get())); + std::__static_fancy_pointer_cast<__node_base_pointer>(__nd.get())); __max_node = __nd.release(); } else { auto [__parent, __child] = __find_equal(__nd->__get_value()); if (__child == nullptr) { - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd.release())); + __insert_node_at( + __parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd.release())); } } }, @@ -1112,62 +1205,65 @@ public: } } - _LIBCPP_HIDE_FROM_ABI iterator __remove_node_pointer(__node_pointer) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __remove_node_pointer(__node_pointer) _NOEXCEPT; #if _LIBCPP_STD_VER >= 17 template - _LIBCPP_HIDE_FROM_ABI _InsertReturnType __node_handle_insert_unique(_NodeHandle&&); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _InsertReturnType __node_handle_insert_unique(_NodeHandle&&); template - _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_unique(const_iterator, _NodeHandle&&); + _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& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Key& __key) { auto [__, __match] = __find_equal(__key); if (__match == nullptr) return end(); - return iterator(static_cast<__node_pointer>(__match)); + return iterator(std::__static_fancy_pointer_cast<__node_pointer>(__match)); } template - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Key& __key) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Key& __key) const { auto [__, __match] = __find_equal(__key); if (__match == nullptr) return end(); - return const_iterator(static_cast<__node_pointer>(__match)); + return const_iterator(std::__static_fancy_pointer_cast<__node_pointer>(__match)); } template - _LIBCPP_HIDE_FROM_ABI size_type __count_unique(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type __count_unique(const _Key& __k) const; template - _LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type __count_multi(const _Key& __k) const; template - _LIBCPP_HIDE_FROM_ABI __end_node_pointer __lower_upper_bound_unique_impl(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __end_node_pointer + __lower_upper_bound_unique_impl(const _Key& __v) const { auto __rt = __root(); auto __result = __end_node(); auto __comp = __lazy_synth_three_way_comparator<_Compare, _Key, value_type>(value_comp()); @@ -1175,156 +1271,209 @@ public: auto __comp_res = __comp(__v, __rt->__get_value()); if (__comp_res.__less()) { - __result = static_cast<__end_node_pointer>(__rt); - __rt = static_cast<__node_pointer>(__rt->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__rt); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) { - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); } else if _LIBCPP_CONSTEXPR (_LowerBound) { - return static_cast<__end_node_pointer>(__rt); + return std::__static_fancy_pointer_cast<__end_node_pointer>(__rt); } else { - return __rt->__right_ ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) : __result; + return __rt->__right_ ? std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) + : __result; } } return __result; } template - _LIBCPP_HIDE_FROM_ABI iterator __lower_bound_unique(const _Key& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __lower_bound_unique(const _Key& __v) { return iterator(__lower_upper_bound_unique_impl(__v)); } template - _LIBCPP_HIDE_FROM_ABI const_iterator __lower_bound_unique(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator __lower_bound_unique(const _Key& __v) const { return const_iterator(__lower_upper_bound_unique_impl(__v)); } template - _LIBCPP_HIDE_FROM_ABI iterator __upper_bound_unique(const _Key& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __upper_bound_unique(const _Key& __v) { return iterator(__lower_upper_bound_unique_impl(__v)); } template - _LIBCPP_HIDE_FROM_ABI const_iterator __upper_bound_unique(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator __upper_bound_unique(const _Key& __v) const { return iterator(__lower_upper_bound_unique_impl(__v)); } private: template - _LIBCPP_HIDE_FROM_ABI iterator + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __lower_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result); template - _LIBCPP_HIDE_FROM_ABI const_iterator + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator __lower_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const; public: template - _LIBCPP_HIDE_FROM_ABI iterator __lower_bound_multi(const _Key& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __lower_bound_multi(const _Key& __v) { return __lower_bound_multi(__v, __root(), __end_node()); } template - _LIBCPP_HIDE_FROM_ABI const_iterator __lower_bound_multi(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator __lower_bound_multi(const _Key& __v) const { return __lower_bound_multi(__v, __root(), __end_node()); } template - _LIBCPP_HIDE_FROM_ABI iterator __upper_bound_multi(const _Key& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __upper_bound_multi(const _Key& __v) { return __upper_bound_multi(__v, __root(), __end_node()); } template - _LIBCPP_HIDE_FROM_ABI const_iterator __upper_bound_multi(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator __upper_bound_multi(const _Key& __v) const { return __upper_bound_multi(__v, __root(), __end_node()); } private: template - _LIBCPP_HIDE_FROM_ABI iterator + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __upper_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result); template - _LIBCPP_HIDE_FROM_ABI const_iterator + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator __upper_bound_multi(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const; public: template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_unique(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __equal_range_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; using _Dp _LIBCPP_NODEBUG = __tree_node_destructor<__node_allocator>; using __node_holder _LIBCPP_NODEBUG = unique_ptr<__node, _Dp>; - _LIBCPP_HIDE_FROM_ABI __node_holder remove(const_iterator __p) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_holder remove(const_iterator __p) _NOEXCEPT; // FIXME: Make this function const qualified. Unfortunately doing so // breaks existing code which uses non-const callable comparators. template - _LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> __find_equal(const _Key& __v); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<__end_node_pointer, __node_base_pointer&> + __find_equal(const _Key& __v); template - _LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> __find_equal(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<__end_node_pointer, __node_base_pointer&> + __find_equal(const _Key& __v) const { return const_cast<__tree*>(this)->__find_equal(__v); } template - _LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<__end_node_pointer, __node_base_pointer&> __find_equal(const_iterator __hint, __node_base_pointer& __dummy, const _Key& __v); - _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __tree& __t) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __copy_assign_alloc(const __tree& __t) { __copy_assign_alloc(__t, integral_constant()); } - _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __tree& __t, true_type) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __copy_assign_alloc(const __tree& __t, true_type) { if (__node_alloc() != __t.__node_alloc()) clear(); __node_alloc() = __t.__node_alloc(); } - _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __tree&, false_type) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __copy_assign_alloc(const __tree&, false_type) {} private: - _LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_leaf_low(__end_node_pointer& __parent, const value_type& __v); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer& + __find_leaf_low(__end_node_pointer& __parent, const value_type& __v); - _LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_leaf_high(__end_node_pointer& __parent, const value_type& __v); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer& + __find_leaf_high(__end_node_pointer& __parent, const value_type& __v); - _LIBCPP_HIDE_FROM_ABI __node_base_pointer& + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_base_pointer& __find_leaf(const_iterator __hint, __end_node_pointer& __parent, const value_type& __v); template - _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&&... __args); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_holder __construct_node(_Args&&... __args); // TODO: Make this _LIBCPP_HIDE_FROM_ABI - _LIBCPP_HIDDEN void destroy(__node_pointer __nd) _NOEXCEPT { (__tree_deleter(__node_alloc_))(__nd); } + _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX26 void destroy(__node_pointer __nd) _NOEXCEPT { + (__tree_deleter(__node_alloc_))(__nd); + } - _LIBCPP_HIDE_FROM_ABI void __move_assign(__tree& __t, false_type); - _LIBCPP_HIDE_FROM_ABI void __move_assign(__tree& __t, true_type) _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign(__tree& __t, false_type); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign(__tree& __t, true_type) _NOEXCEPT_( is_nothrow_move_assignable::value&& is_nothrow_move_assignable<__node_allocator>::value); - _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree& __t) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign_alloc(__tree& __t) _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<__node_allocator>::value) { __move_assign_alloc(__t, integral_constant()); } - _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree& __t, true_type) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign_alloc(__tree& __t, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) { __node_alloc() = std::move(__t.__node_alloc()); } - _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {} template , int> = 0> - _LIBCPP_HIDE_FROM_ABI static void __assign_value(__get_node_value_type_t& __lhs, _From&& __rhs) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_value__sfinae(true_type, __get_node_value_type_t& __lhs, _From&& __rhs) { + __node_allocator& __na = __node_alloc(); + __node_traits::destroy(__na, std::addressof(__lhs)); + __node_traits::construct(__na, std::addressof(__lhs), __rhs.first, __rhs.second); + } + + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_value__sfinae(false_type, __get_node_value_type_t&, _From&&) { + // This method body should never be run. It only exists to allow for compilation. See note in __assign_value for + // more information + } + + template , int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + __assign_value(__get_node_value_type_t& __lhs, _From&& __rhs) { using __key_type = __remove_const_t; - // This is technically UB, since the object was constructed as `const`. - // Clang doesn't optimize on this currently though. - const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first); - __lhs.second = std::forward<_From>(__rhs).second; +#if _LIBCPP_STD_VER >= 26 + + if (std::is_constant_evaluated() && std::is_copy_constructible_v) { + // we use copy, and not "move" as the constraint + // because we can NOT move from `const key_type`, which is how `value_type` is defined + // atleast for map + // typedef pair value_type; + // so we must copy it + + // const_cast is not allowed at constexpr time. + // we get around this by deleting __lhs and creating a new node in-place + // to avoid const_cast __lhs.first + + // We create a sfinae wrapper method here, because if the body of the true_type overload for + // __assign_value__sfinae() gets template instantiated within __assign_value, the code will fail to compile where + // the value is not copy_constructible for runtime execution as well; unless we use `if constexpr`. Given the + // copy-constructible code path will be a performance regression, we want to restrict it to only execute during + // constant evaluation + //, we need to delay the template instantiation + + __assign_value__sfinae(std::integral_constant>(), + std::forward(__lhs), + std::forward(__rhs)); + + } else +#endif + { + // This is technically UB, since the object was constructed as `const`. + // Clang doesn't optimize on this currently though. + const_cast<__key_type&>(__lhs.first) = const_cast<__copy_cvref_t<_From, __key_type>&&>(__rhs.first); + __lhs.second = std::forward<_From>(__rhs).second; + } } template , int> = 0> @@ -1333,22 +1482,22 @@ private: } struct _DetachedTreeCache { - _LIBCPP_HIDE_FROM_ABI explicit _DetachedTreeCache(__tree* __t) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit _DetachedTreeCache(__tree* __t) _NOEXCEPT : __t_(__t), __cache_root_(__detach_from_tree(__t)) { __advance(); } - _LIBCPP_HIDE_FROM_ABI __node_pointer __get() const _NOEXCEPT { return __cache_elem_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __get() const _NOEXCEPT { return __cache_elem_; } - _LIBCPP_HIDE_FROM_ABI void __advance() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __advance() _NOEXCEPT { __cache_elem_ = __cache_root_; if (__cache_root_) { __cache_root_ = __detach_next(__cache_root_); } } - _LIBCPP_HIDE_FROM_ABI ~_DetachedTreeCache() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~_DetachedTreeCache() { __t_->destroy(__cache_elem_); if (__cache_root_) { while (__cache_root_->__parent_ != nullptr) @@ -1361,8 +1510,8 @@ private: _DetachedTreeCache& operator=(_DetachedTreeCache const&) = delete; private: - _LIBCPP_HIDE_FROM_ABI static __node_pointer __detach_from_tree(__tree* __t) _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI static __node_pointer __detach_next(__node_pointer) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static __node_pointer __detach_from_tree(__tree* __t) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static __node_pointer __detach_next(__node_pointer) _NOEXCEPT; __tree* __t_; __node_pointer __cache_root_; @@ -1375,24 +1524,23 @@ private: public: using pointer = __node_pointer; - _LIBCPP_HIDE_FROM_ABI __tree_deleter(__node_allocator& __alloc) : __alloc_(__alloc) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_deleter(__node_allocator& __alloc) : __alloc_(__alloc) {} #ifdef _LIBCPP_COMPILER_CLANG_BASED // FIXME: GCC complains about not being able to always_inline a recursive function _LIBCPP_HIDE_FROM_ABI #endif - void - operator()(__node_pointer __ptr) { + _LIBCPP_CONSTEXPR_SINCE_CXX26 void operator()(__node_pointer __ptr) { if (!__ptr) return; - (*this)(static_cast<__node_pointer>(__ptr->__left_)); + (*this)(std::__static_fancy_pointer_cast<__node_pointer>(__ptr->__left_)); auto __right = __ptr->__right_; __node_traits::destroy(__alloc_, std::addressof(__ptr->__get_value())); __node_traits::deallocate(__alloc_, __ptr, 1); - (*this)(static_cast<__node_pointer>(__right)); + (*this)(std::__static_fancy_pointer_cast<__node_pointer>(__right)); } }; @@ -1403,26 +1551,25 @@ private: #ifdef _LIBCPP_COMPILER_CLANG_BASED // FIXME: GCC complains about not being able to always_inline a recursive function _LIBCPP_HIDE_FROM_ABI #endif - __node_pointer - __copy_construct_tree(__node_pointer __src) { + _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __copy_construct_tree(__node_pointer __src) { if (!__src) return nullptr; __node_holder __new_node = __construct_node(__src->__get_value()); unique_ptr<__node, __tree_deleter> __left( - __copy_construct_tree(static_cast<__node_pointer>(__src->__left_)), __node_alloc_); - __node_pointer __right = __copy_construct_tree(static_cast<__node_pointer>(__src->__right_)); + __copy_construct_tree(std::__static_fancy_pointer_cast<__node_pointer>(__src->__left_)), __node_alloc_); + __node_pointer __right = __copy_construct_tree(std::__static_fancy_pointer_cast<__node_pointer>(__src->__right_)); __node_pointer __new_node_ptr = __new_node.release(); __new_node_ptr->__is_black_ = __src->__is_black_; - __new_node_ptr->__left_ = static_cast<__node_base_pointer>(__left.release()); - __new_node_ptr->__right_ = static_cast<__node_base_pointer>(__right); + __new_node_ptr->__left_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__left.release()); + __new_node_ptr->__right_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__right); if (__new_node_ptr->__left_) - __new_node_ptr->__left_->__parent_ = static_cast<__end_node_pointer>(__new_node_ptr); + __new_node_ptr->__left_->__parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__new_node_ptr); if (__new_node_ptr->__right_) - __new_node_ptr->__right_->__parent_ = static_cast<__end_node_pointer>(__new_node_ptr); + __new_node_ptr->__right_->__parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__new_node_ptr); return __new_node_ptr; } @@ -1432,8 +1579,7 @@ private: #ifdef _LIBCPP_COMPILER_CLANG_BASED // FIXME: GCC complains about not being able to always_inline a recursive function _LIBCPP_HIDE_FROM_ABI #endif - __node_pointer - __copy_assign_tree(__node_pointer __dest, __node_pointer __src) { + _LIBCPP_CONSTEXPR_SINCE_CXX26 __node_pointer __copy_assign_tree(__node_pointer __dest, __node_pointer __src) { if (!__src) { destroy(__dest); return nullptr; @@ -1444,24 +1590,26 @@ private: // If we already have a left node in the destination tree, reuse it and copy-assign recursively if (__dest->__left_) { - __dest->__left_ = static_cast<__node_base_pointer>(__copy_assign_tree( - static_cast<__node_pointer>(__dest->__left_), static_cast<__node_pointer>(__src->__left_))); + __dest->__left_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_assign_tree( + std::__static_fancy_pointer_cast<__node_pointer>(__dest->__left_), + std::__static_fancy_pointer_cast<__node_pointer>(__src->__left_))); // Otherwise, we must create new nodes; copy-construct from here on } else if (__src->__left_) { - auto __new_left = __copy_construct_tree(static_cast<__node_pointer>(__src->__left_)); - __dest->__left_ = static_cast<__node_base_pointer>(__new_left); - __new_left->__parent_ = static_cast<__end_node_pointer>(__dest); + auto __new_left = __copy_construct_tree(std::__static_fancy_pointer_cast<__node_pointer>(__src->__left_)); + __dest->__left_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__new_left); + __new_left->__parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__dest); } // Identical to the left case above, just for the right nodes if (__dest->__right_) { - __dest->__right_ = static_cast<__node_base_pointer>(__copy_assign_tree( - static_cast<__node_pointer>(__dest->__right_), static_cast<__node_pointer>(__src->__right_))); + __dest->__right_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_assign_tree( + std::__static_fancy_pointer_cast<__node_pointer>(__dest->__right_), + std::__static_fancy_pointer_cast<__node_pointer>(__src->__right_))); } else if (__src->__right_) { - auto __new_right = __copy_construct_tree(static_cast<__node_pointer>(__src->__right_)); - __dest->__right_ = static_cast<__node_base_pointer>(__new_right); - __new_right->__parent_ = static_cast<__end_node_pointer>(__dest); + auto __new_right = __copy_construct_tree(std::__static_fancy_pointer_cast<__node_pointer>(__src->__right_)); + __dest->__right_ = std::__static_fancy_pointer_cast<__node_base_pointer>(__new_right); + __new_right->__parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__dest); } return __dest; @@ -1470,16 +1618,16 @@ private: // Precondition: __size_ != 0 template -typename __tree<_Tp, _Compare, _Allocator>::__node_pointer +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_pointer __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_from_tree(__tree* __t) _NOEXCEPT { - __node_pointer __cache = static_cast<__node_pointer>(__t->__begin_node_); + __node_pointer __cache = std::__static_fancy_pointer_cast<__node_pointer>(__t->__begin_node_); __t->__begin_node_ = __t->__end_node(); __t->__end_node()->__left_->__parent_ = nullptr; __t->__end_node()->__left_ = nullptr; __t->__size_ = 0; // __cache->__left_ == nullptr if (__cache->__right_ != nullptr) - __cache = static_cast<__node_pointer>(__cache->__right_); + __cache = std::__static_fancy_pointer_cast<__node_pointer>(__cache->__right_); // __cache->__left_ == nullptr // __cache->__right_ == nullptr return __cache; @@ -1490,27 +1638,28 @@ __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_from_tree(__tree // __cache->right_ == nullptr // This is no longer a red-black tree template -typename __tree<_Tp, _Compare, _Allocator>::__node_pointer +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_pointer __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_next(__node_pointer __cache) _NOEXCEPT { if (__cache->__parent_ == nullptr) return nullptr; - if (std::__tree_is_left_child(static_cast<__node_base_pointer>(__cache))) { + if (std::__tree_is_left_child(std::__static_fancy_pointer_cast<__node_base_pointer>(__cache))) { __cache->__parent_->__left_ = nullptr; - __cache = static_cast<__node_pointer>(__cache->__parent_); + __cache = std::__static_fancy_pointer_cast<__node_pointer>(__cache->__parent_); if (__cache->__right_ == nullptr) return __cache; return static_cast<__node_pointer>(std::__tree_leaf(__cache->__right_)); } // __cache is right child __cache->__parent_unsafe()->__right_ = nullptr; - __cache = static_cast<__node_pointer>(__cache->__parent_); + __cache = std::__static_fancy_pointer_cast<__node_pointer>(__cache->__parent_); if (__cache->__left_ == nullptr) return __cache; return static_cast<__node_pointer>(std::__tree_leaf(__cache->__left_)); } template -__tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>& +__tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t) { if (this == std::addressof(__t)) return *this; @@ -1518,14 +1667,15 @@ __tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=( __copy_assign_alloc(__t); if (__size_ != 0) { - *__root_ptr() = static_cast<__node_base_pointer>(__copy_assign_tree(__root(), __t.__root())); + *__root_ptr() = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_assign_tree(__root(), __t.__root())); } else { - *__root_ptr() = static_cast<__node_base_pointer>(__copy_construct_tree(__t.__root())); + *__root_ptr() = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_construct_tree(__t.__root())); if (__root()) __root()->__parent_ = __end_node(); } - __begin_node_ = - __end_node()->__left_ ? static_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_)) : __end_node(); + __begin_node_ = __end_node()->__left_ + ? std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_)) + : __end_node(); __size_ = __t.size(); return *this; @@ -1533,7 +1683,8 @@ __tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator=( template template -void __tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first, _ForwardIterator __last) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 void +__tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first, _ForwardIterator __last) { using _ITraits = iterator_traits<_ForwardIterator>; using _ItValueType = typename _ITraits::value_type; static_assert( @@ -1553,7 +1704,8 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first template template -void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 void +__tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last) { using _ITraits = iterator_traits<_InputIterator>; using _ItValueType = typename _ITraits::value_type; static_assert( @@ -1572,7 +1724,7 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _ } template -__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) : __begin_node_(__end_node()), __node_alloc_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())), __size_(0), @@ -1580,14 +1732,14 @@ __tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) if (__t.size() == 0) return; - *__root_ptr() = static_cast<__node_base_pointer>(__copy_construct_tree(__t.__root())); + *__root_ptr() = std::__static_fancy_pointer_cast<__node_base_pointer>(__copy_construct_tree(__t.__root())); __root()->__parent_ = __end_node(); - __begin_node_ = static_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_)); + __begin_node_ = std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__end_node()->__left_)); __size_ = __t.size(); } template -__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_( +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_( is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible::value) : __begin_node_(std::move(__t.__begin_node_)), __end_node_(std::move(__t.__end_node_)), @@ -1605,7 +1757,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) _NOEXCEPT_( } template -__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a) +_LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a) : __node_alloc_(__node_allocator(__a)), __size_(0), __value_comp_(std::move(__t.value_comp())) { if (__a == __t.__alloc()) { if (__t.__size_ == 0) @@ -1625,7 +1777,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __ } template -void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value&& is_nothrow_move_assignable<__node_allocator>::value) { destroy(static_cast<__node_pointer>(__end_node()->__left_)); __begin_node_ = __t.__begin_node_; @@ -1644,7 +1796,7 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) } template -void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { if (__node_alloc() == __t.__node_alloc()) __move_assign(__t, true_type()); else { @@ -1665,7 +1817,7 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) { } template -void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) #if _LIBCPP_STD_VER <= 11 _NOEXCEPT_(__is_nothrow_swappable_v && (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>)) @@ -1690,7 +1842,7 @@ void __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) } template -void __tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT { +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT { destroy(__root()); __size_ = 0; __begin_node_ = __end_node(); @@ -1701,7 +1853,7 @@ void __tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT { // Set __parent to parent of null leaf // Return reference to null leaf template -typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__end_node_pointer& __parent, const value_type& __v) { __node_pointer __nd = __root(); if (__nd != nullptr) { @@ -1731,7 +1883,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__end_node_pointer& __parent, // Set __parent to parent of null leaf // Return reference to null leaf template -typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__end_node_pointer& __parent, const value_type& __v) { __node_pointer __nd = __root(); if (__nd != nullptr) { @@ -1747,7 +1899,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__end_node_pointer& __parent if (__nd->__right_ != nullptr) __nd = static_cast<__node_pointer>(__nd->__right_); else { - __parent = static_cast<__end_node_pointer>(__nd); + __parent = std::__static_fancy_pointer_cast<__end_node_pointer>(__nd); return __nd->__right_; } } @@ -1764,7 +1916,8 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__end_node_pointer& __parent // Set __parent to parent of null leaf // Return reference to null leaf template -typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_leaf( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_leaf( const_iterator __hint, __end_node_pointer& __parent, const value_type& __v) { if (__hint == end() || !value_comp()(*__hint, __v)) // check before { @@ -1777,7 +1930,7 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co return __parent->__left_; } else { __parent = static_cast<__end_node_pointer>(__prior.__ptr_); - return static_cast<__node_base_pointer>(__prior.__ptr_)->__right_; + return std::__static_fancy_pointer_cast<__node_base_pointer>(__prior.__ptr_)->__right_; } } // __v < *prev(__hint) @@ -1792,8 +1945,9 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co // If __v doesn't exist, return the parent of the null leaf and a reference to the pointer to the null leaf. template template -_LIBCPP_HIDE_FROM_ABI pair::__end_node_pointer, - typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::__end_node_pointer, + typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> __tree<_Tp, _Compare, _Allocator>::__find_equal(const _Key& __v) { using _Pair = pair<__end_node_pointer, __node_base_pointer&>; @@ -1813,18 +1967,18 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const _Key& __v) { if (__comp_res.__less()) { if (__nd->__left_ == nullptr) - return _Pair(static_cast<__end_node_pointer>(__nd), __nd->__left_); + return _Pair(std::__static_fancy_pointer_cast<__end_node_pointer>(__nd), __nd->__left_); __node_ptr = std::addressof(__nd->__left_); - __nd = static_cast<__node_pointer>(__nd->__left_); + __nd = std::__static_fancy_pointer_cast<__node_pointer>(__nd->__left_); } else if (__comp_res.__greater()) { if (__nd->__right_ == nullptr) - return _Pair(static_cast<__end_node_pointer>(__nd), __nd->__right_); + return _Pair(std::__static_fancy_pointer_cast<__end_node_pointer>(__nd), __nd->__right_); __node_ptr = std::addressof(__nd->__right_); - __nd = static_cast<__node_pointer>(__nd->__right_); + __nd = std::__static_fancy_pointer_cast<__node_pointer>(__nd->__right_); } else { - return _Pair(static_cast<__end_node_pointer>(__nd), *__node_ptr); + return _Pair(std::__static_fancy_pointer_cast<__end_node_pointer>(__nd), *__node_ptr); } } } @@ -1837,8 +1991,9 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const _Key& __v) { // If __v doesn't exist, return the parent of the null leaf and a reference to the pointer to the null leaf. template template -_LIBCPP_HIDE_FROM_ABI pair::__end_node_pointer, - typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::__end_node_pointer, + typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_base_pointer& __dummy, const _Key& __v) { using _Pair = pair<__end_node_pointer, __node_base_pointer&>; @@ -1849,7 +2004,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_ba // *prev(__hint) < __v < *__hint if (__hint.__ptr_->__left_ == nullptr) return _Pair(__hint.__ptr_, __hint.__ptr_->__left_); - return _Pair(__prior.__ptr_, static_cast<__node_pointer>(__prior.__ptr_)->__right_); + return _Pair(__prior.__ptr_, std::__static_fancy_pointer_cast<__node_pointer>(__prior.__ptr_)->__right_); } // __v <= *prev(__hint) return __find_equal(__v); @@ -1874,7 +2029,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_ba } template -void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( __end_node_pointer __parent, __node_base_pointer& __child, __node_base_pointer __new_node) _NOEXCEPT { __new_node->__left_ = nullptr; __new_node->__right_ = nullptr; @@ -1882,14 +2037,14 @@ void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( // __new_node->__is_black_ is initialized in __tree_balance_after_insert __child = __new_node; if (__begin_node_->__left_ != nullptr) - __begin_node_ = static_cast<__end_node_pointer>(__begin_node_->__left_); + __begin_node_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__begin_node_->__left_); std::__tree_balance_after_insert(__end_node()->__left_, __child); ++__size_; } template template -typename __tree<_Tp, _Compare, _Allocator>::__node_holder +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); @@ -1900,7 +2055,7 @@ __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator +typename __tree<_Tp, _Compare, _Allocator>::iterator _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; @@ -1911,24 +2066,24 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator +typename __tree<_Tp, _Compare, _Allocator>::iterator _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, _Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__get_value()); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); return iterator(static_cast<__node_pointer>(__h.release())); } template -pair::iterator, bool> +pair::iterator, bool> _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, __node_pointer __nd) { auto [__parent, __child] = __find_equal(__v); __node_pointer __r = static_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __assign_value(__nd->__get_value(), __v); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd)); __r = __nd; __inserted = true; } @@ -1936,16 +2091,16 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, _ } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd) { __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__get_value()); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd)); return iterator(__nd); } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, __node_pointer __nd) { __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__get_value()); @@ -1954,21 +2109,21 @@ __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, __nod } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr) _NOEXCEPT { iterator __r(__ptr); ++__r; if (__begin_node_ == __ptr) __begin_node_ = __r.__ptr_; --__size_; - std::__tree_remove(__end_node()->__left_, static_cast<__node_base_pointer>(__ptr)); + std::__tree_remove(__end_node()->__left_, std::__static_fancy_pointer_cast<__node_base_pointer>(__ptr)); return __r; } #if _LIBCPP_STD_VER >= 17 template template -_LIBCPP_HIDE_FROM_ABI _InsertReturnType +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _InsertReturnType __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __nh) { if (__nh.empty()) return _InsertReturnType{end(), false, _NodeHandle()}; @@ -1985,7 +2140,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __n template template -_LIBCPP_HIDE_FROM_ABI typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __hint, _NodeHandle&& __nh) { if (__nh.empty()) return end(); @@ -2004,7 +2159,8 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __ template template -_LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodeHandle +__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key) { iterator __it = find(__key); if (__it == end()) return _NodeHandle(); @@ -2013,7 +2169,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()); @@ -2021,7 +2178,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();) { @@ -2037,7 +2195,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(); @@ -2051,7 +2209,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(); @@ -2066,7 +2224,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();) { @@ -2082,7 +2241,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(); @@ -2092,7 +2252,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); @@ -2101,7 +2261,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()) @@ -2112,7 +2272,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; @@ -2123,16 +2283,16 @@ __tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k) { template template -typename __tree<_Tp, _Compare, _Allocator>::size_type +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const { __node_pointer __rt = __root(); auto __comp = __lazy_synth_three_way_comparator(value_comp()); while (__rt != nullptr) { auto __comp_res = __comp(__k, __rt->__get_value()); if (__comp_res.__less()) { - __rt = static_cast<__node_pointer>(__rt->__left_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return 1; } @@ -2141,7 +2301,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(); @@ -2163,64 +2323,69 @@ __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__lower_bound_multi( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__lower_bound_multi( const _Key& __v, __node_pointer __root, __end_node_pointer __result) { while (__root != nullptr) { if (!value_comp()(__root->__get_value(), __v)) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return iterator(__result); } template template -typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::__lower_bound_multi( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::const_iterator +__tree<_Tp, _Compare, _Allocator>::__lower_bound_multi( const _Key& __v, __node_pointer __root, __end_node_pointer __result) const { while (__root != nullptr) { if (!value_comp()(__root->__get_value(), __v)) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return const_iterator(__result); } template template -typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound_multi( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__upper_bound_multi( const _Key& __v, __node_pointer __root, __end_node_pointer __result) { while (__root != nullptr) { if (value_comp()(__v, __root->__get_value())) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return iterator(__result); } template template -typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound_multi( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::const_iterator +__tree<_Tp, _Compare, _Allocator>::__upper_bound_multi( const _Key& __v, __node_pointer __root, __end_node_pointer __result) const { while (__root != nullptr) { if (value_comp()(__v, __root->__get_value())) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return const_iterator(__result); } template template -pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> -__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 + pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> + __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { using _Pp = pair; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); @@ -2228,22 +2393,23 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { while (__rt != nullptr) { auto __comp_res = __comp(__k, __rt->__get_value()); if (__comp_res.__less()) { - __result = static_cast<__end_node_pointer>(__rt); - __rt = static_cast<__node_pointer>(__rt->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__rt); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return _Pp(iterator(__rt), - iterator(__rt->__right_ != nullptr ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) - : __result)); + iterator(__rt->__right_ != nullptr + ? std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) + : __result)); } return _Pp(iterator(__result), iterator(__result)); } template template -pair::const_iterator, - typename __tree<_Tp, _Compare, _Allocator>::const_iterator> +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::const_iterator, + typename __tree<_Tp, _Compare, _Allocator>::const_iterator> __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const { using _Pp = pair; __end_node_pointer __result = __end_node(); @@ -2252,23 +2418,25 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const { while (__rt != nullptr) { auto __comp_res = __comp(__k, __rt->__get_value()); if (__comp_res.__less()) { - __result = static_cast<__end_node_pointer>(__rt); - __rt = static_cast<__node_pointer>(__rt->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__rt); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return _Pp( const_iterator(__rt), - const_iterator( - __rt->__right_ != nullptr ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) : __result)); + const_iterator(__rt->__right_ != nullptr + ? std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) + : __result)); } return _Pp(const_iterator(__result), const_iterator(__result)); } template template -pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> -__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 + pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> + __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { using _Pp = pair; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); @@ -2290,8 +2458,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 { using _Pp = pair; __end_node_pointer __result = __end_node(); @@ -2313,7 +2481,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_) { @@ -2328,7 +2496,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/__type_traits/make_transparent.h b/libcxx/include/__type_traits/make_transparent.h index 4d3207a807fa7..efcce0011f60d 100644 --- a/libcxx/include/__type_traits/make_transparent.h +++ b/libcxx/include/__type_traits/make_transparent.h @@ -33,12 +33,12 @@ template using __make_transparent_t _LIBCPP_NODEBUG = typename __make_transparent<_Comparator>::type; template >::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Comparator& __as_transparent(_Comparator& __comp) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Comparator& __as_transparent(_Comparator& __comp) { return __comp; } template >::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI __make_transparent_t<_Comparator> __as_transparent(_Comparator&) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __make_transparent_t<_Comparator> __as_transparent(_Comparator&) { static_assert(is_empty<_Comparator>::value); return __make_transparent_t<_Comparator>(); } diff --git a/libcxx/include/__utility/default_three_way_comparator.h b/libcxx/include/__utility/default_three_way_comparator.h index 92cdce6aae117..3f6bb1d7455b6 100644 --- a/libcxx/include/__utility/default_three_way_comparator.h +++ b/libcxx/include/__utility/default_three_way_comparator.h @@ -31,7 +31,7 @@ template struct __default_three_way_comparator<_LHS, _RHS, __enable_if_t::value && is_arithmetic<_RHS>::value> > { - _LIBCPP_HIDE_FROM_ABI static int operator()(_LHS __lhs, _RHS __rhs) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static int operator()(_LHS __lhs, _RHS __rhs) { if (__lhs < __rhs) return -1; if (__lhs > __rhs) diff --git a/libcxx/include/__utility/lazy_synth_three_way_comparator.h b/libcxx/include/__utility/lazy_synth_three_way_comparator.h index 8c78742ccb4e3..3b2c7aa4de83f 100644 --- a/libcxx/include/__utility/lazy_synth_three_way_comparator.h +++ b/libcxx/include/__utility/lazy_synth_three_way_comparator.h @@ -34,14 +34,14 @@ struct __lazy_compare_result { const _LHS& __lhs_; const _RHS& __rhs_; - _LIBCPP_HIDE_FROM_ABI - __lazy_compare_result(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp, - _LIBCPP_CTOR_LIFETIMEBOUND const _LHS& __lhs, - _LIBCPP_CTOR_LIFETIMEBOUND const _RHS& __rhs) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __lazy_compare_result( + _LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp, + _LIBCPP_CTOR_LIFETIMEBOUND const _LHS& __lhs, + _LIBCPP_CTOR_LIFETIMEBOUND const _RHS& __rhs) : __comp_(__comp), __lhs_(__lhs), __rhs_(__rhs) {} - _LIBCPP_HIDE_FROM_ABI bool __less() const { return __comp_(__lhs_, __rhs_); } - _LIBCPP_HIDE_FROM_ABI bool __greater() const { return __comp_(__rhs_, __lhs_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __less() const { return __comp_(__lhs_, __rhs_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __greater() const { return __comp_(__rhs_, __lhs_); } }; // This class provides three way comparison between _LHS and _RHS as efficiently as possible. This can be specialized if @@ -51,10 +51,11 @@ template struct __lazy_synth_three_way_comparator { const _Comparator& __comp_; - _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp) : __comp_(__comp) {} - _LIBCPP_HIDE_FROM_ABI __lazy_compare_result<_Comparator, _LHS, _RHS> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __lazy_compare_result<_Comparator, _LHS, _RHS> operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) const { return __lazy_compare_result<_Comparator, _LHS, _RHS>(__comp_, __lhs, __rhs); } @@ -63,10 +64,10 @@ struct __lazy_synth_three_way_comparator { struct __eager_compare_result { int __res_; - _LIBCPP_HIDE_FROM_ABI explicit __eager_compare_result(int __res) : __res_(__res) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __eager_compare_result(int __res) : __res_(__res) {} - _LIBCPP_HIDE_FROM_ABI bool __less() const { return __res_ < 0; } - _LIBCPP_HIDE_FROM_ABI bool __greater() const { return __res_ > 0; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __less() const { return __res_ < 0; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __greater() const { return __res_ > 0; } }; template @@ -77,10 +78,11 @@ struct __lazy_synth_three_way_comparator<_Comparator, __has_default_three_way_comparator<_LHS, _RHS> >::value> > { // This lifetimebound annotation is technically incorrect, but other specializations actually capture the lifetime of // the comparator. - _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} // Same comment as above. - _LIBCPP_HIDE_FROM_ABI static __eager_compare_result + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static __eager_compare_result operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) { return __eager_compare_result(__default_three_way_comparator<_LHS, _RHS>()(__lhs, __rhs)); } @@ -94,10 +96,11 @@ struct __lazy_synth_three_way_comparator<_Comparator, __has_default_three_way_comparator<_LHS, _RHS> >::value> > { // This lifetimebound annotation is technically incorrect, but other specializations actually capture the lifetime of // the comparator. - _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} // Same comment as above. - _LIBCPP_HIDE_FROM_ABI static __eager_compare_result + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static __eager_compare_result operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) { return __eager_compare_result(-__default_three_way_comparator<_LHS, _RHS>()(__lhs, __rhs)); } diff --git a/libcxx/include/__utility/try_key_extraction.h b/libcxx/include/__utility/try_key_extraction.h index 755c08214019f..3423d746dee7f 100644 --- a/libcxx/include/__utility/try_key_extraction.h +++ b/libcxx/include/__utility/try_key_extraction.h @@ -28,7 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_HIDE_FROM_ABI _Ret +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Ret __try_key_extraction_impl(__priority_tag<0>, _WithKey, _WithoutKey __without_key, _Args&&... __args) { return __without_key(std::forward<_Args>(__args)...); } @@ -39,7 +39,7 @@ template >::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Ret +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Ret __try_key_extraction_impl(__priority_tag<1>, _WithKey __with_key, _WithoutKey, _Arg&& __arg) { return __with_key(__arg, std::forward<_Arg>(__arg)); } @@ -52,7 +52,7 @@ template > && is_same<__remove_const_t::first_type>, _KeyT>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Ret +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Ret __try_key_extraction_impl(__priority_tag<1>, _WithKey __with_key, _WithoutKey, _Arg&& __arg) { return __with_key(__arg.first, std::forward<_Arg>(__arg)); } @@ -64,7 +64,7 @@ template >::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Ret +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Ret __try_key_extraction_impl(__priority_tag<1>, _WithKey __with_key, _WithoutKey, _Arg1&& __arg1, _Arg2&& __arg2) { return __with_key(__arg1, std::forward<_Arg1>(__arg1), std::forward<_Arg2>(__arg2)); } @@ -81,7 +81,7 @@ template && tuple_size<_Tuple1>::value == 1 && is_same<__remove_const_ref_t::type>, _KeyT>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Ret __try_key_extraction_impl( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Ret __try_key_extraction_impl( __priority_tag<1>, _WithKey __with_key, _WithoutKey, @@ -102,7 +102,7 @@ _LIBCPP_HIDE_FROM_ABI _Ret __try_key_extraction_impl( // // Both `__with_key` and `__without_key` must take all arguments by reference. template -_LIBCPP_HIDE_FROM_ABI decltype(std::declval<_WithoutKey>()(std::declval<_Args>()...)) +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 decltype(std::declval<_WithoutKey>()(std::declval<_Args>()...)) __try_key_extraction(_WithKey __with_key, _WithoutKey __without_key, _Args&&... __args) { using _Ret = decltype(__without_key(std::forward<_Args>(__args)...)); return std::__try_key_extraction_impl<_KeyT, _Ret>( diff --git a/libcxx/include/map b/libcxx/include/map index 3ff849afcde09..05aca1295b88b 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -642,28 +642,37 @@ class __map_value_compare { _LIBCPP_COMPRESSED_ELEMENT(_Compare, __comp_); public: - _LIBCPP_HIDE_FROM_ABI __map_value_compare() _NOEXCEPT_(is_nothrow_default_constructible<_Compare>::value) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_value_compare() + _NOEXCEPT_(is_nothrow_default_constructible<_Compare>::value) : __comp_() {} - _LIBCPP_HIDE_FROM_ABI __map_value_compare(_Compare __c) _NOEXCEPT_(is_nothrow_copy_constructible<_Compare>::value) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_value_compare(_Compare __c) + _NOEXCEPT_(is_nothrow_copy_constructible<_Compare>::value) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return __comp_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const _Compare& key_comp() const _NOEXCEPT { return __comp_; } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const { return __comp_(__x.first, __y.first); } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const { return __comp_(__x.first, __y); } - _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const { return __comp_(__x, __y.first); } - _LIBCPP_HIDE_FROM_ABI void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _CP& __x, const _CP& __y) const { + return __comp_(__x.first, __y.first); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _CP& __x, const _Key& __y) const { + return __comp_(__x.first, __y); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _Key& __x, const _CP& __y) const { + return __comp_(__x, __y.first); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(__map_value_compare& __y) + _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) { using std::swap; swap(__comp_, __y.__comp_); } # if _LIBCPP_STD_VER >= 14 template - _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _K2& __x, const _CP& __y) const { return __comp_(__x, __y.first); } template - _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _CP& __x, const _K2& __y) const { return __comp_(__x.first, __y); } # endif @@ -679,11 +688,11 @@ template struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _Compare>, _MapValueT, _MapValueT> { __lazy_synth_three_way_comparator<_Compare, _Key, _Key> __comp_; - __lazy_synth_three_way_comparator( + _LIBCPP_CONSTEXPR_SINCE_CXX26 __lazy_synth_three_way_comparator( _LIBCPP_CTOR_LIFETIMEBOUND const __map_value_compare<_Key, _MapValueT, _Compare>& __comp) : __comp_(__comp.key_comp()) {} - _LIBCPP_HIDE_FROM_ABI auto + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto operator()(_LIBCPP_LIFETIMEBOUND const _MapValueT& __lhs, _LIBCPP_LIFETIMEBOUND const _MapValueT& __rhs) const { return __comp_(__lhs.first, __rhs.first); } @@ -693,11 +702,11 @@ template struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _Compare>, _TransparentKey, _MapValueT> { __lazy_synth_three_way_comparator<_Compare, _TransparentKey, _Key> __comp_; - __lazy_synth_three_way_comparator( + _LIBCPP_CONSTEXPR_SINCE_CXX26 __lazy_synth_three_way_comparator( _LIBCPP_CTOR_LIFETIMEBOUND const __map_value_compare<_Key, _MapValueT, _Compare>& __comp) : __comp_(__comp.key_comp()) {} - _LIBCPP_HIDE_FROM_ABI auto + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto operator()(_LIBCPP_LIFETIMEBOUND const _TransparentKey& __lhs, _LIBCPP_LIFETIMEBOUND const _MapValueT& __rhs) const { return __comp_(__lhs, __rhs.first); } @@ -719,7 +728,7 @@ struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _ # endif // _LIBCPP_STD_VER >= 14 template -inline _LIBCPP_HIDE_FROM_ABI void +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(__map_value_compare<_Key, _CP, _Compare>& __x, __map_value_compare<_Key, _CP, _Compare>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); @@ -780,37 +789,41 @@ public: using reference = value_type&; using pointer = typename _TreeIterator::pointer; - _LIBCPP_HIDE_FROM_ABI __map_iterator() _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator() _NOEXCEPT {} - _LIBCPP_HIDE_FROM_ABI __map_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *__i_; } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(*__i_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return *__i_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { + return pointer_traits::pointer_to(*__i_); + } - _LIBCPP_HIDE_FROM_ABI __map_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator& operator++() { ++__i_; return *this; } - _LIBCPP_HIDE_FROM_ABI __map_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator operator++(int) { __map_iterator __t(*this); ++(*this); return __t; } - _LIBCPP_HIDE_FROM_ABI __map_iterator& operator--() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator& operator--() { --__i_; return *this; } - _LIBCPP_HIDE_FROM_ABI __map_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_iterator operator--(int) { __map_iterator __t(*this); --(*this); return __t; } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __map_iterator& __x, const __map_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const __map_iterator& __x, const __map_iterator& __y) { return __x.__i_ == __y.__i_; } - friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __map_iterator& __x, const __map_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator!=(const __map_iterator& __x, const __map_iterator& __y) { return __x.__i_ != __y.__i_; } @@ -833,39 +846,43 @@ public: using reference = const value_type&; using pointer = typename _TreeIterator::pointer; - _LIBCPP_HIDE_FROM_ABI __map_const_iterator() _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator() _NOEXCEPT {} - _LIBCPP_HIDE_FROM_ABI __map_const_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator(__map_iterator< typename _TreeIterator::__non_const_iterator> __i) _NOEXCEPT : __i_(__i.__i_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *__i_; } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(*__i_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return *__i_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const { + return pointer_traits::pointer_to(*__i_); + } - _LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator& operator++() { ++__i_; return *this; } - _LIBCPP_HIDE_FROM_ABI __map_const_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator operator++(int) { __map_const_iterator __t(*this); ++(*this); return __t; } - _LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator--() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator& operator--() { --__i_; return *this; } - _LIBCPP_HIDE_FROM_ABI __map_const_iterator operator--(int) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __map_const_iterator operator--(int) { __map_const_iterator __t(*this); --(*this); return __t; } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __map_const_iterator& __x, const __map_const_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const __map_const_iterator& __x, const __map_const_iterator& __y) { return __x.__i_ == __y.__i_; } - friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __map_const_iterator& __x, const __map_const_iterator& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator!=(const __map_const_iterator& __x, const __map_const_iterator& __y) { return __x.__i_ != __y.__i_; } @@ -901,10 +918,11 @@ public: protected: key_compare comp; - _LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : comp(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare(key_compare __c) : comp(__c) {} public: - _LIBCPP_HIDE_FROM_ABI bool operator()(const value_type& __x, const value_type& __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const value_type& __x, const value_type& __y) const { return comp(__x.first, __y.first); } }; @@ -940,26 +958,27 @@ public: template friend class multimap; - _LIBCPP_HIDE_FROM_ABI map() _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map() _NOEXCEPT_( is_nothrow_default_constructible::value&& is_nothrow_default_constructible::value&& is_nothrow_copy_constructible::value) : __tree_(__vc(key_compare())) {} - _LIBCPP_HIDE_FROM_ABI explicit map(const key_compare& __comp) _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit map(const key_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible::value&& is_nothrow_copy_constructible::value) : __tree_(__vc(__comp)) {} - _LIBCPP_HIDE_FROM_ABI explicit map(const key_compare& __comp, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit map(const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), typename __base::allocator_type(__a)) {} template - _LIBCPP_HIDE_FROM_ABI map(_InputIterator __f, _InputIterator __l, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + map(_InputIterator __f, _InputIterator __l, const key_compare& __comp = key_compare()) : __tree_(__vc(__comp)) { insert(__f, __l); } template - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(_InputIterator __f, _InputIterator __l, const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), typename __base::allocator_type(__a)) { insert(__f, __l); @@ -967,7 +986,7 @@ public: # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(from_range_t, _Range&& __range, const key_compare& __comp = key_compare(), @@ -979,157 +998,187 @@ public: # if _LIBCPP_STD_VER >= 14 template - _LIBCPP_HIDE_FROM_ABI map(_InputIterator __f, _InputIterator __l, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 map(_InputIterator __f, _InputIterator __l, const allocator_type& __a) : map(__f, __l, key_compare(), __a) {} # endif # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI map(from_range_t, _Range&& __range, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(from_range_t, _Range&& __range, const allocator_type& __a) : map(from_range, std::forward<_Range>(__range), key_compare(), __a) {} # endif - _LIBCPP_HIDE_FROM_ABI map(const map& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(const map& __m) = default; - _LIBCPP_HIDE_FROM_ABI map& operator=(const map& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map& operator=(const map& __m) = default; # ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI map(map&& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(map&& __m) = default; - _LIBCPP_HIDE_FROM_ABI map(map&& __m, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(map&& __m, const allocator_type& __a); - _LIBCPP_HIDE_FROM_ABI map& operator=(map&& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map& operator=(map&& __m) = default; - _LIBCPP_HIDE_FROM_ABI map(initializer_list __il, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + map(initializer_list __il, const key_compare& __comp = key_compare()) : __tree_(__vc(__comp)) { insert(__il.begin(), __il.end()); } - _LIBCPP_HIDE_FROM_ABI map(initializer_list __il, const key_compare& __comp, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + map(initializer_list __il, const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), typename __base::allocator_type(__a)) { insert(__il.begin(), __il.end()); } # if _LIBCPP_STD_VER >= 14 - _LIBCPP_HIDE_FROM_ABI map(initializer_list __il, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(initializer_list __il, const allocator_type& __a) : map(__il, key_compare(), __a) {} # endif - _LIBCPP_HIDE_FROM_ABI map& operator=(initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map& operator=(initializer_list __il) { __tree_.__assign_unique(__il.begin(), __il.end()); return *this; } # endif // _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI explicit map(const allocator_type& __a) : __tree_(typename __base::allocator_type(__a)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit map(const allocator_type& __a) + : __tree_(typename __base::allocator_type(__a)) {} - _LIBCPP_HIDE_FROM_ABI map(const map& __m, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 map(const map& __m, const allocator_type& __a) : __tree_(__m.__tree_.value_comp(), typename __base::allocator_type(__a)) { insert(__m.begin(), __m.end()); } - _LIBCPP_HIDE_FROM_ABI ~map() { static_assert(sizeof(std::__diagnose_non_const_comparator<_Key, _Compare>()), ""); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~map() { + static_assert(sizeof(std::__diagnose_non_const_comparator<_Key, _Compare>()), ""); + } - _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __tree_.begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __tree_.begin(); } - _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __tree_.end(); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __tree_.end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() _NOEXCEPT { return __tree_.begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const _NOEXCEPT { return __tree_.begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() _NOEXCEPT { return __tree_.end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const _NOEXCEPT { return __tree_.end(); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const _NOEXCEPT { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() _NOEXCEPT { + return reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const _NOEXCEPT { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() _NOEXCEPT { + return reverse_iterator(begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const _NOEXCEPT { + return const_reverse_iterator(begin()); + } - _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return end(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const _NOEXCEPT { return begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const _NOEXCEPT { return end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const _NOEXCEPT { + return rbegin(); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const _NOEXCEPT { return rend(); } - [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __tree_.size() == 0; } - _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __tree_.size(); } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __tree_.max_size(); } + [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const _NOEXCEPT { + return __tree_.size() == 0; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const _NOEXCEPT { return __tree_.size(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const _NOEXCEPT { + return __tree_.max_size(); + } - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](const key_type& __k); # ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& operator[](key_type&& __k); # endif template >, int> = 0> - _LIBCPP_HIDE_FROM_ABI mapped_type& at(_Arg&& __arg) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 mapped_type& at(_Arg&& __arg) { auto [_, __child] = __tree_.__find_equal(__arg); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__get_value().second; + return std::__static_fancy_pointer_cast<__node_pointer>(__child)->__get_value().second; } template >, int> = 0> - _LIBCPP_HIDE_FROM_ABI const mapped_type& at(_Arg&& __arg) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const mapped_type& at(_Arg&& __arg) const { auto [_, __child] = __tree_.__find_equal(__arg); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__get_value().second; + return std::__static_fancy_pointer_cast<__node_pointer>(__child)->__get_value().second; } - _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)...).first; } template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI pair insert(_Pp&& __p) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(_Pp&& __p) { return __tree_.__emplace_unique(std::forward<_Pp>(__p)); } template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __pos, _Pp&& __p) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __pos, _Pp&& __p) { return __tree_.__emplace_hint_unique(__pos.__i_, std::forward<_Pp>(__p)).first; } # endif // _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI pair insert(const value_type& __v) { return __tree_.__emplace_unique(__v); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(const value_type& __v) { + return __tree_.__emplace_unique(__v); + } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, const value_type& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __p, const value_type& __v) { return __tree_.__emplace_hint_unique(__p.__i_, __v).first; } # ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI pair insert(value_type&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert(value_type&& __v) { return __tree_.__emplace_unique(std::move(__v)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, value_type&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __p, value_type&& __v) { return __tree_.__emplace_hint_unique(__p.__i_, std::move(__v)).first; } - _LIBCPP_HIDE_FROM_ABI void insert(initializer_list __il) { insert(__il.begin(), __il.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list __il) { + insert(__il.begin(), __il.end()); + } # endif template - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) { __tree_.__insert_range_unique(__first, __last); } # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) { __tree_.__insert_range_unique(ranges::begin(__range), ranges::end(__range)); } # endif @@ -1137,13 +1186,15 @@ public: # if _LIBCPP_STD_VER >= 17 template - _LIBCPP_HIDE_FROM_ABI pair try_emplace(const key_type& __k, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + try_emplace(const key_type& __k, _Args&&... __args) { return __tree_.__emplace_unique( std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple(std::forward<_Args>(__args)...)); } template - _LIBCPP_HIDE_FROM_ABI pair try_emplace(key_type&& __k, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + try_emplace(key_type&& __k, _Args&&... __args) { return __tree_.__emplace_unique( std::piecewise_construct, std::forward_as_tuple(std::move(__k)), @@ -1151,7 +1202,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args) { return __tree_ .__emplace_hint_unique( __h.__i_, @@ -1162,7 +1214,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args) { return __tree_ .__emplace_hint_unique( __h.__i_, @@ -1173,7 +1226,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(const key_type& __k, _Vp&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + insert_or_assign(const key_type& __k, _Vp&& __v) { auto __result = __tree_.__emplace_unique(__k, std::forward<_Vp>(__v)); auto& [__iter, __inserted] = __result; if (!__inserted) @@ -1182,7 +1236,7 @@ public: } template - _LIBCPP_HIDE_FROM_ABI pair insert_or_assign(key_type&& __k, _Vp&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair insert_or_assign(key_type&& __k, _Vp&& __v) { auto __result = __tree_.__emplace_unique(std::move(__k), std::forward<_Vp>(__v)); auto& [__iter, __inserted] = __result; if (!__inserted) @@ -1191,7 +1245,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __h, const key_type& __k, _Vp&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __h, const key_type& __k, _Vp&& __v) { auto [__r, __inserted] = __tree_.__emplace_hint_unique(__h.__i_, __k, std::forward<_Vp>(__v)); if (!__inserted) @@ -1201,7 +1256,8 @@ public: } template - _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __h, key_type&& __k, _Vp&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + insert_or_assign(const_iterator __h, key_type&& __k, _Vp&& __v) { auto [__r, __inserted] = __tree_.__emplace_hint_unique(__h.__i_, std::move(__k), std::forward<_Vp>(__v)); if (!__inserted) @@ -1212,39 +1268,45 @@ public: # endif // _LIBCPP_STD_VER >= 17 - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __tree_.erase(__p.__i_); } - _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __p) { return __tree_.erase(__p.__i_); } - _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __tree_.__erase_unique(__k); } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __p) { + return __tree_.erase(__p.__i_); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __p) { return __tree_.erase(__p.__i_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __k) { + return __tree_.__erase_unique(__k); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __f, const_iterator __l) { return __tree_.erase(__f.__i_, __l.__i_); } - _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __tree_.clear(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() _NOEXCEPT { __tree_.clear(); } # if _LIBCPP_STD_VER >= 17 - _LIBCPP_HIDE_FROM_ABI insert_return_type insert(node_type&& __nh) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 insert_return_type insert(node_type&& __nh) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to map::insert()"); return __tree_.template __node_handle_insert_unique< node_type, insert_return_type>(std::move(__nh)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, node_type&& __nh) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, node_type&& __nh) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to map::insert()"); return __tree_.template __node_handle_insert_unique(__hint.__i_, std::move(__nh)); } - _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(key_type const& __key) { return __tree_.template __node_handle_extract(__key); } - _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(const_iterator __it) { return __tree_.template __node_handle_extract(__it.__i_); } template - _LIBCPP_HIDE_FROM_ABI void merge(map& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(map& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } template - _LIBCPP_HIDE_FROM_ABI void merge(map&& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(map&& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); @@ -1263,46 +1325,56 @@ public: } # endif - _LIBCPP_HIDE_FROM_ABI void swap(map& __m) _NOEXCEPT_(__is_nothrow_swappable_v<__base>) { __tree_.swap(__m.__tree_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(map& __m) _NOEXCEPT_(__is_nothrow_swappable_v<__base>) { + __tree_.swap(__m.__tree_); + } - _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); } - _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __k) { return __tree_.find(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __k) const { + return __tree_.find(__k); + } # if _LIBCPP_STD_VER >= 14 template || __is_transparently_comparable_v<_Compare, key_type, _K2>, int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _K2& __k) { return __tree_.find(__k); } template || __is_transparently_comparable_v<_Compare, key_type, _K2>, int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const { + _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 || __is_transparently_comparable_v<_Compare, key_type, _K2>, int> = 0> - _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _K2& __k) const { return find(__k) != end(); } # endif // _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_unique(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __k) { + return __tree_.__lower_bound_unique(__k); + } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __k) const { return __tree_.__lower_bound_unique(__k); } @@ -1312,21 +1384,23 @@ public: template || __is_transparently_comparable_v<_Compare, key_type, _K2>, 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_multi(__k); } template || __is_transparently_comparable_v<_Compare, key_type, _K2>, 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_multi(__k); } # endif - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_unique(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __k) { + return __tree_.__upper_bound_unique(__k); + } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __k) const { return __tree_.__upper_bound_unique(__k); } @@ -1334,30 +1408,32 @@ public: template || __is_transparently_comparable_v<_Compare, key_type, _K2>, 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_multi(__k); } template || __is_transparently_comparable_v<_Compare, key_type, _K2>, 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_multi(__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 @@ -1429,7 +1505,7 @@ map(initializer_list>, _Allocator) # ifndef _LIBCPP_CXX03_LANG template -map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) +_LIBCPP_CONSTEXPR_SINCE_CXX26 map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) : __tree_(std::move(__m.__tree_), typename __base::allocator_type(__a)) { if (__a != __m.get_allocator()) { const_iterator __e = cend(); @@ -1441,13 +1517,13 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) } template -_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { return __tree_.__emplace_unique(std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple()) .first->second; } template -_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k) { return __tree_ .__emplace_unique(std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple()) .first->second; @@ -1482,23 +1558,23 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { # endif // _LIBCPP_CXX03_LANG template -_Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) { auto [_, __child] = __tree_.__find_equal(__k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__get_value().second; + return std::__static_fancy_pointer_cast<__node_pointer>(__child)->__get_value().second; } template -const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const { +_LIBCPP_CONSTEXPR_SINCE_CXX26 const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const { auto [_, __child] = __tree_.__find_equal(__k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__get_value().second; + return std::__static_fancy_pointer_cast<__node_pointer>(__child)->__get_value().second; } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator==(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return __x.size() == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin()); } @@ -1506,31 +1582,31 @@ operator==(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, # if _LIBCPP_STD_VER <= 17 template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator<(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return std::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator!=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__x == __y); } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator>(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return __y < __x; } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator>=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__x < __y); } template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__y < __x); } @@ -1538,7 +1614,7 @@ operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, # else // #if _LIBCPP_STD_VER <= 17 template -_LIBCPP_HIDE_FROM_ABI __synth_three_way_result> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __synth_three_way_result> operator<=>(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); } @@ -1546,7 +1622,7 @@ operator<=>(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp # endif // #if _LIBCPP_STD_VER <= 17 template -inline _LIBCPP_HIDE_FROM_ABI void +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(map<_Key, _Tp, _Compare, _Allocator>& __x, map<_Key, _Tp, _Compare, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); @@ -1554,7 +1630,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); } diff --git a/libcxx/include/version b/libcxx/include/version index 44d7908923fc5..80eb04c56640e 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..943b79f5211fc 100644 --- a/libcxx/test/std/containers/associative/from_range_associative_containers.h +++ b/libcxx/test/std/containers/associative/from_range_associative_containers.h @@ -60,7 +60,7 @@ template