forked from OSchip/llvm-project
Fix a strict aliasing violation in map and unordered_map.
These containers type-punned between pair<K, V> and pair<const K, V> as an optimization. This commit instead provides access to the pair via a pair of references that assign through to the underlying object. It's still undefined to mutate a const object, but clang doesn't optimize on this for data members, so this should be safe. Differential revision: https://reviews.llvm.org/D47607 llvm-svn: 333948
This commit is contained in:
parent
ba81d7f1eb
commit
f52318b47b
|
@ -32,13 +32,8 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Key, class _Tp>
|
||||
union __hash_value_type;
|
||||
#else
|
||||
template <class _Key, class _Tp>
|
||||
struct __hash_value_type;
|
||||
#endif
|
||||
|
||||
template <class _Key, class _Cp, class _Hash,
|
||||
bool = is_empty<_Hash>::value && !__libcpp_is_final<_Hash>::value>
|
||||
|
@ -172,7 +167,7 @@ struct __hash_key_value_types {
|
|||
}
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type&& __move(__node_value_type& __v) {
|
||||
static __container_value_type&& __move(__node_value_type& __v) {
|
||||
return _VSTD::move(__v);
|
||||
}
|
||||
#endif
|
||||
|
@ -184,7 +179,6 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
|
|||
typedef _Tp mapped_type;
|
||||
typedef __hash_value_type<_Key, _Tp> __node_value_type;
|
||||
typedef pair<const _Key, _Tp> __container_value_type;
|
||||
typedef pair<_Key, _Tp> __nc_value_type;
|
||||
typedef __container_value_type __map_value_type;
|
||||
static const bool __is_map = true;
|
||||
|
||||
|
@ -198,7 +192,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
|
|||
static typename enable_if<__is_same_uncvref<_Up, __node_value_type>::value,
|
||||
__container_value_type const&>::type
|
||||
__get_value(_Up& __t) {
|
||||
return __t.__cc;
|
||||
return __t.__get_value();
|
||||
}
|
||||
|
||||
template <class _Up>
|
||||
|
@ -211,12 +205,12 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
|
|||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type* __get_ptr(__node_value_type& __n) {
|
||||
return _VSTD::addressof(__n.__cc);
|
||||
return _VSTD::addressof(__n.__get_value());
|
||||
}
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __nc_value_type&& __move(__node_value_type& __v) {
|
||||
return _VSTD::move(__v.__nc);
|
||||
static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) {
|
||||
return __v.__move();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,13 +37,8 @@ template <class _Pointer> class __tree_end_node;
|
|||
template <class _VoidPtr> class __tree_node_base;
|
||||
template <class _Tp, class _VoidPtr> class __tree_node;
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Key, class _Value>
|
||||
union __value_type;
|
||||
#else
|
||||
template <class _Key, class _Value>
|
||||
struct __value_type;
|
||||
#endif
|
||||
|
||||
template <class _Key, class _CP, class _Compare,
|
||||
bool = is_empty<_Compare>::value && !__libcpp_is_final<_Compare>::value>
|
||||
|
@ -569,10 +564,9 @@ struct __tree_key_value_types {
|
|||
static __container_value_type* __get_ptr(__node_value_type& __n) {
|
||||
return _VSTD::addressof(__n);
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type&& __move(__node_value_type& __v) {
|
||||
static __container_value_type&& __move(__node_value_type& __v) {
|
||||
return _VSTD::move(__v);
|
||||
}
|
||||
#endif
|
||||
|
@ -584,14 +578,13 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
|
|||
typedef _Tp mapped_type;
|
||||
typedef __value_type<_Key, _Tp> __node_value_type;
|
||||
typedef pair<const _Key, _Tp> __container_value_type;
|
||||
typedef pair<_Key, _Tp> __nc_value_type;
|
||||
typedef __container_value_type __map_value_type;
|
||||
static const bool __is_map = true;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static key_type const&
|
||||
__get_key(__node_value_type const& __t) {
|
||||
return __t.__cc.first;
|
||||
return __t.__get_value().first;
|
||||
}
|
||||
|
||||
template <class _Up>
|
||||
|
@ -605,7 +598,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
|
|||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type const&
|
||||
__get_value(__node_value_type const& __t) {
|
||||
return __t.__cc;
|
||||
return __t.__get_value();
|
||||
}
|
||||
|
||||
template <class _Up>
|
||||
|
@ -618,13 +611,13 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
|
|||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type* __get_ptr(__node_value_type& __n) {
|
||||
return _VSTD::addressof(__n.__cc);
|
||||
return _VSTD::addressof(__n.__get_value());
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __nc_value_type&& __move(__node_value_type& __v) {
|
||||
return _VSTD::move(__v.__nc);
|
||||
static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) {
|
||||
return __v.__move();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -470,13 +470,13 @@ public:
|
|||
const _Compare& key_comp() const _NOEXCEPT {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _CP& __x, const _CP& __y) const
|
||||
{return static_cast<const _Compare&>(*this)(__x.__cc.first, __y.__cc.first);}
|
||||
{return static_cast<const _Compare&>(*this)(__x.__get_value().first, __y.__get_value().first);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _CP& __x, const _Key& __y) const
|
||||
{return static_cast<const _Compare&>(*this)(__x.__cc.first, __y);}
|
||||
{return static_cast<const _Compare&>(*this)(__x.__get_value().first, __y);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _Key& __x, const _CP& __y) const
|
||||
{return static_cast<const _Compare&>(*this)(__x, __y.__cc.first);}
|
||||
{return static_cast<const _Compare&>(*this)(__x, __y.__get_value().first);}
|
||||
void swap(__map_value_compare&__y)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_Compare>::value)
|
||||
{
|
||||
|
@ -489,13 +489,13 @@ public:
|
|||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type
|
||||
operator () ( const _K2& __x, const _CP& __y ) const
|
||||
{return static_cast<const _Compare&>(*this) (__x, __y.__cc.first);}
|
||||
{return static_cast<const _Compare&>(*this) (__x, __y.__get_value().first);}
|
||||
|
||||
template <typename _K2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type
|
||||
operator () (const _CP& __x, const _K2& __y) const
|
||||
{return static_cast<const _Compare&>(*this) (__x.__cc.first, __y);}
|
||||
{return static_cast<const _Compare&>(*this) (__x.__get_value().first, __y);}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -518,13 +518,13 @@ public:
|
|||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _CP& __x, const _CP& __y) const
|
||||
{return comp(__x.__cc.first, __y.__cc.first);}
|
||||
{return comp(__x.__get_value().first, __y.__get_value().first);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _CP& __x, const _Key& __y) const
|
||||
{return comp(__x.__cc.first, __y);}
|
||||
{return comp(__x.__get_value().first, __y);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _Key& __x, const _CP& __y) const
|
||||
{return comp(__x, __y.__cc.first);}
|
||||
{return comp(__x, __y.__get_value().first);}
|
||||
void swap(__map_value_compare&__y)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_Compare>::value)
|
||||
{
|
||||
|
@ -537,13 +537,13 @@ public:
|
|||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type
|
||||
operator () ( const _K2& __x, const _CP& __y ) const
|
||||
{return comp (__x, __y.__cc.first);}
|
||||
{return comp (__x, __y.__get_value().first);}
|
||||
|
||||
template <typename _K2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type
|
||||
operator () (const _CP& __x, const _K2& __y) const
|
||||
{return comp (__x.__cc.first, __y);}
|
||||
{return comp (__x.__get_value().first, __y);}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -597,9 +597,9 @@ public:
|
|||
void operator()(pointer __p) _NOEXCEPT
|
||||
{
|
||||
if (__second_constructed)
|
||||
__alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__cc.second));
|
||||
__alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__get_value().second));
|
||||
if (__first_constructed)
|
||||
__alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__cc.first));
|
||||
__alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__get_value().first));
|
||||
if (__p)
|
||||
__alloc_traits::deallocate(__na_, __p, 1);
|
||||
}
|
||||
|
@ -614,23 +614,67 @@ template <class _TreeIterator> class __map_const_iterator;
|
|||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Key, class _Tp>
|
||||
union __value_type
|
||||
struct __value_type
|
||||
{
|
||||
typedef _Key key_type;
|
||||
typedef _Tp mapped_type;
|
||||
typedef pair<const key_type, mapped_type> value_type;
|
||||
typedef pair<key_type, mapped_type> __nc_value_type;
|
||||
typedef pair<key_type&, mapped_type&> __nc_ref_pair_type;
|
||||
typedef pair<key_type&&, mapped_type&&> __nc_rref_pair_type;
|
||||
|
||||
private:
|
||||
value_type __cc;
|
||||
__nc_value_type __nc;
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
value_type& __get_value()
|
||||
{
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
return *_VSTD::launder(_VSTD::addressof(__cc));
|
||||
#else
|
||||
return __cc;
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const value_type& __get_value() const
|
||||
{
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
return *_VSTD::launder(_VSTD::addressof(__cc));
|
||||
#else
|
||||
return __cc;
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__nc_ref_pair_type __ref()
|
||||
{
|
||||
value_type& __v = __get_value();
|
||||
return __nc_ref_pair_type(const_cast<key_type&>(__v.first), __v.second);
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__nc_rref_pair_type __move()
|
||||
{
|
||||
value_type& __v = __get_value();
|
||||
return __nc_rref_pair_type(
|
||||
_VSTD::move(const_cast<key_type&>(__v.first)),
|
||||
_VSTD::move(__v.second));
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__value_type& operator=(const __value_type& __v)
|
||||
{__nc = __v.__cc; return *this;}
|
||||
{
|
||||
__ref() = __v.__get_value();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__value_type& operator=(__value_type&& __v)
|
||||
{__nc = _VSTD::move(__v.__nc); return *this;}
|
||||
{
|
||||
__ref() = __v.__move();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _ValueTp,
|
||||
class = typename enable_if<
|
||||
|
@ -638,8 +682,10 @@ union __value_type
|
|||
>::type
|
||||
>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__value_type& operator=(_ValueTp&& __v) {
|
||||
__nc = _VSTD::forward<_ValueTp>(__v); return *this;
|
||||
__value_type& operator=(_ValueTp&& __v)
|
||||
{
|
||||
__ref() = _VSTD::forward<_ValueTp>(__v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -658,8 +704,15 @@ struct __value_type
|
|||
typedef _Tp mapped_type;
|
||||
typedef pair<const key_type, mapped_type> value_type;
|
||||
|
||||
private:
|
||||
value_type __cc;
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
value_type& __get_value() { return __cc; }
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const value_type& __get_value() const { return __cc; }
|
||||
|
||||
private:
|
||||
__value_type();
|
||||
__value_type(__value_type const&);
|
||||
|
@ -701,9 +754,9 @@ public:
|
|||
__map_iterator(_TreeIterator __i) _NOEXCEPT : __i_(__i) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reference operator*() const {return __i_->__cc;}
|
||||
reference operator*() const {return __i_->__get_value();}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pointer operator->() const {return pointer_traits<pointer>::pointer_to(__i_->__cc);}
|
||||
pointer operator->() const {return pointer_traits<pointer>::pointer_to(__i_->__get_value());}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__map_iterator& operator++() {++__i_; return *this;}
|
||||
|
@ -764,9 +817,9 @@ public:
|
|||
: __i_(__i.__i_) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reference operator*() const {return __i_->__cc;}
|
||||
reference operator*() const {return __i_->__get_value();}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pointer operator->() const {return pointer_traits<pointer>::pointer_to(__i_->__cc);}
|
||||
pointer operator->() const {return pointer_traits<pointer>::pointer_to(__i_->__get_value());}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__map_const_iterator& operator++() {++__i_; return *this;}
|
||||
|
@ -809,7 +862,6 @@ public:
|
|||
typedef _Key key_type;
|
||||
typedef _Tp mapped_type;
|
||||
typedef pair<const key_type, mapped_type> value_type;
|
||||
typedef pair<key_type, mapped_type> __nc_value_type;
|
||||
typedef _Compare key_compare;
|
||||
typedef _Allocator allocator_type;
|
||||
typedef value_type& reference;
|
||||
|
@ -1308,7 +1360,7 @@ map<_Key, _Tp, _Compare, _Allocator>::map(map&& __m, const allocator_type& __a)
|
|||
const_iterator __e = cend();
|
||||
while (!__m.empty())
|
||||
__tree_.__insert_unique(__e.__i_,
|
||||
_VSTD::move(__m.__tree_.remove(__m.begin().__i_)->__value_.__nc));
|
||||
__m.__tree_.remove(__m.begin().__i_)->__value_.__move());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1319,7 +1371,7 @@ map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k)
|
|||
return __tree_.__emplace_unique_key_args(__k,
|
||||
_VSTD::piecewise_construct,
|
||||
_VSTD::forward_as_tuple(__k),
|
||||
_VSTD::forward_as_tuple()).first->__cc.second;
|
||||
_VSTD::forward_as_tuple()).first->__get_value().second;
|
||||
}
|
||||
|
||||
template <class _Key, class _Tp, class _Compare, class _Allocator>
|
||||
|
@ -1329,7 +1381,7 @@ map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k)
|
|||
return __tree_.__emplace_unique_key_args(__k,
|
||||
_VSTD::piecewise_construct,
|
||||
_VSTD::forward_as_tuple(_VSTD::move(__k)),
|
||||
_VSTD::forward_as_tuple()).first->__cc.second;
|
||||
_VSTD::forward_as_tuple()).first->__get_value().second;
|
||||
}
|
||||
|
||||
#else // _LIBCPP_CXX03_LANG
|
||||
|
@ -1340,9 +1392,9 @@ map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(const key_type&
|
|||
{
|
||||
__node_allocator& __na = __tree_.__node_alloc();
|
||||
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
|
||||
__node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.first), __k);
|
||||
__node_traits::construct(__na, _VSTD::addressof(__h->__value_.__get_value().first), __k);
|
||||
__h.get_deleter().__first_constructed = true;
|
||||
__node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second));
|
||||
__node_traits::construct(__na, _VSTD::addressof(__h->__value_.__get_value().second));
|
||||
__h.get_deleter().__second_constructed = true;
|
||||
return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03
|
||||
}
|
||||
|
@ -1360,7 +1412,7 @@ 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_.__cc.second;
|
||||
return __r->__value_.__get_value().second;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
@ -1375,7 +1427,7 @@ map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k)
|
|||
if (__child == nullptr)
|
||||
throw out_of_range("map::at: key not found");
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
return static_cast<__node_pointer>(__child)->__value_.__cc.second;
|
||||
return static_cast<__node_pointer>(__child)->__value_.__get_value().second;
|
||||
}
|
||||
|
||||
template <class _Key, class _Tp, class _Compare, class _Allocator>
|
||||
|
@ -1388,7 +1440,7 @@ map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const
|
|||
if (__child == nullptr)
|
||||
throw out_of_range("map::at: key not found");
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
return static_cast<__node_pointer>(__child)->__value_.__cc.second;
|
||||
return static_cast<__node_pointer>(__child)->__value_.__get_value().second;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1465,7 +1517,6 @@ public:
|
|||
typedef _Key key_type;
|
||||
typedef _Tp mapped_type;
|
||||
typedef pair<const key_type, mapped_type> value_type;
|
||||
typedef pair<key_type, mapped_type> __nc_value_type;
|
||||
typedef _Compare key_compare;
|
||||
typedef _Allocator allocator_type;
|
||||
typedef value_type& reference;
|
||||
|
@ -1852,7 +1903,7 @@ multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const alloca
|
|||
const_iterator __e = cend();
|
||||
while (!__m.empty())
|
||||
__tree_.__insert_multi(__e.__i_,
|
||||
_VSTD::move(__m.__tree_.remove(__m.begin().__i_)->__value_.__nc));
|
||||
_VSTD::move(__m.__tree_.remove(__m.begin().__i_)->__value_.__move()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -396,7 +396,7 @@ public:
|
|||
const _Hash& hash_function() const _NOEXCEPT {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
size_t operator()(const _Cp& __x) const
|
||||
{return static_cast<const _Hash&>(*this)(__x.__cc.first);}
|
||||
{return static_cast<const _Hash&>(*this)(__x.__get_value().first);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
size_t operator()(const _Key& __x) const
|
||||
{return static_cast<const _Hash&>(*this)(__x);}
|
||||
|
@ -425,7 +425,7 @@ public:
|
|||
const _Hash& hash_function() const _NOEXCEPT {return __hash_;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
size_t operator()(const _Cp& __x) const
|
||||
{return __hash_(__x.__cc.first);}
|
||||
{return __hash_(__x.__get_value().first);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
size_t operator()(const _Key& __x) const
|
||||
{return __hash_(__x);}
|
||||
|
@ -464,13 +464,13 @@ public:
|
|||
const _Pred& key_eq() const _NOEXCEPT {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _Cp& __x, const _Cp& __y) const
|
||||
{return static_cast<const _Pred&>(*this)(__x.__cc.first, __y.__cc.first);}
|
||||
{return static_cast<const _Pred&>(*this)(__x.__get_value().first, __y.__get_value().first);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _Cp& __x, const _Key& __y) const
|
||||
{return static_cast<const _Pred&>(*this)(__x.__cc.first, __y);}
|
||||
{return static_cast<const _Pred&>(*this)(__x.__get_value().first, __y);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _Key& __x, const _Cp& __y) const
|
||||
{return static_cast<const _Pred&>(*this)(__x, __y.__cc.first);}
|
||||
{return static_cast<const _Pred&>(*this)(__x, __y.__get_value().first);}
|
||||
void swap(__unordered_map_equal&__y)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_Pred>::value)
|
||||
{
|
||||
|
@ -496,13 +496,13 @@ public:
|
|||
const _Pred& key_eq() const _NOEXCEPT {return __pred_;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _Cp& __x, const _Cp& __y) const
|
||||
{return __pred_(__x.__cc.first, __y.__cc.first);}
|
||||
{return __pred_(__x.__get_value().first, __y.__get_value().first);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _Cp& __x, const _Key& __y) const
|
||||
{return __pred_(__x.__cc.first, __y);}
|
||||
{return __pred_(__x.__get_value().first, __y);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _Key& __x, const _Cp& __y) const
|
||||
{return __pred_(__x, __y.__cc.first);}
|
||||
{return __pred_(__x, __y.__get_value().first);}
|
||||
void swap(__unordered_map_equal&__y)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_Pred>::value)
|
||||
{
|
||||
|
@ -572,9 +572,9 @@ public:
|
|||
void operator()(pointer __p) _NOEXCEPT
|
||||
{
|
||||
if (__second_constructed)
|
||||
__alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__cc.second));
|
||||
__alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__get_value().second));
|
||||
if (__first_constructed)
|
||||
__alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__cc.first));
|
||||
__alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_.__get_value().first));
|
||||
if (__p)
|
||||
__alloc_traits::deallocate(__na_, __p, 1);
|
||||
}
|
||||
|
@ -582,23 +582,67 @@ public:
|
|||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Key, class _Tp>
|
||||
union __hash_value_type
|
||||
struct __hash_value_type
|
||||
{
|
||||
typedef _Key key_type;
|
||||
typedef _Tp mapped_type;
|
||||
typedef pair<const key_type, mapped_type> value_type;
|
||||
typedef pair<key_type, mapped_type> __nc_value_type;
|
||||
typedef pair<key_type&, mapped_type&> __nc_ref_pair_type;
|
||||
typedef pair<key_type&&, mapped_type&&> __nc_rref_pair_type;
|
||||
|
||||
private:
|
||||
value_type __cc;
|
||||
__nc_value_type __nc;
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
value_type& __get_value()
|
||||
{
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
return *_VSTD::launder(_VSTD::addressof(__cc));
|
||||
#else
|
||||
return __cc;
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const value_type& __get_value() const
|
||||
{
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
return *_VSTD::launder(_VSTD::addressof(__cc));
|
||||
#else
|
||||
return __cc;
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__nc_ref_pair_type __ref()
|
||||
{
|
||||
value_type& __v = __get_value();
|
||||
return __nc_ref_pair_type(const_cast<key_type&>(__v.first), __v.second);
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__nc_rref_pair_type __move()
|
||||
{
|
||||
value_type& __v = __get_value();
|
||||
return __nc_rref_pair_type(
|
||||
_VSTD::move(const_cast<key_type&>(__v.first)),
|
||||
_VSTD::move(__v.second));
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__hash_value_type& operator=(const __hash_value_type& __v)
|
||||
{__nc = __v.__cc; return *this;}
|
||||
{
|
||||
__ref() = __v.__get_value();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__hash_value_type& operator=(__hash_value_type&& __v)
|
||||
{__nc = _VSTD::move(__v.__nc); return *this;}
|
||||
{
|
||||
__ref() = __v.__move();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _ValueTp,
|
||||
class = typename enable_if<
|
||||
|
@ -606,8 +650,10 @@ union __hash_value_type
|
|||
>::type
|
||||
>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__hash_value_type& operator=(_ValueTp&& __v) {
|
||||
__nc = _VSTD::forward<_ValueTp>(__v); return *this;
|
||||
__hash_value_type& operator=(_ValueTp&& __v)
|
||||
{
|
||||
__ref() = _VSTD::forward<_ValueTp>(__v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -628,8 +674,15 @@ struct __hash_value_type
|
|||
typedef _Tp mapped_type;
|
||||
typedef pair<const key_type, mapped_type> value_type;
|
||||
|
||||
private:
|
||||
value_type __cc;
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
value_type& __get_value() { return __cc; }
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const value_type& __get_value() const { return __cc; }
|
||||
|
||||
private:
|
||||
~__hash_value_type();
|
||||
};
|
||||
|
@ -657,9 +710,9 @@ public:
|
|||
__hash_map_iterator(_HashIterator __i) _NOEXCEPT : __i_(__i) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reference operator*() const {return __i_->__cc;}
|
||||
reference operator*() const {return __i_->__get_value();}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pointer operator->() const {return pointer_traits<pointer>::pointer_to(__i_->__cc);}
|
||||
pointer operator->() const {return pointer_traits<pointer>::pointer_to(__i_->__get_value());}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__hash_map_iterator& operator++() {++__i_; return *this;}
|
||||
|
@ -711,9 +764,9 @@ public:
|
|||
: __i_(__i.__i_) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reference operator*() const {return __i_->__cc;}
|
||||
reference operator*() const {return __i_->__get_value();}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pointer operator->() const {return pointer_traits<pointer>::pointer_to(__i_->__cc);}
|
||||
pointer operator->() const {return pointer_traits<pointer>::pointer_to(__i_->__get_value());}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__hash_map_const_iterator& operator++() {++__i_; return *this;}
|
||||
|
@ -750,7 +803,6 @@ public:
|
|||
typedef _Pred key_equal;
|
||||
typedef _Alloc allocator_type;
|
||||
typedef pair<const key_type, mapped_type> value_type;
|
||||
typedef pair<key_type, mapped_type> __nc_value_type;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
static_assert((is_same<value_type, typename allocator_type::value_type>::value),
|
||||
|
@ -1298,8 +1350,8 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(
|
|||
{
|
||||
iterator __i = __u.begin();
|
||||
while (__u.size() != 0) {
|
||||
__table_.__emplace_unique(_VSTD::move(
|
||||
__u.__table_.remove((__i++).__i_)->__value_.__nc));
|
||||
__table_.__emplace_unique(
|
||||
__u.__table_.remove((__i++).__i_)->__value_.__move());
|
||||
}
|
||||
}
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
@ -1385,7 +1437,7 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type& __k)
|
|||
{
|
||||
return __table_.__emplace_unique_key_args(__k,
|
||||
std::piecewise_construct, std::forward_as_tuple(__k),
|
||||
std::forward_as_tuple()).first->__cc.second;
|
||||
std::forward_as_tuple()).first->__get_value().second;
|
||||
}
|
||||
|
||||
template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
|
||||
|
@ -1394,7 +1446,7 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](key_type&& __k)
|
|||
{
|
||||
return __table_.__emplace_unique_key_args(__k,
|
||||
std::piecewise_construct, std::forward_as_tuple(std::move(__k)),
|
||||
std::forward_as_tuple()).first->__cc.second;
|
||||
std::forward_as_tuple()).first->__get_value().second;
|
||||
}
|
||||
#else // _LIBCPP_CXX03_LANG
|
||||
|
||||
|
@ -1404,9 +1456,9 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node_with_key(const
|
|||
{
|
||||
__node_allocator& __na = __table_.__node_alloc();
|
||||
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
|
||||
__node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.first), __k);
|
||||
__node_traits::construct(__na, _VSTD::addressof(__h->__value_.__get_value().first), __k);
|
||||
__h.get_deleter().__first_constructed = true;
|
||||
__node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second));
|
||||
__node_traits::construct(__na, _VSTD::addressof(__h->__value_.__get_value().second));
|
||||
__h.get_deleter().__second_constructed = true;
|
||||
return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03
|
||||
}
|
||||
|
@ -1500,7 +1552,6 @@ public:
|
|||
typedef _Pred key_equal;
|
||||
typedef _Alloc allocator_type;
|
||||
typedef pair<const key_type, mapped_type> value_type;
|
||||
typedef pair<key_type, mapped_type> __nc_value_type;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
static_assert((is_same<value_type, typename allocator_type::value_type>::value),
|
||||
|
@ -1915,8 +1966,7 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap(
|
|||
while (__u.size() != 0)
|
||||
{
|
||||
__table_.__insert_multi(
|
||||
_VSTD::move(__u.__table_.remove((__i++).__i_)->__value_.__nc)
|
||||
);
|
||||
__u.__table_.remove((__i++).__i_)->__value_.__move());
|
||||
}
|
||||
}
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
|
Loading…
Reference in New Issue