@@ -592,6 +592,7 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
592592#include < __cxx03/__ranges/from_range.h>
593593#include < __cxx03/__tree>
594594#include < __cxx03/__type_traits/is_allocator.h>
595+ #include < __cxx03/__type_traits/is_standard_layout.h>
595596#include < __cxx03/__utility/forward.h>
596597#include < __cxx03/__utility/piecewise_construct.h>
597598#include < __cxx03/__utility/swap.h>
@@ -633,13 +634,13 @@ public:
633634 : _Compare(__c) {}
634635 _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp () const _NOEXCEPT { return *this ; }
635636 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _CP& __y) const {
636- return static_cast <const _Compare&>(*this )(__x. __get_value ().first , __y. __get_value ().first );
637+ return static_cast <const _Compare&>(*this )(_CP:: __get_value (__x ).first , _CP:: __get_value (__y ).first );
637638 }
638639 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _Key& __y) const {
639- return static_cast <const _Compare&>(*this )(__x. __get_value ().first , __y);
640+ return static_cast <const _Compare&>(*this )(_CP:: __get_value (__x ).first , __y);
640641 }
641642 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _Key& __x, const _CP& __y) const {
642- return static_cast <const _Compare&>(*this )(__x, __y. __get_value ().first );
643+ return static_cast <const _Compare&>(*this )(__x, _CP:: __get_value (__y ).first );
643644 }
644645 _LIBCPP_HIDE_FROM_ABI void swap (__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
645646 using std::swap;
@@ -649,12 +650,12 @@ public:
649650#if _LIBCPP_STD_VER >= 14
650651 template <typename _K2>
651652 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _K2& __x, const _CP& __y) const {
652- return static_cast <const _Compare&>(*this )(__x, __y. __get_value ().first );
653+ return static_cast <const _Compare&>(*this )(__x, _CP:: __get_value (__y ).first );
653654 }
654655
655656 template <typename _K2>
656657 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _K2& __y) const {
657- return static_cast <const _Compare&>(*this )(__x. __get_value ().first , __y);
658+ return static_cast <const _Compare&>(*this )(_CP:: __get_value (__x ).first , __y);
658659 }
659660#endif
660661};
@@ -671,13 +672,13 @@ public:
671672 _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp () const _NOEXCEPT { return __comp_; }
672673
673674 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _CP& __y) const {
674- return __comp_ (__x. __get_value ().first , __y. __get_value ().first );
675+ return __comp_ (_CP:: __get_value (__x ).first , _CP:: __get_value (__y ).first );
675676 }
676677 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _Key& __y) const {
677- return __comp_ (__x. __get_value ().first , __y);
678+ return __comp_ (_CP:: __get_value (__x ).first , __y);
678679 }
679680 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _Key& __x, const _CP& __y) const {
680- return __comp_ (__x, __y. __get_value ().first );
681+ return __comp_ (__x, _CP:: __get_value (__y ).first );
681682 }
682683 void swap (__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
683684 using std::swap;
@@ -687,12 +688,12 @@ public:
687688#if _LIBCPP_STD_VER >= 14
688689 template <typename _K2>
689690 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _K2& __x, const _CP& __y) const {
690- return __comp_ (__x, __y. __get_value ().first );
691+ return __comp_ (__x, _CP:: __get_value (__y ).first );
691692 }
692693
693694 template <typename _K2>
694695 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _K2& __y) const {
695- return __comp_ (__x. __get_value ().first , __y);
696+ return __comp_ (_CP:: __get_value (__x ).first , __y);
696697 }
697698#endif
698699};
@@ -708,6 +709,7 @@ template <class _Allocator>
708709class __map_node_destructor {
709710 typedef _Allocator allocator_type;
710711 typedef allocator_traits<allocator_type> __alloc_traits;
712+ typedef __alloc_traits::value_type value_type;
711713
712714public:
713715 typedef typename __alloc_traits::pointer pointer;
@@ -737,9 +739,9 @@ public:
737739
738740 _LIBCPP_HIDE_FROM_ABI void operator ()(pointer __p) _NOEXCEPT {
739741 if (__second_constructed)
740- __alloc_traits::destroy (__na_, std::addressof (__p->__value_ . __get_value ( ).second ));
742+ __alloc_traits::destroy (__na_, std::addressof (value_type::__get_value ( __p->__value_ ).second ));
741743 if (__first_constructed)
742- __alloc_traits::destroy (__na_, std::addressof (__p->__value_ . __get_value ( ).first ));
744+ __alloc_traits::destroy (__na_, std::addressof (value_type::__get_value ( __p->__value_ ).first ));
743745 if (__p)
744746 __alloc_traits::deallocate (__na_, __p, 1 );
745747 }
@@ -765,35 +767,38 @@ struct _LIBCPP_STANDALONE_DEBUG __value_type {
765767private:
766768 value_type __cc_;
767769
770+ private:
771+ static_assert (is_standard_layout_v<__hash_value_type<_Key, _Tp>>, " " );
772+
768773public:
769- _LIBCPP_HIDE_FROM_ABI value_type& __get_value () {
774+ _LIBCPP_HIDE_FROM_ABI static value_type& __get_value (__hash_value_type& __v ) {
770775# if _LIBCPP_STD_VER >= 17
771- return *std::launder (std::addressof (__cc_ ));
776+ return *std::launder (std::addressof (reinterpret_cast <value_type&>(__v) ));
772777# else
773- return __cc_ ;
778+ return reinterpret_cast <value_type&>(__v) ;
774779# endif
775780 }
776781
777- _LIBCPP_HIDE_FROM_ABI const value_type& __get_value () const {
782+ _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value (const __hash_value_type& __v) {
778783# if _LIBCPP_STD_VER >= 17
779- return *std::launder (std::addressof (__cc_ ));
784+ return *std::launder (std::addressof (reinterpret_cast < const value_type&>(__v) ));
780785# else
781- return __cc_ ;
786+ return reinterpret_cast < const value_type&>(__v) ;
782787# endif
783788 }
784789
785790 _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref () {
786- value_type& __v = __get_value ();
791+ value_type& __v = __get_value (* this );
787792 return __nc_ref_pair_type (const_cast <key_type&>(__v.first ), __v.second );
788793 }
789794
790795 _LIBCPP_HIDE_FROM_ABI __nc_rref_pair_type __move () {
791- value_type& __v = __get_value ();
796+ value_type& __v = __get_value (* this );
792797 return __nc_rref_pair_type (std::move (const_cast <key_type&>(__v.first )), std::move (__v.second ));
793798 }
794799
795800 _LIBCPP_HIDE_FROM_ABI __value_type& operator =(const __value_type& __v) {
796- __ref () = __v. __get_value ();
801+ __ref () = __get_value (__v );
797802 return *this ;
798803 }
799804
@@ -826,8 +831,13 @@ private:
826831 value_type __cc_;
827832
828833public:
829- _LIBCPP_HIDE_FROM_ABI value_type& __get_value () { return __cc_; }
830- _LIBCPP_HIDE_FROM_ABI const value_type& __get_value () const { return __cc_; }
834+ _LIBCPP_HIDE_FROM_ABI static value_type& __get_value (__hash_value_type& __v) {
835+ return reinterpret_cast <value_type&>(__v);
836+ }
837+
838+ _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value (const __hash_value_type& __v) const {
839+ return reinterpret_cast <const value_type&>(__v);
840+ }
831841
832842 __value_type () = delete ;
833843 __value_type (__value_type const &) = delete ;
@@ -864,8 +874,10 @@ public:
864874
865875 _LIBCPP_HIDE_FROM_ABI __map_iterator (_TreeIterator __i) _NOEXCEPT : __i_(__i) {}
866876
867- _LIBCPP_HIDE_FROM_ABI reference operator *() const { return __i_->__get_value (); }
868- _LIBCPP_HIDE_FROM_ABI pointer operator ->() const { return pointer_traits<pointer>::pointer_to (__i_->__get_value ()); }
877+ _LIBCPP_HIDE_FROM_ABI reference operator *() const { return value_type::__get_value (*__i_); }
878+ _LIBCPP_HIDE_FROM_ABI pointer operator ->() const {
879+ return pointer_traits<pointer>::pointer_to (value_type::__get_value (*__i_));
880+ }
869881
870882 _LIBCPP_HIDE_FROM_ABI __map_iterator& operator ++() {
871883 ++__i_;
@@ -922,8 +934,10 @@ public:
922934 _LIBCPP_HIDE_FROM_ABI
923935 __map_const_iterator (__map_iterator< typename _TreeIterator::__non_const_iterator> __i) _NOEXCEPT : __i_(__i.__i_) {}
924936
925- _LIBCPP_HIDE_FROM_ABI reference operator *() const { return __i_->__get_value (); }
926- _LIBCPP_HIDE_FROM_ABI pointer operator ->() const { return pointer_traits<pointer>::pointer_to (__i_->__get_value ()); }
937+ _LIBCPP_HIDE_FROM_ABI reference operator *() const { return value_type::__get_value (*__i_); }
938+ _LIBCPP_HIDE_FROM_ABI pointer operator ->() const {
939+ return pointer_traits<pointer>::pointer_to (value_type::__get_value (*__i_));
940+ }
927941
928942 _LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator ++() {
929943 ++__i_;
@@ -1286,7 +1300,7 @@ public:
12861300 auto [__r, __inserted] = __tree_.__emplace_hint_unique_key_args (__h.__i_ , __k, __k, std::forward<_Vp>(__v));
12871301
12881302 if (!__inserted)
1289- __r-> __get_value ().second = std::forward<_Vp>(__v);
1303+ __value_type:: __get_value (*__r ).second = std::forward<_Vp>(__v);
12901304
12911305 return __r;
12921306 }
@@ -1297,7 +1311,7 @@ public:
12971311 __tree_.__emplace_hint_unique_key_args (__h.__i_ , __k, std::move (__k), std::forward<_Vp>(__v));
12981312
12991313 if (!__inserted)
1300- __r-> __get_value ().second = std::forward<_Vp>(__v);
1314+ __value_type:: __get_value (*__r ).second = std::forward<_Vp>(__v);
13011315
13021316 return __r;
13031317 }
@@ -1509,20 +1523,22 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a)
15091523
15101524template <class _Key , class _Tp , class _Compare , class _Allocator >
15111525_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator [](const key_type& __k) {
1512- return __tree_
1513- .__emplace_unique_key_args (__k, std::piecewise_construct, std::forward_as_tuple (__k), std::forward_as_tuple ())
1514- .first ->__get_value ()
1526+ return _Tp::__get_value (__tree_
1527+ .__emplace_unique_key_args (
1528+ __k, std::piecewise_construct, std::forward_as_tuple (__k), std::forward_as_tuple ())
1529+ .first )
15151530 .second ;
15161531}
15171532
15181533template <class _Key , class _Tp , class _Compare , class _Allocator >
15191534_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator [](key_type&& __k) {
15201535 // TODO investigate this clang-tidy warning.
15211536 // NOLINTBEGIN(bugprone-use-after-move)
1522- return __tree_
1523- .__emplace_unique_key_args (
1524- __k, std::piecewise_construct, std::forward_as_tuple (std::move (__k)), std::forward_as_tuple ())
1525- .first ->__get_value ()
1537+ return _Tp::__get_value (
1538+ __tree_
1539+ .__emplace_unique_key_args (
1540+ __k, std::piecewise_construct, std::forward_as_tuple (std::move (__k)), std::forward_as_tuple ())
1541+ .first )
15261542 .second ;
15271543 // NOLINTEND(bugprone-use-after-move)
15281544}
@@ -1534,9 +1550,9 @@ typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder
15341550map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(const key_type& __k) {
15351551 __node_allocator& __na = __tree_.__node_alloc ();
15361552 __node_holder __h (__node_traits::allocate (__na, 1 ), _Dp (__na));
1537- __node_traits::construct (__na, std::addressof (__h->__value_ . __get_value ( ).first ), __k);
1553+ __node_traits::construct (__na, std::addressof (_Tp::__get_value ( __h->__value_ ).first ), __k);
15381554 __h.get_deleter ().__first_constructed = true ;
1539- __node_traits::construct (__na, std::addressof (__h->__value_ . __get_value ( ).second ));
1555+ __node_traits::construct (__na, std::addressof (_Tp::__get_value ( __h->__value_ ).second ));
15401556 __h.get_deleter ().__second_constructed = true ;
15411557 return __h;
15421558}
@@ -1551,7 +1567,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) {
15511567 __tree_.__insert_node_at (__parent, __child, static_cast <__node_base_pointer>(__h.get ()));
15521568 __r = __h.release ();
15531569 }
1554- return __r->__value_ . __get_value ( ).second ;
1570+ return _Tp::__get_value ( __r->__value_ ).second ;
15551571}
15561572
15571573#endif // _LIBCPP_CXX03_LANG
@@ -1562,7 +1578,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) {
15621578 __node_base_pointer& __child = __tree_.__find_equal (__parent, __k);
15631579 if (__child == nullptr )
15641580 __throw_out_of_range (" map::at: key not found" );
1565- return static_cast <__node_pointer>(__child)->__value_ . __get_value ( ).second ;
1581+ return _Tp::__get_value ( static_cast <__node_pointer>(__child)->__value_ ).second ;
15661582}
15671583
15681584template <class _Key , class _Tp , class _Compare , class _Allocator >
@@ -1571,7 +1587,7 @@ const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const {
15711587 __node_base_pointer __child = __tree_.__find_equal (__parent, __k);
15721588 if (__child == nullptr )
15731589 __throw_out_of_range (" map::at: key not found" );
1574- return static_cast <__node_pointer>(__child)->__value_ . __get_value ( ).second ;
1590+ return _Tp::__get_value ( static_cast <__node_pointer>(__child)->__value_ ).second ;
15751591}
15761592
15771593template <class _Key , class _Tp , class _Compare , class _Allocator >
0 commit comments