@@ -584,6 +584,7 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
584584#include < __cxx03/__memory/allocator.h>
585585#include < __cxx03/__tree>
586586#include < __cxx03/__type_traits/is_allocator.h>
587+ #include < __cxx03/__type_traits/is_standard_layout.h>
587588#include < __cxx03/__utility/forward.h>
588589#include < __cxx03/__utility/piecewise_construct.h>
589590#include < __cxx03/__utility/swap.h>
@@ -616,13 +617,13 @@ public:
616617 : _Compare(__c) {}
617618 _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp () const _NOEXCEPT { return *this ; }
618619 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _CP& __y) const {
619- return static_cast <const _Compare&>(*this )(__x. __get_value ().first , __y. __get_value ().first );
620+ return static_cast <const _Compare&>(*this )(_CP:: __get_value (__x ).first , _CP:: __get_value (__y ).first );
620621 }
621622 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _Key& __y) const {
622- return static_cast <const _Compare&>(*this )(__x. __get_value ().first , __y);
623+ return static_cast <const _Compare&>(*this )(_CP:: __get_value (__x ).first , __y);
623624 }
624625 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _Key& __x, const _CP& __y) const {
625- return static_cast <const _Compare&>(*this )(__x, __y. __get_value ().first );
626+ return static_cast <const _Compare&>(*this )(__x, _CP:: __get_value (__y ).first );
626627 }
627628 _LIBCPP_HIDE_FROM_ABI void swap (__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
628629 using std::swap;
@@ -632,12 +633,12 @@ public:
632633#if _LIBCPP_STD_VER >= 14
633634 template <typename _K2>
634635 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _K2& __x, const _CP& __y) const {
635- return static_cast <const _Compare&>(*this )(__x, __y. __get_value ().first );
636+ return static_cast <const _Compare&>(*this )(__x, _CP:: __get_value (__y ).first );
636637 }
637638
638639 template <typename _K2>
639640 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _K2& __y) const {
640- return static_cast <const _Compare&>(*this )(__x. __get_value ().first , __y);
641+ return static_cast <const _Compare&>(*this )(_CP:: __get_value (__x ).first , __y);
641642 }
642643#endif
643644};
@@ -654,13 +655,13 @@ public:
654655 _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp () const _NOEXCEPT { return __comp_; }
655656
656657 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _CP& __y) const {
657- return __comp_ (__x. __get_value ().first , __y. __get_value ().first );
658+ return __comp_ (_CP:: __get_value (__x ).first , _CP:: __get_value (__y ).first );
658659 }
659660 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _Key& __y) const {
660- return __comp_ (__x. __get_value ().first , __y);
661+ return __comp_ (_CP:: __get_value (__x ).first , __y);
661662 }
662663 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _Key& __x, const _CP& __y) const {
663- return __comp_ (__x, __y. __get_value ().first );
664+ return __comp_ (__x, _CP:: __get_value (__y ).first );
664665 }
665666 void swap (__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
666667 using std::swap;
@@ -670,12 +671,12 @@ public:
670671#if _LIBCPP_STD_VER >= 14
671672 template <typename _K2>
672673 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _K2& __x, const _CP& __y) const {
673- return __comp_ (__x, __y. __get_value ().first );
674+ return __comp_ (__x, _CP:: __get_value (__y ).first );
674675 }
675676
676677 template <typename _K2>
677678 _LIBCPP_HIDE_FROM_ABI bool operator ()(const _CP& __x, const _K2& __y) const {
678- return __comp_ (__x. __get_value ().first , __y);
679+ return __comp_ (_CP:: __get_value (__x ).first , __y);
679680 }
680681#endif
681682};
@@ -691,6 +692,7 @@ template <class _Allocator>
691692class __map_node_destructor {
692693 typedef _Allocator allocator_type;
693694 typedef allocator_traits<allocator_type> __alloc_traits;
695+ typedef __alloc_traits::value_type value_type;
694696
695697public:
696698 typedef typename __alloc_traits::pointer pointer;
@@ -720,9 +722,9 @@ public:
720722
721723 _LIBCPP_HIDE_FROM_ABI void operator ()(pointer __p) _NOEXCEPT {
722724 if (__second_constructed)
723- __alloc_traits::destroy (__na_, std::addressof (__p->__value_ . __get_value ( ).second ));
725+ __alloc_traits::destroy (__na_, std::addressof (value_type::__get_value ( __p->__value_ ).second ));
724726 if (__first_constructed)
725- __alloc_traits::destroy (__na_, std::addressof (__p->__value_ . __get_value ( ).first ));
727+ __alloc_traits::destroy (__na_, std::addressof (value_type::__get_value ( __p->__value_ ).first ));
726728 if (__p)
727729 __alloc_traits::deallocate (__na_, __p, 1 );
728730 }
@@ -749,34 +751,34 @@ private:
749751 value_type __cc_;
750752
751753public:
752- _LIBCPP_HIDE_FROM_ABI value_type& __get_value () {
754+ _LIBCPP_HIDE_FROM_ABI static value_type& __get_value (__hash_value_type& __v ) {
753755# if _LIBCPP_STD_VER >= 17
754- return *std::launder (std::addressof (__cc_ ));
756+ return *std::launder (std::addressof (reinterpret_cast < const value_type&>(__v) ));
755757# else
756- return __cc_ ;
758+ return reinterpret_cast < const value_type&>(__v) ;
757759# endif
758760 }
759761
760- _LIBCPP_HIDE_FROM_ABI const value_type& __get_value () const {
762+ _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value (const __hash_value_type& __v) {
761763# if _LIBCPP_STD_VER >= 17
762- return *std::launder (std::addressof (__cc_ ));
764+ return *std::launder (std::addressof (reinterpret_cast <value_type&>(__v) ));
763765# else
764- return __cc_ ;
766+ return reinterpret_cast <value_type&>(__v) ;
765767# endif
766768 }
767769
768770 _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref () {
769- value_type& __v = __get_value ();
771+ value_type& __v = __get_value (* this );
770772 return __nc_ref_pair_type (const_cast <key_type&>(__v.first ), __v.second );
771773 }
772774
773775 _LIBCPP_HIDE_FROM_ABI __nc_rref_pair_type __move () {
774- value_type& __v = __get_value ();
776+ value_type& __v = __get_value (* this );
775777 return __nc_rref_pair_type (std::move (const_cast <key_type&>(__v.first )), std::move (__v.second ));
776778 }
777779
778780 _LIBCPP_HIDE_FROM_ABI __value_type& operator =(const __value_type& __v) {
779- __ref () = __v. __get_value ();
781+ __ref () = __get_value (__v );
780782 return *this ;
781783 }
782784
@@ -808,9 +810,17 @@ struct __value_type {
808810private:
809811 value_type __cc_;
810812
813+ private:
814+ static_assert (is_standard_layout_v<__hash_value_type<_Key, _Tp>>, " " );
815+
811816public:
812- _LIBCPP_HIDE_FROM_ABI value_type& __get_value () { return __cc_; }
813- _LIBCPP_HIDE_FROM_ABI const value_type& __get_value () const { return __cc_; }
817+ _LIBCPP_HIDE_FROM_ABI static value_type& __get_value (__hash_value_type& __v) {
818+ return reinterpret_cast <value_type&>(__v);
819+ }
820+
821+ _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value (const __hash_value_type& __v) const {
822+ return reinterpret_cast <const value_type&>(__v);
823+ }
814824
815825 __value_type () = delete ;
816826 __value_type (__value_type const &) = delete ;
@@ -847,8 +857,10 @@ public:
847857
848858 _LIBCPP_HIDE_FROM_ABI __map_iterator (_TreeIterator __i) _NOEXCEPT : __i_(__i) {}
849859
850- _LIBCPP_HIDE_FROM_ABI reference operator *() const { return __i_->__get_value (); }
851- _LIBCPP_HIDE_FROM_ABI pointer operator ->() const { return pointer_traits<pointer>::pointer_to (__i_->__get_value ()); }
860+ _LIBCPP_HIDE_FROM_ABI reference operator *() const { return value_type::__get_value (*__i_); }
861+ _LIBCPP_HIDE_FROM_ABI pointer operator ->() const {
862+ return pointer_traits<pointer>::pointer_to (value_type::__get_value (*__i_));
863+ }
852864
853865 _LIBCPP_HIDE_FROM_ABI __map_iterator& operator ++() {
854866 ++__i_;
@@ -905,8 +917,10 @@ public:
905917 _LIBCPP_HIDE_FROM_ABI
906918 __map_const_iterator (__map_iterator< typename _TreeIterator::__non_const_iterator> __i) _NOEXCEPT : __i_(__i.__i_) {}
907919
908- _LIBCPP_HIDE_FROM_ABI reference operator *() const { return __i_->__get_value (); }
909- _LIBCPP_HIDE_FROM_ABI pointer operator ->() const { return pointer_traits<pointer>::pointer_to (__i_->__get_value ()); }
920+ _LIBCPP_HIDE_FROM_ABI reference operator *() const { return value_type::__get_value (*__i_); }
921+ _LIBCPP_HIDE_FROM_ABI pointer operator ->() const {
922+ return pointer_traits<pointer>::pointer_to (value_type::__get_value (*__i_));
923+ }
910924
911925 _LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator ++() {
912926 ++__i_;
@@ -1269,7 +1283,7 @@ public:
12691283 auto [__r, __inserted] = __tree_.__emplace_hint_unique_key_args (__h.__i_ , __k, __k, std::forward<_Vp>(__v));
12701284
12711285 if (!__inserted)
1272- __r-> __get_value ().second = std::forward<_Vp>(__v);
1286+ __value_type:: __get_value (*__r ).second = std::forward<_Vp>(__v);
12731287
12741288 return __r;
12751289 }
@@ -1280,7 +1294,7 @@ public:
12801294 __tree_.__emplace_hint_unique_key_args (__h.__i_ , __k, std::move (__k), std::forward<_Vp>(__v));
12811295
12821296 if (!__inserted)
1283- __r-> __get_value ().second = std::forward<_Vp>(__v);
1297+ __value_type:: __get_value (*__r ).second = std::forward<_Vp>(__v);
12841298
12851299 return __r;
12861300 }
@@ -1492,20 +1506,22 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a)
14921506
14931507template <class _Key , class _Tp , class _Compare , class _Allocator >
14941508_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator [](const key_type& __k) {
1495- return __tree_
1496- .__emplace_unique_key_args (__k, std::piecewise_construct, std::forward_as_tuple (__k), std::forward_as_tuple ())
1497- .first ->__get_value ()
1509+ return _Tp::__get_value (__tree_
1510+ .__emplace_unique_key_args (
1511+ __k, std::piecewise_construct, std::forward_as_tuple (__k), std::forward_as_tuple ())
1512+ .first )
14981513 .second ;
14991514}
15001515
15011516template <class _Key , class _Tp , class _Compare , class _Allocator >
15021517_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator [](key_type&& __k) {
15031518 // TODO investigate this clang-tidy warning.
15041519 // NOLINTBEGIN(bugprone-use-after-move)
1505- return __tree_
1506- .__emplace_unique_key_args (
1507- __k, std::piecewise_construct, std::forward_as_tuple (std::move (__k)), std::forward_as_tuple ())
1508- .first ->__get_value ()
1520+ return _Tp::__get_value (
1521+ __tree_
1522+ .__emplace_unique_key_args (
1523+ __k, std::piecewise_construct, std::forward_as_tuple (std::move (__k)), std::forward_as_tuple ())
1524+ .first )
15091525 .second ;
15101526 // NOLINTEND(bugprone-use-after-move)
15111527}
@@ -1517,9 +1533,9 @@ typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder
15171533map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(const key_type& __k) {
15181534 __node_allocator& __na = __tree_.__node_alloc ();
15191535 __node_holder __h (__node_traits::allocate (__na, 1 ), _Dp (__na));
1520- __node_traits::construct (__na, std::addressof (__h->__value_ . __get_value ( ).first ), __k);
1536+ __node_traits::construct (__na, std::addressof (_Tp::__get_value ( __h->__value_ ).first ), __k);
15211537 __h.get_deleter ().__first_constructed = true ;
1522- __node_traits::construct (__na, std::addressof (__h->__value_ . __get_value ( ).second ));
1538+ __node_traits::construct (__na, std::addressof (_Tp::__get_value ( __h->__value_ ).second ));
15231539 __h.get_deleter ().__second_constructed = true ;
15241540 return __h;
15251541}
@@ -1534,7 +1550,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) {
15341550 __tree_.__insert_node_at (__parent, __child, static_cast <__node_base_pointer>(__h.get ()));
15351551 __r = __h.release ();
15361552 }
1537- return __r->__value_ . __get_value ( ).second ;
1553+ return _Tp::__get_value ( __r->__value_ ).second ;
15381554}
15391555
15401556#endif // _LIBCPP_CXX03_LANG
@@ -1545,7 +1561,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) {
15451561 __node_base_pointer& __child = __tree_.__find_equal (__parent, __k);
15461562 if (__child == nullptr )
15471563 __throw_out_of_range (" map::at: key not found" );
1548- return static_cast <__node_pointer>(__child)->__value_ . __get_value ( ).second ;
1564+ return _Tp::__get_value ( static_cast <__node_pointer>(__child)->__value_ ).second ;
15491565}
15501566
15511567template <class _Key , class _Tp , class _Compare , class _Allocator >
@@ -1554,7 +1570,7 @@ const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const {
15541570 __node_base_pointer __child = __tree_.__find_equal (__parent, __k);
15551571 if (__child == nullptr )
15561572 __throw_out_of_range (" map::at: key not found" );
1557- return static_cast <__node_pointer>(__child)->__value_ . __get_value ( ).second ;
1573+ return _Tp::__get_value ( static_cast <__node_pointer>(__child)->__value_ ).second ;
15581574}
15591575
15601576template <class _Key , class _Tp , class _Compare , class _Allocator >
0 commit comments