diff --git a/libcxx/include/__cxx03/__hash_table b/libcxx/include/__cxx03/__hash_table index a4eff8c654f11..4ffe633b14501 100644 --- a/libcxx/include/__cxx03/__hash_table +++ b/libcxx/include/__cxx03/__hash_table @@ -183,7 +183,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) { - return __t.__get_value(); + return _Up::__get_value(__t); } template ::value, int> = 0> @@ -192,7 +192,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { } _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { - return std::addressof(__n.__get_value()); + return std::addressof(__node_value_type::__get_value(__n)); } _LIBCPP_HIDE_FROM_ABI static pair __move(__node_value_type& __v) { return __v.__move(); } }; diff --git a/libcxx/include/__cxx03/__tree b/libcxx/include/__cxx03/__tree index aec20a7541b26..1c4cd18804817 100644 --- a/libcxx/include/__cxx03/__tree +++ b/libcxx/include/__cxx03/__tree @@ -533,7 +533,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > { static const bool __is_map = true; _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__node_value_type const& __t) { - return __t.__get_value().first; + return __node_value_type::__get_value(__t).first; } template ::value, int> = 0> @@ -542,7 +542,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > { } _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __t) { - return __t.__get_value(); + return __node_value_type::__get_value(__t); } template ::value, int> = 0> @@ -551,7 +551,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > { } _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { - return std::addressof(__n.__get_value()); + return std::addressof(__node_value_type::__get_value(__n)); } _LIBCPP_HIDE_FROM_ABI static pair __move(__node_value_type& __v) { return __v.__move(); } diff --git a/libcxx/include/__cxx03/map b/libcxx/include/__cxx03/map index ca097f583acc0..3371f3d7dcd3f 100644 --- a/libcxx/include/__cxx03/map +++ b/libcxx/include/__cxx03/map @@ -584,6 +584,7 @@ erase_if(multimap& c, Predicate pred); // C++20 #include <__cxx03/__memory/allocator.h> #include <__cxx03/__tree> #include <__cxx03/__type_traits/is_allocator.h> +#include <__cxx03/__type_traits/is_standard_layout.h> #include <__cxx03/__utility/forward.h> #include <__cxx03/__utility/piecewise_construct.h> #include <__cxx03/__utility/swap.h> @@ -616,13 +617,13 @@ public: : _Compare(__c) {} _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return *this; } _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const { - return static_cast(*this)(__x.__get_value().first, __y.__get_value().first); + return static_cast(*this)(_CP::__get_value(__x).first, _CP::__get_value(__y).first); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const { - return static_cast(*this)(__x.__get_value().first, __y); + return static_cast(*this)(_CP::__get_value(__x).first, __y); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const { - return static_cast(*this)(__x, __y.__get_value().first); + return static_cast(*this)(__x, _CP::__get_value(__y).first); } _LIBCPP_HIDE_FROM_ABI void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) { using std::swap; @@ -632,12 +633,12 @@ public: #if _LIBCPP_STD_VER >= 14 template _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const { - return static_cast(*this)(__x, __y.__get_value().first); + return static_cast(*this)(__x, _CP::__get_value(__y).first); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const { - return static_cast(*this)(__x.__get_value().first, __y); + return static_cast(*this)(_CP::__get_value(__x).first, __y); } #endif }; @@ -654,13 +655,13 @@ public: _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return __comp_; } _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const { - return __comp_(__x.__get_value().first, __y.__get_value().first); + return __comp_(_CP::__get_value(__x).first, _CP::__get_value(__y).first); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const { - return __comp_(__x.__get_value().first, __y); + return __comp_(_CP::__get_value(__x).first, __y); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const { - return __comp_(__x, __y.__get_value().first); + return __comp_(__x, _CP::__get_value(__y).first); } void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) { using std::swap; @@ -670,12 +671,12 @@ public: #if _LIBCPP_STD_VER >= 14 template _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const { - return __comp_(__x, __y.__get_value().first); + return __comp_(__x, _CP::__get_value(__y).first); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const { - return __comp_(__x.__get_value().first, __y); + return __comp_(_CP::__get_value(__x).first, __y); } #endif }; @@ -691,6 +692,7 @@ template class __map_node_destructor { typedef _Allocator allocator_type; typedef allocator_traits __alloc_traits; + typedef __alloc_traits::value_type value_type; public: typedef typename __alloc_traits::pointer pointer; @@ -720,9 +722,9 @@ public: _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { if (__second_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__value_.__get_value().second)); + __alloc_traits::destroy(__na_, std::addressof(value_type::__get_value(__p->__value_).second)); if (__first_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__value_.__get_value().first)); + __alloc_traits::destroy(__na_, std::addressof(value_type::__get_value(__p->__value_).first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } @@ -749,34 +751,34 @@ private: value_type __cc_; public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { + _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) { # if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); + return *std::launder(std::addressof(reinterpret_cast(__v))); # else - return __cc_; + return reinterpret_cast(__v); # endif } - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { + _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) { # if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); + return *std::launder(std::addressof(reinterpret_cast(__v))); # else - return __cc_; + return reinterpret_cast(__v); # endif } _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref() { - value_type& __v = __get_value(); + value_type& __v = __get_value(*this); return __nc_ref_pair_type(const_cast(__v.first), __v.second); } _LIBCPP_HIDE_FROM_ABI __nc_rref_pair_type __move() { - value_type& __v = __get_value(); + value_type& __v = __get_value(*this); return __nc_rref_pair_type(std::move(const_cast(__v.first)), std::move(__v.second)); } _LIBCPP_HIDE_FROM_ABI __value_type& operator=(const __value_type& __v) { - __ref() = __v.__get_value(); + __ref() = __get_value(__v); return *this; } @@ -808,9 +810,17 @@ struct __value_type { private: value_type __cc_; +private: + static_assert(is_standard_layout_v<__hash_value_type<_Key, _Tp>>, ""); + public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { return __cc_; } - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { return __cc_; } + _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) { + return reinterpret_cast(__v); + } + + _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) const { + return reinterpret_cast(__v); + } __value_type() = delete; __value_type(__value_type const&) = delete; @@ -847,8 +857,10 @@ public: _LIBCPP_HIDE_FROM_ABI __map_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__i_->__get_value()); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return value_type::__get_value(*__i_); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + return pointer_traits::pointer_to(value_type::__get_value(*__i_)); + } _LIBCPP_HIDE_FROM_ABI __map_iterator& operator++() { ++__i_; @@ -905,8 +917,10 @@ public: _LIBCPP_HIDE_FROM_ABI __map_const_iterator(__map_iterator< typename _TreeIterator::__non_const_iterator> __i) _NOEXCEPT : __i_(__i.__i_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__i_->__get_value()); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return value_type::__get_value(*__i_); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + return pointer_traits::pointer_to(value_type::__get_value(*__i_)); + } _LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator++() { ++__i_; @@ -1269,7 +1283,7 @@ public: auto [__r, __inserted] = __tree_.__emplace_hint_unique_key_args(__h.__i_, __k, __k, std::forward<_Vp>(__v)); if (!__inserted) - __r->__get_value().second = std::forward<_Vp>(__v); + __value_type::__get_value(*__r).second = std::forward<_Vp>(__v); return __r; } @@ -1280,7 +1294,7 @@ public: __tree_.__emplace_hint_unique_key_args(__h.__i_, __k, std::move(__k), std::forward<_Vp>(__v)); if (!__inserted) - __r->__get_value().second = std::forward<_Vp>(__v); + __value_type::__get_value(*__r).second = std::forward<_Vp>(__v); return __r; } @@ -1492,9 +1506,10 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) template _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { - return __tree_ - .__emplace_unique_key_args(__k, std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple()) - .first->__get_value() + return _Tp::__get_value(__tree_ + .__emplace_unique_key_args( + __k, std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple()) + .first) .second; } @@ -1502,10 +1517,11 @@ template _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k) { // TODO investigate this clang-tidy warning. // NOLINTBEGIN(bugprone-use-after-move) - return __tree_ - .__emplace_unique_key_args( - __k, std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple()) - .first->__get_value() + return _Tp::__get_value( + __tree_ + .__emplace_unique_key_args( + __k, std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple()) + .first) .second; // NOLINTEND(bugprone-use-after-move) } @@ -1517,9 +1533,9 @@ typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(const key_type& __k) { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - __node_traits::construct(__na, std::addressof(__h->__value_.__get_value().first), __k); + __node_traits::construct(__na, std::addressof(_Tp::__get_value(__h->__value_).first), __k); __h.get_deleter().__first_constructed = true; - __node_traits::construct(__na, std::addressof(__h->__value_.__get_value().second)); + __node_traits::construct(__na, std::addressof(_Tp::__get_value(__h->__value_).second)); __h.get_deleter().__second_constructed = true; return __h; } @@ -1534,7 +1550,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { __tree_.__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); __r = __h.release(); } - return __r->__value_.__get_value().second; + return _Tp::__get_value(__r->__value_).second; } #endif // _LIBCPP_CXX03_LANG @@ -1545,7 +1561,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) { __node_base_pointer& __child = __tree_.__find_equal(__parent, __k); if (__child == nullptr) __throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__value_.__get_value().second; + return _Tp::__get_value(static_cast<__node_pointer>(__child)->__value_).second; } template @@ -1554,7 +1570,7 @@ const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const { __node_base_pointer __child = __tree_.__find_equal(__parent, __k); if (__child == nullptr) __throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__value_.__get_value().second; + return _Tp::__get_value(static_cast<__node_pointer>(__child)->__value_).second; } template diff --git a/libcxx/include/__cxx03/unordered_map b/libcxx/include/__cxx03/unordered_map index 10e84f35a3578..647c00a5a0594 100644 --- a/libcxx/include/__cxx03/unordered_map +++ b/libcxx/include/__cxx03/unordered_map @@ -594,6 +594,7 @@ template #include <__cxx03/__memory/addressof.h> #include <__cxx03/__memory/allocator.h> #include <__cxx03/__type_traits/is_allocator.h> +#include <__cxx03/__type_traits/is_standard_layout.h> #include <__cxx03/__type_traits/type_identity.h> #include <__cxx03/__utility/forward.h> #include <__cxx03/stdexcept> @@ -823,30 +824,33 @@ struct _LIBCPP_STANDALONE_DEBUG __hash_value_type { private: value_type __cc_; +private: + static_assert(std::is_standard_layout_v<__hash_value_type<_Key, _Tp>>, ""); + public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { + _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) { # if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); + return *std::launder(std::addressof(reinterpret_cast(__v))); # else - return __cc_; + return reinterpret_cast(__v); # endif } - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { + _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) { # if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); + return *std::launder(std::addressof(reinterpret_cast(__v))); # else - return __cc_; + return reinterpret_cast(__v); # endif } _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref() { - value_type& __v = __get_value(); + value_type& __v = __get_value(*this); return __nc_ref_pair_type(const_cast(__v.first), __v.second); } _LIBCPP_HIDE_FROM_ABI __nc_rref_pair_type __move() { - value_type& __v = __get_value(); + value_type& __v = __get_value(*this); return __nc_rref_pair_type(std::move(const_cast(__v.first)), std::move(__v.second)); } @@ -885,9 +889,17 @@ struct __hash_value_type { private: value_type __cc_; +private: + static_assert(is_standard_layout_v<__hash_value_type<_Key, _Tp>>, ""); + public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { return __cc_; } - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { return __cc_; } + _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) { + return reinterpret_cast(__v); + } + + _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) const { + return reinterpret_cast(__v); + } ~__hash_value_type() = delete; }; diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index fca58ca296067..9bcf042a9306e 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -193,7 +193,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) { - return __t.__get_value(); + return __node_value_type::__get_value(__t); } template ::value, int> = 0> @@ -202,7 +202,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { } _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { - return std::addressof(__n.__get_value()); + return std::addressof(__node_value_type::__get_value(__n)); } _LIBCPP_HIDE_FROM_ABI static pair __move(__node_value_type& __v) { return __v.__move(); } }; diff --git a/libcxx/include/__tree b/libcxx/include/__tree index e84bc4ffda0bd..bcb25924b0bed 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -534,7 +534,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > { } _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __t) { - return __t.__get_value(); + return __node_value_type::__get_value(__t); } template ::value, int> = 0> @@ -543,7 +543,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > { } _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { - return std::addressof(__n.__get_value()); + return std::addressof(__node_value_type::__get_value(__n)); } _LIBCPP_HIDE_FROM_ABI static pair __move(__node_value_type& __v) { return __v.__move(); } diff --git a/libcxx/include/ext/hash_map b/libcxx/include/ext/hash_map index da2a34aa56dfb..d5f7f7e02d128 100644 --- a/libcxx/include/ext/hash_map +++ b/libcxx/include/ext/hash_map @@ -329,9 +329,9 @@ public: _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) { if (__second_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().second)); + __alloc_traits::destroy(__na_, std::addressof(value_type::__get_value(*__p).second)); if (__first_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().first)); + __alloc_traits::destroy(__na_, std::addressof(value_type::__get_value(*__p).first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } @@ -614,9 +614,9 @@ typename hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node(const key_type& __k) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - __node_traits::construct(__na, std::addressof(__h->__get_value().first), __k); + __node_traits::construct(__na, std::addressof(_Tp::__get_value(*__h).first, __k); __h.get_deleter().__first_constructed = true; - __node_traits::construct(__na, std::addressof(__h->__get_value().second)); + __node_traits::construct(__na, std::addressof(_Tp::__get_value(*__h).second)); __h.get_deleter().__second_constructed = true; return __h; } diff --git a/libcxx/include/map b/libcxx/include/map index a244696295fb8..cb1ded3b7af0b 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -601,6 +601,7 @@ erase_if(multimap& c, Predicate pred); // C++20 # include <__tree> # include <__type_traits/container_traits.h> # include <__type_traits/is_allocator.h> +# include <__type_traits/is_standard_layout.h> # include <__type_traits/remove_const.h> # include <__type_traits/type_identity.h> # include <__utility/forward.h> @@ -645,13 +646,13 @@ public: : _Compare(__c) {} _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return *this; } _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const { - return static_cast(*this)(__x.__get_value().first, __y.__get_value().first); + return static_cast(*this)(_CP::__get_value(__x).first, _CP::__get_value(__y).first); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const { - return static_cast(*this)(__x.__get_value().first, __y); + return static_cast(*this)(_CP::__get_value(__x).first, __y); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const { - return static_cast(*this)(__x, __y.__get_value().first); + return static_cast(*this)(__x, _CP::__get_value(__y).first); } _LIBCPP_HIDE_FROM_ABI void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) { using std::swap; @@ -661,12 +662,12 @@ public: # if _LIBCPP_STD_VER >= 14 template _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const { - return static_cast(*this)(__x, __y.__get_value().first); + return static_cast(*this)(__x, _CP::__get_value(__y).first); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const { - return static_cast(*this)(__x.__get_value().first, __y); + return static_cast(*this)(_CP::__get_value(__x).first, __y); } # endif }; @@ -683,13 +684,13 @@ public: _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return __comp_; } _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const { - return __comp_(__x.__get_value().first, __y.__get_value().first); + return __comp_(_CP::__get_value(__x).first, _CP::__get_value(__y).first); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const { - return __comp_(__x.__get_value().first, __y); + return __comp_(_CP::__get_value(__x).first, __y); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const { - return __comp_(__x, __y.__get_value().first); + return __comp_(__x, _CP::__get_value(__y).first); } void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) { using std::swap; @@ -699,12 +700,12 @@ public: # if _LIBCPP_STD_VER >= 14 template _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const { - return __comp_(__x, __y.__get_value().first); + return __comp_(__x, _CP::__get_value(__y).first); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const { - return __comp_(__x.__get_value().first, __y); + return __comp_(_CP::__get_value(__x).first, __y); } # endif }; @@ -749,9 +750,9 @@ public: _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { if (__second_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__value_.__get_value().second)); + __alloc_traits::destroy(__na_, std::addressof(_CP::__get_value(__p->__value_).second)); if (__first_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__value_.__get_value().first)); + __alloc_traits::destroy(__na_, std::addressof(_CP::__get_value(__p->__value_).first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } @@ -773,35 +774,38 @@ struct _LIBCPP_STANDALONE_DEBUG __value_type { private: value_type __cc_; +private: + static_assert(is_standard_layout_v<__hash_value_type<_Key, _Tp>>, ""); + public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { + _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) { # if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); + return *std::launder(std::addressof(reinterpret_cast(__v))); # else - return __cc_; + return reinterpret_cast(__v); # endif } - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { + _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) { # if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); + return *std::launder(std::addressof(reinterpret_cast(__v))); # else - return __cc_; + return reinterpret_cast(__v); # endif } _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref() { - value_type& __v = __get_value(); + value_type& __v = __get_value(*this); return __nc_ref_pair_type(const_cast(__v.first), __v.second); } _LIBCPP_HIDE_FROM_ABI __nc_rref_pair_type __move() { - value_type& __v = __get_value(); + value_type& __v = __get_value(*this); return __nc_rref_pair_type(std::move(const_cast(__v.first)), std::move(__v.second)); } _LIBCPP_HIDE_FROM_ABI __value_type& operator=(const __value_type& __v) { - __ref() = __v.__get_value(); + __ref() = __get_value(__v); return *this; } @@ -834,8 +838,13 @@ private: value_type __cc_; public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { return __cc_; } - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { return __cc_; } + _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) { + return reinterpret_cast(__v); + } + + _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) const { + return reinterpret_cast(__v); + } __value_type() = delete; __value_type(__value_type const&) = delete; @@ -872,8 +881,10 @@ public: _LIBCPP_HIDE_FROM_ABI __map_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__i_->__get_value()); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return value_type::__get_value(*__i_); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + return pointer_traits::pointer_to(value_type::__get_value(*__i_)); + } _LIBCPP_HIDE_FROM_ABI __map_iterator& operator++() { ++__i_; @@ -930,8 +941,10 @@ public: _LIBCPP_HIDE_FROM_ABI __map_const_iterator(__map_iterator< typename _TreeIterator::__non_const_iterator> __i) _NOEXCEPT : __i_(__i.__i_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__i_->__get_value()); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return value_type::__get_value(*__i_); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + return pointer_traits::pointer_to(value_type::__get_value(*__i_)); + } _LIBCPP_HIDE_FROM_ABI __map_const_iterator& operator++() { ++__i_; @@ -1294,7 +1307,7 @@ public: auto [__r, __inserted] = __tree_.__emplace_hint_unique_key_args(__h.__i_, __k, __k, std::forward<_Vp>(__v)); if (!__inserted) - __r->__get_value().second = std::forward<_Vp>(__v); + __value_type::__get_value(*__r).second = std::forward<_Vp>(__v); return __r; } @@ -1305,7 +1318,7 @@ public: __tree_.__emplace_hint_unique_key_args(__h.__i_, __k, std::move(__k), std::forward<_Vp>(__v)); if (!__inserted) - __r->__get_value().second = std::forward<_Vp>(__v); + __value_type::__get_value(__r).second = std::forward<_Vp>(__v); return __r; } @@ -1517,9 +1530,10 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a) template _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { - return __tree_ - .__emplace_unique_key_args(__k, std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple()) - .first->__get_value() + return _Tp::__get_value(*__tree_ + .__emplace_unique_key_args( + __k, std::piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple()) + .first) .second; } @@ -1527,10 +1541,11 @@ template _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k) { // TODO investigate this clang-tidy warning. // NOLINTBEGIN(bugprone-use-after-move) - return __tree_ - .__emplace_unique_key_args( - __k, std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple()) - .first->__get_value() + return _Tp::__get_value( + *__tree_ + .__emplace_unique_key_args( + __k, std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple()) + .first) .second; // NOLINTEND(bugprone-use-after-move) } @@ -1542,9 +1557,9 @@ typename map<_Key, _Tp, _Compare, _Allocator>::__node_holder map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(const key_type& __k) { __node_allocator& __na = __tree_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - __node_traits::construct(__na, std::addressof(__h->__value_.__get_value().first), __k); + __node_traits::construct(__na, std::addressof(_Tp::__get_value(__h->__value_).first), __k); __h.get_deleter().__first_constructed = true; - __node_traits::construct(__na, std::addressof(__h->__value_.__get_value().second)); + __node_traits::construct(__na, std::addressof(_Tp::__get_value(__h->__value_).second)); __h.get_deleter().__second_constructed = true; return __h; } @@ -1559,7 +1574,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) { __tree_.__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); __r = __h.release(); } - return __r->__value_.__get_value().second; + return _Tp::__get_value(__r->__value_).second; } # endif // _LIBCPP_CXX03_LANG @@ -1570,7 +1585,7 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) { __node_base_pointer& __child = __tree_.__find_equal(__parent, __k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__value_.__get_value().second; + return _Tp::__get_value(static_cast<__node_pointer>(__child)->__value_).second; } template @@ -1579,7 +1594,7 @@ const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const { __node_base_pointer __child = __tree_.__find_equal(__parent, __k); if (__child == nullptr) std::__throw_out_of_range("map::at: key not found"); - return static_cast<__node_pointer>(__child)->__value_.__get_value().second; + return _Tp::__get_value(static_cast<__node_pointer>(__child)->__value_).second; } template diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map index 61c89a0ca73bb..a9c118fe7adf6 100644 --- a/libcxx/include/unordered_map +++ b/libcxx/include/unordered_map @@ -613,6 +613,7 @@ template # include <__type_traits/invoke.h> # include <__type_traits/is_allocator.h> # include <__type_traits/is_integral.h> +# include <__type_traits/is_standard_layout.h> # include <__type_traits/remove_const.h> # include <__type_traits/type_identity.h> # include <__utility/forward.h> @@ -655,7 +656,7 @@ public: : _Hash(__h) {} _LIBCPP_HIDE_FROM_ABI const _Hash& hash_function() const _NOEXCEPT { return *this; } _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Cp& __x) const { - return static_cast(*this)(__x.__get_value().first); + return static_cast(*this)(_Cp::get_value(__x).first); } _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Key& __x) const { return static_cast(*this)(__x); } # if _LIBCPP_STD_VER >= 20 @@ -680,7 +681,7 @@ public: _LIBCPP_HIDE_FROM_ABI __unordered_map_hasher(const _Hash& __h) _NOEXCEPT_(is_nothrow_copy_constructible<_Hash>::value) : __hash_(__h) {} _LIBCPP_HIDE_FROM_ABI const _Hash& hash_function() const _NOEXCEPT { return __hash_; } - _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Cp& __x) const { return __hash_(__x.__get_value().first); } + _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Cp& __x) const { return __hash_(_Cp::__get_value(__x).first); } _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Key& __x) const { return __hash_(__x); } # if _LIBCPP_STD_VER >= 20 template @@ -713,22 +714,22 @@ public: : _Pred(__p) {} _LIBCPP_HIDE_FROM_ABI const _Pred& key_eq() const _NOEXCEPT { return *this; } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Cp& __y) const { - return static_cast(*this)(__x.__get_value().first, __y.__get_value().first); + return static_cast(*this)(_Cp::__get_value(__x).first, _Cp::__get_value(__y).first); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Key& __y) const { - return static_cast(*this)(__x.__get_value().first, __y); + return static_cast(*this)(_Cp::__get_value(__x).first, __y); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _Cp& __y) const { - return static_cast(*this)(__x, __y.__get_value().first); + return static_cast(*this)(__x, _Cp::__get_value(__y).first); } # if _LIBCPP_STD_VER >= 20 template _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _K2& __y) const { - return static_cast(*this)(__x.__get_value().first, __y); + return static_cast(*this)(_Cp::__get_value(__x).first, __y); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _Cp& __y) const { - return static_cast(*this)(__x, __y.__get_value().first); + return static_cast(*this)(__x, _Cp::__get_value(__y).first); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _K2& __y) const { @@ -756,22 +757,22 @@ public: : __pred_(__p) {} _LIBCPP_HIDE_FROM_ABI const _Pred& key_eq() const _NOEXCEPT { return __pred_; } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Cp& __y) const { - return __pred_(__x.__get_value().first, __y.__get_value().first); + return __pred_(_Cp::__get_value(__x).first, _Cp::__get_value(__y).first); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Key& __y) const { - return __pred_(__x.__get_value().first, __y); + return __pred_(_Cp::__get_value(__x).first, __y); } _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _Cp& __y) const { - return __pred_(__x, __y.__get_value().first); + return __pred_(__x, _Cp::__get_value(__y).first); } # if _LIBCPP_STD_VER >= 20 template _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _K2& __y) const { - return __pred_(__x.__get_value().first, __y); + return __pred_(_Cp::__get_value(__x).first, __y); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _Cp& __y) const { - return __pred_(__x, __y.__get_value().first); + return __pred_(__x, _Cp::__get_value(__y).first); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _K2& __y) const { @@ -832,10 +833,12 @@ public: # endif // _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { + using __alloc_traits::value_type::__get_value; + if (__second_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().__get_value().second)); + __alloc_traits::destroy(__na_, std::addressof(__get_value(__get_value(*__p)).second)); if (__first_constructed) - __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().__get_value().first)); + __alloc_traits::destroy(__na_, std::addressof(__get_value(__get_value(*__p)).first)); if (__p) __alloc_traits::deallocate(__na_, __p, 1); } @@ -853,35 +856,38 @@ struct _LIBCPP_STANDALONE_DEBUG __hash_value_type { private: value_type __cc_; +private: + static_assert(is_standard_layout_v<__hash_value_type<_Key, _Tp>>, ""); + public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { + _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) { # if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); + return *std::launder(std::addressof(reinterpret_cast(__v))); # else - return __cc_; + return reinterpret_cast(__v); # endif } - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { + _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) { # if _LIBCPP_STD_VER >= 17 - return *std::launder(std::addressof(__cc_)); + return *std::launder(std::addressof(reinterpret_cast(__v))); # else - return __cc_; + return reinterpret_cast(__v); # endif } _LIBCPP_HIDE_FROM_ABI __nc_ref_pair_type __ref() { - value_type& __v = __get_value(); + value_type& __v = __get_value(*this); return __nc_ref_pair_type(const_cast(__v.first), __v.second); } _LIBCPP_HIDE_FROM_ABI __nc_rref_pair_type __move() { - value_type& __v = __get_value(); + value_type& __v = __get_value(*this); return __nc_rref_pair_type(std::move(const_cast(__v.first)), std::move(__v.second)); } _LIBCPP_HIDE_FROM_ABI __hash_value_type& operator=(const __hash_value_type& __v) { - __ref() = __v.__get_value(); + __ref() = __get_value(__v); return *this; } @@ -915,9 +921,17 @@ struct __hash_value_type { private: value_type __cc_; +private: + static_assert(std::is_standard_layout_v<__hash_value_type<_Key, _Tp>>, ""); + public: - _LIBCPP_HIDE_FROM_ABI value_type& __get_value() { return __cc_; } - _LIBCPP_HIDE_FROM_ABI const value_type& __get_value() const { return __cc_; } + _LIBCPP_HIDE_FROM_ABI static value_type& __get_value(__hash_value_type& __v) { + return reinterpret_cast(__v); + } + + _LIBCPP_HIDE_FROM_ABI static const value_type& __get_value(const __hash_value_type& __v) const { + return reinterpret_cast(__v); + } ~__hash_value_type() = delete; }; @@ -941,8 +955,10 @@ public: _LIBCPP_HIDE_FROM_ABI __hash_map_iterator(_HashIterator __i) _NOEXCEPT : __i_(__i) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__i_->__get_value()); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return value_type::__get_value(*__i_); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + return pointer_traits::pointer_to(value_type::__get_value(*__i_)); + } _LIBCPP_HIDE_FROM_ABI __hash_map_iterator& operator++() { ++__i_; @@ -995,8 +1011,10 @@ public: __hash_map_const_iterator(__hash_map_iterator __i) _NOEXCEPT : __i_(__i.__i_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __i_->__get_value(); } - _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits::pointer_to(__i_->__get_value()); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { return value_type::__get_value(*__i_); } + _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + return pointer_traits::pointer_to(value_type::__get_value(*__i_)); + } _LIBCPP_HIDE_FROM_ABI __hash_map_const_iterator& operator++() { ++__i_; @@ -1681,7 +1699,7 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(unordered_map&& __ if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) { - __table_.__emplace_unique(__u.__table_.remove((__i++).__i_)->__get_value().__move()); + __table_.__emplace_unique(_Tp::__get_value(*__u.__table_.remove((__i++).__i_)).__move()); } } } @@ -1739,18 +1757,20 @@ inline void unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterato template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type& __k) { - return __table_ - .__emplace_unique_key_args(__k, piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple()) - .first->__get_value() + return _Tp::__get_value(*__table_ + .__emplace_unique_key_args( + __k, piecewise_construct, std::forward_as_tuple(__k), std::forward_as_tuple()) + .first) .second; } template _Tp& unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](key_type&& __k) { - return __table_ - .__emplace_unique_key_args( - __k, piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple()) - .first->__get_value() + return _Tp::__get_value( + *__table_ + .__emplace_unique_key_args( + __k, piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple()) + .first) .second; } # else // _LIBCPP_CXX03_LANG @@ -1760,9 +1780,9 @@ typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node_with_key(const key_type& __k) { __node_allocator& __na = __table_.__node_alloc(); __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); - __node_traits::construct(__na, std::addressof(__h->__get_value().__get_value().first), __k); + __node_traits::construct(__na, std::addressof(_Tp::__get_value(_Tp::__get_value(*__h).first), __k); __h.get_deleter().__first_constructed = true; - __node_traits::construct(__na, std::addressof(__h->__get_value().__get_value().second)); + __node_traits::construct(__na, std::addressof(_Tp::__get_value(_Tp::__get_value(*__h).second)); __h.get_deleter().__second_constructed = true; return __h; } @@ -2438,7 +2458,7 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) { - __table_.__insert_multi(__u.__table_.remove((__i++).__i_)->__get_value().__move()); + __table_.__insert_multi(_Tp::__get_value(*__u.__table_.remove((__i++).__i_)).__move()); } } }