diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 3c7175c73f21e..62e903542c6db 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/include/__tree b/libcxx/include/__tree index ef960d481cb7b..5941aa3da6e5c 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,25 @@ 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 +#if _LIBCPP_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 +651,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 +696,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 +764,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 +888,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 +963,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 +992,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 +1016,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 +1029,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 +1049,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 +1059,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 +1142,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 +1171,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,164 +1203,220 @@ public: } } - _LIBCPP_HIDE_FROM_ABI iterator __remove_node_pointer(__node_pointer) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __remove_node_pointer(__node_pointer) _NOEXCEPT; #if _LIBCPP_STD_VER >= 17 template - _LIBCPP_HIDE_FROM_ABI _InsertReturnType __node_handle_insert_unique(_NodeHandle&&); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _InsertReturnType __node_handle_insert_unique(_NodeHandle&&); template - _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_unique(const_iterator, _NodeHandle&&); + _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 iterator lower_bound(const _Key& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Key& __v) { return __lower_bound(__v, __root(), __end_node()); } template - _LIBCPP_HIDE_FROM_ABI iterator __lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result); template - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Key& __v) const { return __lower_bound(__v, __root(), __end_node()); } template - _LIBCPP_HIDE_FROM_ABI const_iterator + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator __lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const; template - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Key& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Key& __v) { return __upper_bound(__v, __root(), __end_node()); } template - _LIBCPP_HIDE_FROM_ABI iterator __upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator + __upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result); template - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Key& __v) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Key& __v) const { return __upper_bound(__v, __root(), __end_node()); } template - _LIBCPP_HIDE_FROM_ABI const_iterator + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator __upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const; template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_unique(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __equal_range_unique(const _Key& __k); template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_unique(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __equal_range_unique(const _Key& __k) const; template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_multi(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair __equal_range_multi(const _Key& __k); template - _LIBCPP_HIDE_FROM_ABI pair __equal_range_multi(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + __equal_range_multi(const _Key& __k) const; 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> @@ -1278,22 +1425,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) @@ -1306,8 +1453,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_; @@ -1320,24 +1467,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)); } }; @@ -1348,26 +1494,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; } @@ -1377,8 +1522,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; @@ -1389,24 +1533,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; @@ -1415,16 +1561,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; @@ -1435,27 +1581,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; @@ -1463,14 +1610,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; @@ -1478,7 +1626,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( @@ -1498,7 +1647,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( @@ -1517,7 +1667,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), @@ -1525,14 +1675,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_)), @@ -1550,7 +1700,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) @@ -1570,7 +1720,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_; @@ -1589,7 +1739,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 { @@ -1610,7 +1760,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>)) @@ -1635,7 +1785,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(); @@ -1646,7 +1796,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) { @@ -1676,7 +1826,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) { @@ -1692,7 +1842,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_; } } @@ -1709,7 +1859,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 { @@ -1722,7 +1873,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) @@ -1737,8 +1888,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&>; @@ -1758,18 +1910,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); } } } @@ -1782,8 +1934,9 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const _Key& __v) { // If __v doesn't exist, return the parent of the null leaf and a reference to the pointer to the null leaf. template template -_LIBCPP_HIDE_FROM_ABI pair::__end_node_pointer, - typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::__end_node_pointer, + typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&> __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_base_pointer& __dummy, const _Key& __v) { using _Pair = pair<__end_node_pointer, __node_base_pointer&>; @@ -1794,7 +1947,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_ba // *prev(__hint) < __v < *__hint if (__hint.__ptr_->__left_ == nullptr) return _Pair(__hint.__ptr_, __hint.__ptr_->__left_); - return _Pair(__prior.__ptr_, static_cast<__node_pointer>(__prior.__ptr_)->__right_); + return _Pair(__prior.__ptr_, std::__static_fancy_pointer_cast<__node_pointer>(__prior.__ptr_)->__right_); } // __v <= *prev(__hint) return __find_equal(__v); @@ -1819,7 +1972,7 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_ba } template -void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( +_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( __end_node_pointer __parent, __node_base_pointer& __child, __node_base_pointer __new_node) _NOEXCEPT { __new_node->__left_ = nullptr; __new_node->__right_ = nullptr; @@ -1827,14 +1980,14 @@ void __tree<_Tp, _Compare, _Allocator>::__insert_node_at( // __new_node->__is_black_ is initialized in __tree_balance_after_insert __child = __new_node; if (__begin_node_->__left_ != nullptr) - __begin_node_ = static_cast<__end_node_pointer>(__begin_node_->__left_); + __begin_node_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__begin_node_->__left_); std::__tree_balance_after_insert(__end_node()->__left_, __child); ++__size_; } template template -typename __tree<_Tp, _Compare, _Allocator>::__node_holder +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::__node_holder __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) { __node_allocator& __na = __node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); @@ -1845,7 +1998,7 @@ __tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator +typename __tree<_Tp, _Compare, _Allocator>::iterator _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; @@ -1856,24 +2009,24 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator +typename __tree<_Tp, _Compare, _Allocator>::iterator _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, _Args&&... __args) { __node_holder __h = __construct_node(std::forward<_Args>(__args)...); __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __h->__get_value()); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get())); return iterator(static_cast<__node_pointer>(__h.release())); } template -pair::iterator, bool> +pair::iterator, bool> _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, __node_pointer __nd) { auto [__parent, __child] = __find_equal(__v); __node_pointer __r = static_cast<__node_pointer>(__child); bool __inserted = false; if (__child == nullptr) { __assign_value(__nd->__get_value(), __v); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd)); __r = __nd; __inserted = true; } @@ -1881,16 +2034,16 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, _ } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd) { __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf_high(__parent, __nd->__get_value()); - __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + __insert_node_at(__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__nd)); return iterator(__nd); } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, __node_pointer __nd) { __end_node_pointer __parent; __node_base_pointer& __child = __find_leaf(__p, __parent, __nd->__get_value()); @@ -1899,21 +2052,21 @@ __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, __nod } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr) _NOEXCEPT { iterator __r(__ptr); ++__r; if (__begin_node_ == __ptr) __begin_node_ = __r.__ptr_; --__size_; - std::__tree_remove(__end_node()->__left_, static_cast<__node_base_pointer>(__ptr)); + std::__tree_remove(__end_node()->__left_, std::__static_fancy_pointer_cast<__node_base_pointer>(__ptr)); return __r; } #if _LIBCPP_STD_VER >= 17 template template -_LIBCPP_HIDE_FROM_ABI _InsertReturnType +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _InsertReturnType __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __nh) { if (__nh.empty()) return _InsertReturnType{end(), false, _NodeHandle()}; @@ -1930,7 +2083,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __n template template -_LIBCPP_HIDE_FROM_ABI typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __hint, _NodeHandle&& __nh) { if (__nh.empty()) return end(); @@ -1949,7 +2102,8 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __ template template -_LIBCPP_HIDE_FROM_ABI _NodeHandle __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodeHandle +__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key) { iterator __it = find(__key); if (__it == end()) return _NodeHandle(); @@ -1958,7 +2112,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()); @@ -1966,7 +2121,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();) { @@ -1982,7 +2138,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(); @@ -1996,7 +2152,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(_NodeHandle&& __nh template template -_LIBCPP_HIDE_FROM_ABI typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh) { if (__nh.empty()) return end(); @@ -2011,7 +2167,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();) { @@ -2027,7 +2184,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(); @@ -2037,7 +2195,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allo } template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l) { while (__f != __l) __f = erase(__f); @@ -2046,7 +2204,7 @@ __tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l) template template -typename __tree<_Tp, _Compare, _Allocator>::size_type +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k) { iterator __i = find(__k); if (__i == end()) @@ -2057,7 +2215,7 @@ __tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k) { template template -typename __tree<_Tp, _Compare, _Allocator>::size_type +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k) { pair __p = __equal_range_multi(__k); size_type __r = 0; @@ -2068,16 +2226,16 @@ __tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k) { template template -typename __tree<_Tp, _Compare, _Allocator>::size_type +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const { __node_pointer __rt = __root(); auto __comp = __lazy_synth_three_way_comparator(value_comp()); while (__rt != nullptr) { auto __comp_res = __comp(__k, __rt->__get_value()); if (__comp_res.__less()) { - __rt = static_cast<__node_pointer>(__rt->__left_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return 1; } @@ -2086,7 +2244,7 @@ __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const { template template -typename __tree<_Tp, _Compare, _Allocator>::size_type +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const { __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); @@ -2108,64 +2266,67 @@ __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const { template template -typename __tree<_Tp, _Compare, _Allocator>::iterator +typename __tree<_Tp, _Compare, _Allocator>::iterator _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) { while (__root != nullptr) { if (!value_comp()(__root->__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( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::const_iterator +__tree<_Tp, _Compare, _Allocator>::__lower_bound( const _Key& __v, __node_pointer __root, __end_node_pointer __result) const { while (__root != nullptr) { if (!value_comp()(__root->__get_value(), __v)) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return const_iterator(__result); } template template -typename __tree<_Tp, _Compare, _Allocator>::iterator +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) { while (__root != nullptr) { if (value_comp()(__v, __root->__get_value())) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return iterator(__result); } template template -typename __tree<_Tp, _Compare, _Allocator>::const_iterator __tree<_Tp, _Compare, _Allocator>::__upper_bound( +_LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::const_iterator +__tree<_Tp, _Compare, _Allocator>::__upper_bound( const _Key& __v, __node_pointer __root, __end_node_pointer __result) const { while (__root != nullptr) { if (value_comp()(__v, __root->__get_value())) { - __result = static_cast<__end_node_pointer>(__root); - __root = static_cast<__node_pointer>(__root->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__root); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__left_); } else - __root = static_cast<__node_pointer>(__root->__right_); + __root = std::__static_fancy_pointer_cast<__node_pointer>(__root->__right_); } return const_iterator(__result); } template template -pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> -__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 + pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> + __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { using _Pp = pair; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); @@ -2173,22 +2334,23 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { while (__rt != nullptr) { auto __comp_res = __comp(__k, __rt->__get_value()); if (__comp_res.__less()) { - __result = static_cast<__end_node_pointer>(__rt); - __rt = static_cast<__node_pointer>(__rt->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__rt); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return _Pp(iterator(__rt), - iterator(__rt->__right_ != nullptr ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) - : __result)); + iterator(__rt->__right_ != nullptr + ? std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) + : __result)); } return _Pp(iterator(__result), iterator(__result)); } template template -pair::const_iterator, - typename __tree<_Tp, _Compare, _Allocator>::const_iterator> +_LIBCPP_CONSTEXPR_SINCE_CXX26 pair::const_iterator, + typename __tree<_Tp, _Compare, _Allocator>::const_iterator> __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const { using _Pp = pair; __end_node_pointer __result = __end_node(); @@ -2197,23 +2359,25 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const { while (__rt != nullptr) { auto __comp_res = __comp(__k, __rt->__get_value()); if (__comp_res.__less()) { - __result = static_cast<__end_node_pointer>(__rt); - __rt = static_cast<__node_pointer>(__rt->__left_); + __result = std::__static_fancy_pointer_cast<__end_node_pointer>(__rt); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__left_); } else if (__comp_res.__greater()) - __rt = static_cast<__node_pointer>(__rt->__right_); + __rt = std::__static_fancy_pointer_cast<__node_pointer>(__rt->__right_); else return _Pp( const_iterator(__rt), - const_iterator( - __rt->__right_ != nullptr ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) : __result)); + const_iterator(__rt->__right_ != nullptr + ? std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) + : __result)); } return _Pp(const_iterator(__result), const_iterator(__result)); } template template -pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> -__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { +_LIBCPP_CONSTEXPR_SINCE_CXX26 + pair::iterator, typename __tree<_Tp, _Compare, _Allocator>::iterator> + __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { using _Pp = pair; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); @@ -2234,8 +2398,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(); @@ -2256,7 +2420,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_) { @@ -2271,7 +2435,8 @@ __tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT { } template -inline _LIBCPP_HIDE_FROM_ABI void swap(__tree<_Tp, _Compare, _Allocator>& __x, __tree<_Tp, _Compare, _Allocator>& __y) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void +swap(__tree<_Tp, _Compare, _Allocator>& __x, __tree<_Tp, _Compare, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } diff --git a/libcxx/include/map b/libcxx/include/map index 035f913bd3497..5b63dd85c9357 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -1618,26 +1618,28 @@ public: template friend class multimap; - _LIBCPP_HIDE_FROM_ABI multimap() _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap() _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 multimap(const key_compare& __comp) _NOEXCEPT_( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit multimap(const key_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible::value&& is_nothrow_copy_constructible::value) : __tree_(__vc(__comp)) {} - _LIBCPP_HIDE_FROM_ABI explicit multimap(const key_compare& __comp, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit multimap(const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), typename __base::allocator_type(__a)) {} template - _LIBCPP_HIDE_FROM_ABI multimap(_InputIterator __f, _InputIterator __l, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + multimap(_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 multimap(_InputIterator __f, _InputIterator __l, const key_compare& __comp, const allocator_type& __a) : __tree_(__vc(__comp), typename __base::allocator_type(__a)) { insert(__f, __l); @@ -1645,7 +1647,7 @@ public: # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap(from_range_t, _Range&& __range, const key_compare& __comp = key_compare(), @@ -1657,260 +1659,316 @@ public: # if _LIBCPP_STD_VER >= 14 template - _LIBCPP_HIDE_FROM_ABI multimap(_InputIterator __f, _InputIterator __l, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap(_InputIterator __f, _InputIterator __l, const allocator_type& __a) : multimap(__f, __l, key_compare(), __a) {} # endif # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange _Range> - _LIBCPP_HIDE_FROM_ABI multimap(from_range_t, _Range&& __range, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap(from_range_t, _Range&& __range, const allocator_type& __a) : multimap(from_range, std::forward<_Range>(__range), key_compare(), __a) {} # endif - _LIBCPP_HIDE_FROM_ABI multimap(const multimap& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap(const multimap& __m) = default; - _LIBCPP_HIDE_FROM_ABI multimap& operator=(const multimap& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap& operator=(const multimap& __m) = default; # ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI multimap(multimap&& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap(multimap&& __m) = default; - _LIBCPP_HIDE_FROM_ABI multimap(multimap&& __m, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap(multimap&& __m, const allocator_type& __a); - _LIBCPP_HIDE_FROM_ABI multimap& operator=(multimap&& __m) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap& operator=(multimap&& __m) = default; - _LIBCPP_HIDE_FROM_ABI multimap(initializer_list __il, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + multimap(initializer_list __il, const key_compare& __comp = key_compare()) : __tree_(__vc(__comp)) { insert(__il.begin(), __il.end()); } - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap(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 multimap(initializer_list __il, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap(initializer_list __il, const allocator_type& __a) : multimap(__il, key_compare(), __a) {} # endif - _LIBCPP_HIDE_FROM_ABI multimap& operator=(initializer_list __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap& operator=(initializer_list __il) { __tree_.__assign_multi(__il.begin(), __il.end()); return *this; } # endif // _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI explicit multimap(const allocator_type& __a) : __tree_(typename __base::allocator_type(__a)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit multimap(const allocator_type& __a) + : __tree_(typename __base::allocator_type(__a)) {} - _LIBCPP_HIDE_FROM_ABI multimap(const multimap& __m, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 multimap(const multimap& __m, const allocator_type& __a) : __tree_(__m.__tree_.value_comp(), typename __base::allocator_type(__a)) { insert(__m.begin(), __m.end()); } - _LIBCPP_HIDE_FROM_ABI ~multimap() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~multimap() { 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 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 iterator emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace(_Args&&... __args) { return __tree_.__emplace_multi(std::forward<_Args>(__args)...); } template - _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __p, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __p, _Args&&... __args) { return __tree_.__emplace_hint_multi(__p.__i_, std::forward<_Args>(__args)...); } template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator insert(_Pp&& __p) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(_Pp&& __p) { return __tree_.__emplace_multi(std::forward<_Pp>(__p)); } template ::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __pos, _Pp&& __p) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __pos, _Pp&& __p) { return __tree_.__emplace_hint_multi(__pos.__i_, std::forward<_Pp>(__p)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __v) { return __tree_.__emplace_multi(std::move(__v)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(value_type&& __v) { + return __tree_.__emplace_multi(std::move(__v)); + } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, value_type&& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __p, value_type&& __v) { return __tree_.__emplace_hint_multi(__p.__i_, std::move(__v)); } - _LIBCPP_HIDE_FROM_ABI void insert(initializer_list __il) { insert(__il.begin(), __il.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list __il) { + insert(__il.begin(), __il.end()); + } # endif // _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __v) { return __tree_.__emplace_multi(__v); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const value_type& __v) { + return __tree_.__emplace_multi(__v); + } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, const value_type& __v) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __p, const value_type& __v) { return __tree_.__emplace_hint_multi(__p.__i_, __v); } template - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __f, _InputIterator __l) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __f, _InputIterator __l) { __tree_.__insert_range_multi(__f, __l); } # 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_multi(ranges::begin(__range), ranges::end(__range)); } # endif - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __tree_.erase(__p.__i_); } - _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __p) { return __tree_.erase(__p.__i_); } - _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __tree_.__erase_multi(__k); } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __p) { + return __tree_.erase(__p.__i_); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __p) { return __tree_.erase(__p.__i_); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __k) { + return __tree_.__erase_multi(__k); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __f, const_iterator __l) { return __tree_.erase(__f.__i_, __l.__i_); } # if _LIBCPP_STD_VER >= 17 - _LIBCPP_HIDE_FROM_ABI iterator insert(node_type&& __nh) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(node_type&& __nh) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to multimap::insert()"); return __tree_.template __node_handle_insert_multi(std::move(__nh)); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, node_type&& __nh) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, node_type&& __nh) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to multimap::insert()"); return __tree_.template __node_handle_insert_multi(__hint.__i_, std::move(__nh)); } - _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(key_type const& __key) { return __tree_.template __node_handle_extract(__key); } - _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 node_type extract(const_iterator __it) { return __tree_.template __node_handle_extract(__it.__i_); } template - _LIBCPP_HIDE_FROM_ABI void merge(multimap& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(multimap& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__source.__tree_); } template - _LIBCPP_HIDE_FROM_ABI void merge(multimap&& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(multimap&& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__source.__tree_); } template - _LIBCPP_HIDE_FROM_ABI void merge(map& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(map& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__source.__tree_); } template - _LIBCPP_HIDE_FROM_ABI void merge(map&& __source) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + merge(map&& __source) { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__source.__tree_); } # endif - _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __tree_.clear(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() _NOEXCEPT { __tree_.clear(); } - _LIBCPP_HIDE_FROM_ABI void swap(multimap& __m) _NOEXCEPT_(__is_nothrow_swappable_v<__base>) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(multimap& __m) + _NOEXCEPT_(__is_nothrow_swappable_v<__base>) { __tree_.swap(__m.__tree_); } - _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); } - _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __k) { return __tree_.find(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __k) const { + return __tree_.find(__k); + } # if _LIBCPP_STD_VER >= 14 template , int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _K2& __k) { return __tree_.find(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _K2& __k) const { return __tree_.find(__k); } # endif - _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __tree_.__count_multi(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __k) const { + return __tree_.__count_multi(__k); + } # if _LIBCPP_STD_VER >= 14 template , int> = 0> - _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _K2& __k) const { return __tree_.__count_multi(__k); } # endif # if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __k) const { + return find(__k) != end(); + } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _K2& __k) const { return find(__k) != end(); } # endif // _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.lower_bound(__k); } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __k) { + return __tree_.lower_bound(__k); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __k) const { + return __tree_.lower_bound(__k); + } # if _LIBCPP_STD_VER >= 14 template , int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _K2& __k) { return __tree_.lower_bound(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _K2& __k) const { return __tree_.lower_bound(__k); } # endif - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.upper_bound(__k); } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__k); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __k) { + return __tree_.upper_bound(__k); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __k) const { + return __tree_.upper_bound(__k); + } # if _LIBCPP_STD_VER >= 14 template , int> = 0> - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _K2& __k) { return __tree_.upper_bound(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _K2& __k) const { return __tree_.upper_bound(__k); } # endif - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const key_type& __k) { return __tree_.__equal_range_multi(__k); } - _LIBCPP_HIDE_FROM_ABI pair equal_range(const key_type& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const key_type& __k) const { return __tree_.__equal_range_multi(__k); } # if _LIBCPP_STD_VER >= 14 template , int> = 0> - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _K2& __k) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair equal_range(const _K2& __k) { return __tree_.__equal_range_multi(__k); } template , int> = 0> - _LIBCPP_HIDE_FROM_ABI pair equal_range(const _K2& __k) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair + equal_range(const _K2& __k) const { return __tree_.__equal_range_multi(__k); } # endif @@ -1976,6 +2034,7 @@ multimap(initializer_list>, _Allocator) # ifndef _LIBCPP_CXX03_LANG template +_LIBCPP_CONSTEXPR_SINCE_CXX26 multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const allocator_type& __a) : __tree_(std::move(__m.__tree_), typename __base::allocator_type(__a)) { if (__a != __m.get_allocator()) { @@ -1988,7 +2047,7 @@ multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const alloca # endif template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX26 operator==(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { return __x.size() == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin()); } @@ -1996,31 +2055,31 @@ operator==(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap< # if _LIBCPP_STD_VER <= 17 template -inline _LIBCPP_HIDE_FROM_ABI bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator<(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_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 multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_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 multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_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 multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_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 multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { return !(__y < __x); } @@ -2028,7 +2087,7 @@ operator<=(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap< # 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 multimap<_Key, _Tp, _Compare, _Allocator>& __x, const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), __synth_three_way); @@ -2037,7 +2096,7 @@ operator<=>(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, # endif // #if _LIBCPP_STD_VER <= 17 template -inline _LIBCPP_HIDE_FROM_ABI void +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(multimap<_Key, _Tp, _Compare, _Allocator>& __x, multimap<_Key, _Tp, _Compare, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); @@ -2045,7 +2104,7 @@ swap(multimap<_Key, _Tp, _Compare, _Allocator>& __x, multimap<_Key, _Tp, _Compar # if _LIBCPP_STD_VER >= 20 template -inline _LIBCPP_HIDE_FROM_ABI typename multimap<_Key, _Tp, _Compare, _Allocator>::size_type +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename multimap<_Key, _Tp, _Compare, _Allocator>::size_type erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) { return std::__libcpp_erase_if_container(__c, __pred); } diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 5d469d4914b0b..aee6d9ed4c738 100644 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -387,6 +387,11 @@ def add_version_header(tc): "values": {"c++26": 202502}, "headers": ["list"], }, + { + "name": "__cpp_lib_constexpr_map", + "values": {"c++26": 202502}, + "headers": ["map"], + }, { "name": "__cpp_lib_constexpr_memory", "values": {"c++20": 201811, "c++23": 202202},