@@ -209,7 +209,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _EndNodePtr __tree_ne
209209 return std::__static_fancy_pointer_cast<_EndNodePtr>(std::__tree_min (__x->__right_ ));
210210 while (!std::__tree_is_left_child (__x))
211211 __x = __x->__parent_unsafe ();
212- return static_cast <_EndNodePtr>(__x->__parent_ );
212+ return std::__static_fancy_pointer_cast <_EndNodePtr>(__x->__parent_ );
213213}
214214
215215// Returns: pointer to the previous in-order node before __x.
@@ -620,13 +620,10 @@ public:
620620
621621// This line fails with:
622622// libcxx/test-suite-install/include/c++/v1/__memory/construct_at.h:38:49: note: non-literal type
623- // 'std::__tree_node<std::__value_type<Key, int>, void *>' cannot be used in a constant expression
624- //
623+ // `'std::__tree_node<std::__value_type<Key, int>, void *>' cannot be used in a constant expression`
625624// during constant evaluation as part of P3372
626625// on:
627- // 1. Arm CI which is on clang 19.x (will be fixed in: https://github.com/llvm/llvm-project/issues/161159 )
628- // 2. AppleClang is not yet using clang >= 20.x, which has "fixed" this issue
629- // 3. A few others like FreeBSD/amd64, AArch64, AIX
626+ // 1. AppleClang, which is not yet using clang >= 20.x, which has "fixed" this issue
630627// FIXME: when AppleClang is based off of clang >= 20.x
631628// FIXME: when Clang-based CI is using clang >= 20.x
632629#if (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 2000) || \
@@ -1069,10 +1066,10 @@ public:
10691066#if _LIBCPP_STD_VER >= 26
10701067 if (std::is_constant_evaluated () && std::is_copy_constructible_v<decltype (__value.first )>) {
10711068 // We create a sfinae wrapper method here, because if the __emplace_hint_unique method gets template instantiated
1072- // within __insert_unique_from_orphaned_node, the code will fail to compile where the value is not
1073- // copy_constructible for runtime execution as well ; unless we use `if constexpr`. Given the copy-constructible
1069+ // within __insert_unique_from_orphaned_node, the code will fail to compile when the value is not
1070+ // copy_constructible (even for runtime execution) ; unless we use `if constexpr`. Given the copy-constructible
10741071 // code path will be a performance regression, we want to restrict it to only execute during constant evaluation
1075- // , we need to delay the template instantiation
1072+ // , hence, we need to delay the template instantiation.
10761073 __emplace_hint_unique__sfinae (
10771074 integral_constant< bool , std::is_copy_constructible_v<decltype (__value.first )> >(),
10781075 __p,
@@ -1426,7 +1423,7 @@ private:
14261423 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
14271424 __assign_value__sfinae (false_type, __get_node_value_type_t <value_type>&, _From&&) {
14281425 // This method body should never be run. It only exists to allow for compilation. See note in __assign_value for
1429- // more information
1426+ // more information.
14301427 }
14311428
14321429 template <class _From , class _ValueT = _Tp, __enable_if_t <__is_tree_value_type_v<_ValueT>, int > = 0 >
@@ -1437,22 +1434,23 @@ private:
14371434#if _LIBCPP_STD_VER >= 26
14381435
14391436 if (std::is_constant_evaluated () && std::is_copy_constructible_v<decltype (__rhs.first )>) {
1440- // we use copy, and not "move" as the constraint
1441- // because we can NOT move from `const key_type`, which is how `value_type` is defined
1442- // atleast for map
1443- // typedef pair<const key_type, mapped_type> value_type;
1444- // so we must copy it
1445-
1446- // const_cast is not allowed at constexpr time.
1447- // we get around this by deleting __lhs and creating a new node in-place
1448- // to avoid const_cast __lhs.first
1449-
1450- // We create a sfinae wrapper method here, because if the body of the true_type overload for
1451- // __assign_value__sfinae() gets template instantiated within __assign_value, the code will fail to compile where
1452- // the value is not copy_constructible for runtime execution as well; unless we use `if constexpr`. Given the
1453- // copy-constructible code path will be a performance regression, we want to restrict it to only execute during
1454- // constant evaluation
1455- // , we need to delay the template instantiation
1437+ // We use copy, and not "move" as the constraint here because we can NOT move
1438+ // from `const key_type`, which is how `value_type` is defined for `std::map`
1439+ // `typedef pair<const key_type, mapped_type> value_type;`
1440+ // so we must copy it to not perform undefined behavior which
1441+ // is disallowed during constant evaluation.
1442+
1443+ // Furthermore, `const_cast` is not allowed during constant evaluation.
1444+ // We get around this by deleting `__lhs` and creating a new node in-place
1445+ // to avoid the `const_cast` when attempting to assign to `__lhs.first`.
1446+
1447+ // We create a sfinae wrapper method here, because if the body of the `true_type` overload for
1448+ // `__assign_value__sfinae()` gets template instantiated within `__assign_value`,
1449+ // the code will fail to compile when
1450+ // the value is not copy_constructible (even for runtime execution); unless we use `if constexpr`.
1451+ // Given that the copy-constructible code path will be a performance regression,
1452+ // we want to restrict it to only execute during constant evaluation
1453+ // , we need to delay the template instantiation.
14561454
14571455 __assign_value__sfinae (std::integral_constant<bool , std::is_copy_constructible_v<decltype (__rhs.first )>>(),
14581456 std::forward<decltype (__lhs)>(__lhs),
@@ -1493,7 +1491,7 @@ private:
14931491 __t_->destroy (__cache_elem_);
14941492 if (__cache_root_) {
14951493 while (__cache_root_->__parent_ != nullptr )
1496- __cache_root_ = static_cast <__node_pointer>(__cache_root_->__parent_ );
1494+ __cache_root_ = std::__static_fancy_pointer_cast <__node_pointer>(__cache_root_->__parent_ );
14971495 __t_->destroy (__cache_root_);
14981496 }
14991497 }
@@ -1639,14 +1637,14 @@ __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_next(__node_poin
16391637 __cache = std::__static_fancy_pointer_cast<__node_pointer>(__cache->__parent_ );
16401638 if (__cache->__right_ == nullptr )
16411639 return __cache;
1642- return static_cast <__node_pointer>(std::__tree_leaf (__cache->__right_ ));
1640+ return std::__static_fancy_pointer_cast <__node_pointer>(std::__tree_leaf (__cache->__right_ ));
16431641 }
16441642 // __cache is right child
16451643 __cache->__parent_unsafe ()->__right_ = nullptr ;
16461644 __cache = std::__static_fancy_pointer_cast<__node_pointer>(__cache->__parent_ );
16471645 if (__cache->__left_ == nullptr )
16481646 return __cache;
1649- return static_cast <__node_pointer>(std::__tree_leaf (__cache->__left_ ));
1647+ return std::__static_fancy_pointer_cast <__node_pointer>(std::__tree_leaf (__cache->__left_ ));
16501648}
16511649
16521650template <class _Tp , class _Compare , class _Allocator >
@@ -1741,7 +1739,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(__tree&&
17411739 if (__size_ == 0 )
17421740 __begin_node_ = __end_node ();
17431741 else {
1744- __end_node ()->__left_ ->__parent_ = static_cast <__end_node_pointer>(__end_node ());
1742+ __end_node ()->__left_ ->__parent_ = std::__static_fancy_pointer_cast <__end_node_pointer>(__end_node ());
17451743 __t .__begin_node_ = __t .__end_node ();
17461744 __t .__end_node ()->__left_ = nullptr ;
17471745 __t .__size_ = 0 ;
@@ -1757,7 +1755,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(__tree&&
17571755 else {
17581756 __begin_node_ = __t .__begin_node_ ;
17591757 __end_node ()->__left_ = __t .__end_node ()->__left_ ;
1760- __end_node ()->__left_ ->__parent_ = static_cast <__end_node_pointer>(__end_node ());
1758+ __end_node ()->__left_ ->__parent_ = std::__static_fancy_pointer_cast <__end_node_pointer>(__end_node ());
17611759 __size_ = __t .__size_ ;
17621760 __t .__begin_node_ = __t .__end_node ();
17631761 __t .__end_node ()->__left_ = nullptr ;
@@ -1771,7 +1769,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree<_Tp, _Compare, _Allocator>::__tree(__tree&&
17711769template <class _Tp , class _Compare , class _Allocator >
17721770_LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t , true_type)
17731771 _NOEXCEPT_ (is_nothrow_move_assignable<value_compare>::value&& is_nothrow_move_assignable<__node_allocator>::value) {
1774- destroy (static_cast <__node_pointer>(__end_node ()->__left_ ));
1772+ destroy (std::__static_fancy_pointer_cast <__node_pointer>(__end_node ()->__left_ ));
17751773 __begin_node_ = __t .__begin_node_ ;
17761774 __end_node_ = __t .__end_node_ ;
17771775 __move_assign_alloc (__t );
@@ -1780,7 +1778,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree<_Tp, _Compare, _Allocator>::__move_ass
17801778 if (__size_ == 0 )
17811779 __begin_node_ = __end_node ();
17821780 else {
1783- __end_node ()->__left_ ->__parent_ = static_cast <__end_node_pointer>(__end_node ());
1781+ __end_node ()->__left_ ->__parent_ = std::__static_fancy_pointer_cast <__end_node_pointer>(__end_node ());
17841782 __t .__begin_node_ = __t .__end_node ();
17851783 __t .__end_node ()->__left_ = nullptr ;
17861784 __t .__size_ = 0 ;
@@ -1852,16 +1850,16 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__end_node_pointer& __parent,
18521850 while (true ) {
18531851 if (value_comp ()(__nd->__get_value (), __v)) {
18541852 if (__nd->__right_ != nullptr )
1855- __nd = static_cast <__node_pointer>(__nd->__right_ );
1853+ __nd = std::__static_fancy_pointer_cast <__node_pointer>(__nd->__right_ );
18561854 else {
1857- __parent = static_cast <__end_node_pointer>(__nd);
1855+ __parent = std::__static_fancy_pointer_cast <__end_node_pointer>(__nd);
18581856 return __nd->__right_ ;
18591857 }
18601858 } else {
18611859 if (__nd->__left_ != nullptr )
1862- __nd = static_cast <__node_pointer>(__nd->__left_ );
1860+ __nd = std::__static_fancy_pointer_cast <__node_pointer>(__nd->__left_ );
18631861 else {
1864- __parent = static_cast <__end_node_pointer>(__nd);
1862+ __parent = std::__static_fancy_pointer_cast <__end_node_pointer>(__nd);
18651863 return __parent->__left_ ;
18661864 }
18671865 }
@@ -1918,10 +1916,10 @@ __tree<_Tp, _Compare, _Allocator>::__find_leaf(
19181916 if (__prior == begin () || !value_comp ()(__v, *--__prior)) {
19191917 // *prev(__hint) <= __v <= *__hint
19201918 if (__hint.__ptr_ ->__left_ == nullptr ) {
1921- __parent = static_cast <__end_node_pointer>(__hint.__ptr_ );
1919+ __parent = std::__static_fancy_pointer_cast <__end_node_pointer>(__hint.__ptr_ );
19221920 return __parent->__left_ ;
19231921 } else {
1924- __parent = static_cast <__end_node_pointer>(__prior.__ptr_ );
1922+ __parent = std::__static_fancy_pointer_cast <__end_node_pointer>(__prior.__ptr_ );
19251923 return std::__static_fancy_pointer_cast<__node_base_pointer>(__prior.__ptr_ )->__right_ ;
19261924 }
19271925 }
@@ -2008,15 +2006,15 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, __node_ba
20082006 if (__next == end () || value_comp ()(__v, *__next)) {
20092007 // *__hint < __v < *std::next(__hint)
20102008 if (__hint.__get_np ()->__right_ == nullptr )
2011- return _Pair (__hint.__ptr_ , static_cast <__node_pointer>(__hint.__ptr_ )->__right_ );
2009+ return _Pair (__hint.__ptr_ , std::__static_fancy_pointer_cast <__node_pointer>(__hint.__ptr_ )->__right_ );
20122010 return _Pair (__next.__ptr_ , __next.__ptr_ ->__left_ );
20132011 }
20142012 // *next(__hint) <= __v
20152013 return __find_equal (__v);
20162014 }
20172015
20182016 // else __v == *__hint
2019- __dummy = static_cast <__node_base_pointer>(__hint.__ptr_ );
2017+ __dummy = std::__static_fancy_pointer_cast <__node_base_pointer>(__hint.__ptr_ );
20202018 return _Pair (__hint.__ptr_ , __dummy);
20212019}
20222020
@@ -2064,14 +2062,14 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, _Arg
20642062 __end_node_pointer __parent;
20652063 __node_base_pointer& __child = __find_leaf (__p, __parent, __h->__get_value ());
20662064 __insert_node_at (__parent, __child, std::__static_fancy_pointer_cast<__node_base_pointer>(__h.get ()));
2067- return iterator (static_cast <__node_pointer>(__h.release ()));
2065+ return iterator (std::__static_fancy_pointer_cast <__node_pointer>(__h.release ()));
20682066}
20692067
20702068template <class _Tp , class _Compare , class _Allocator >
20712069pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool > _LIBCPP_CONSTEXPR_SINCE_CXX26
20722070__tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, __node_pointer __nd) {
20732071 auto [__parent, __child] = __find_equal (__v);
2074- __node_pointer __r = static_cast <__node_pointer>(__child);
2072+ __node_pointer __r = std::__static_fancy_pointer_cast <__node_pointer>(__child);
20752073 bool __inserted = false ;
20762074 if (__child == nullptr ) {
20772075 __assign_value (__nd->__get_value (), __v);
@@ -2096,7 +2094,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 typename __tree<_Tp, _Compare, _Allocator>::iterat
20962094__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, __node_pointer __nd) {
20972095 __end_node_pointer __parent;
20982096 __node_base_pointer& __child = __find_leaf (__p, __parent, __nd->__get_value ());
2099- __insert_node_at (__parent, __child, static_cast <__node_base_pointer>(__nd));
2097+ __insert_node_at (__parent, __child, std::__static_fancy_pointer_cast <__node_base_pointer>(__nd));
21002098 return iterator (__nd);
21012099}
21022100
@@ -2123,9 +2121,10 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __n
21232121 __node_pointer __ptr = __nh.__ptr_ ;
21242122 auto [__parent, __child] = __find_equal (__ptr->__get_value ());
21252123 if (__child != nullptr )
2126- return _InsertReturnType{iterator (static_cast <__node_pointer>(__child)), false , std::move (__nh)};
2124+ return _InsertReturnType{
2125+ iterator (std::__static_fancy_pointer_cast<__node_pointer>(__child)), false , std::move (__nh)};
21272126
2128- __insert_node_at (__parent, __child, static_cast <__node_base_pointer>(__ptr));
2127+ __insert_node_at (__parent, __child, std::__static_fancy_pointer_cast <__node_base_pointer>(__ptr));
21292128 __nh.__release_ptr ();
21302129 return _InsertReturnType{iterator (__ptr), true , _NodeHandle ()};
21312130}
@@ -2140,9 +2139,9 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __
21402139 __node_pointer __ptr = __nh.__ptr_ ;
21412140 __node_base_pointer __dummy;
21422141 auto [__parent, __child] = __find_equal (__hint, __dummy, __ptr->__get_value ());
2143- __node_pointer __r = static_cast <__node_pointer>(__child);
2142+ __node_pointer __r = std::__static_fancy_pointer_cast <__node_pointer>(__child);
21442143 if (__child == nullptr ) {
2145- __insert_node_at (__parent, __child, static_cast <__node_base_pointer>(__ptr));
2144+ __insert_node_at (__parent, __child, std::__static_fancy_pointer_cast <__node_base_pointer>(__ptr));
21462145 __r = __ptr;
21472146 __nh.__release_ptr ();
21482147 }
@@ -2179,7 +2178,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_merge_unique(__tree<_Tp, _Comp2
21792178 if (__child != nullptr )
21802179 continue ;
21812180 __source.__remove_node_pointer (__src_ptr);
2182- __insert_node_at (__parent, __child, static_cast <__node_base_pointer>(__src_ptr));
2181+ __insert_node_at (__parent, __child, std::__static_fancy_pointer_cast <__node_base_pointer>(__src_ptr));
21832182 }
21842183}
21852184
@@ -2222,7 +2221,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_merge_multi(__tree<_Tp, _Comp2,
22222221 __node_base_pointer& __child = __find_leaf_high (__parent, __src_ptr->__get_value ());
22232222 ++__i;
22242223 __source.__remove_node_pointer (__src_ptr);
2225- __insert_node_at (__parent, __child, static_cast <__node_base_pointer>(__src_ptr));
2224+ __insert_node_at (__parent, __child, std::__static_fancy_pointer_cast <__node_base_pointer>(__src_ptr));
22262225 }
22272226}
22282227
@@ -2478,12 +2477,12 @@ __tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT {
24782477 __node_pointer __np = __p.__get_np ();
24792478 if (__begin_node_ == __p.__ptr_ ) {
24802479 if (__np->__right_ != nullptr )
2481- __begin_node_ = static_cast <__end_node_pointer>(__np->__right_ );
2480+ __begin_node_ = std::__static_fancy_pointer_cast <__end_node_pointer>(__np->__right_ );
24822481 else
2483- __begin_node_ = static_cast <__end_node_pointer>(__np->__parent_ );
2482+ __begin_node_ = std::__static_fancy_pointer_cast <__end_node_pointer>(__np->__parent_ );
24842483 }
24852484 --__size_;
2486- std::__tree_remove (__end_node ()->__left_ , static_cast <__node_base_pointer>(__np));
2485+ std::__tree_remove (__end_node ()->__left_ , std::__static_fancy_pointer_cast <__node_base_pointer>(__np));
24872486 return __node_holder (__np, _Dp (__node_alloc (), true ));
24882487}
24892488
0 commit comments