14
14
#include < __assert>
15
15
#include < __config>
16
16
#include < __fwd/map.h>
17
+ #include < __fwd/pair.h>
17
18
#include < __fwd/set.h>
18
19
#include < __iterator/distance.h>
19
20
#include < __iterator/iterator_traits.h>
25
26
#include < __memory/swap_allocator.h>
26
27
#include < __memory/unique_ptr.h>
27
28
#include < __type_traits/can_extract_key.h>
29
+ #include < __type_traits/copy_cvref.h>
28
30
#include < __type_traits/enable_if.h>
29
31
#include < __type_traits/invoke.h>
30
32
#include < __type_traits/is_const.h>
@@ -505,48 +507,24 @@ struct __is_tree_value_type<_One> : __is_tree_value_type_imp<__remove_cvref_t<_O
505
507
template <class _Tp >
506
508
struct __tree_key_value_types {
507
509
typedef _Tp key_type;
508
- typedef _Tp __node_value_type;
509
510
typedef _Tp __container_value_type;
510
511
static const bool __is_map = false ;
511
512
512
513
_LIBCPP_HIDE_FROM_ABI static key_type const & __get_key (_Tp const & __v) { return __v; }
513
- _LIBCPP_HIDE_FROM_ABI static __container_value_type const & __get_value (__node_value_type const & __v) { return __v; }
514
- _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr (__node_value_type& __n) { return std::addressof (__n); }
515
- _LIBCPP_HIDE_FROM_ABI static __container_value_type&& __move(__node_value_type& __v) { return std::move (__v); }
516
514
};
517
515
518
516
template <class _Key , class _Tp >
519
517
struct __tree_key_value_types <__value_type<_Key, _Tp> > {
520
518
typedef _Key key_type;
521
519
typedef _Tp mapped_type;
522
- typedef __value_type<_Key, _Tp> __node_value_type;
523
520
typedef pair<const _Key, _Tp> __container_value_type;
524
521
typedef __container_value_type __map_value_type;
525
522
static const bool __is_map = true ;
526
523
527
- _LIBCPP_HIDE_FROM_ABI static key_type const & __get_key (__node_value_type const & __t ) {
528
- return __t .__get_value ().first ;
529
- }
530
-
531
524
template <class _Up , __enable_if_t <__is_same_uncvref<_Up, __container_value_type>::value, int > = 0 >
532
525
_LIBCPP_HIDE_FROM_ABI static key_type const & __get_key (_Up& __t ) {
533
526
return __t .first ;
534
527
}
535
-
536
- _LIBCPP_HIDE_FROM_ABI static __container_value_type const & __get_value (__node_value_type const & __t ) {
537
- return __t .__get_value ();
538
- }
539
-
540
- template <class _Up , __enable_if_t <__is_same_uncvref<_Up, __container_value_type>::value, int > = 0 >
541
- _LIBCPP_HIDE_FROM_ABI static __container_value_type const & __get_value (_Up& __t ) {
542
- return __t ;
543
- }
544
-
545
- _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr (__node_value_type& __n) {
546
- return std::addressof (__n.__get_value ());
547
- }
548
-
549
- _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move (__node_value_type& __v) { return __v.__move (); }
550
528
};
551
529
552
530
template <class _VoidPtr >
@@ -587,6 +565,19 @@ struct __tree_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
587
565
typedef __rebind_pointer_t <_AllocPtr, const _Mv> __const_map_value_type_pointer;
588
566
};
589
567
568
+ template <class _Tp >
569
+ struct __get_node_value_type {
570
+ using type _LIBCPP_NODEBUG = _Tp;
571
+ };
572
+
573
+ template <class _Key , class _ValueT >
574
+ struct __get_node_value_type <__value_type<_Key, _ValueT> > {
575
+ using type _LIBCPP_NODEBUG = pair<const _Key, _ValueT>;
576
+ };
577
+
578
+ template <class _Tp >
579
+ using __get_node_value_type_t _LIBCPP_NODEBUG = typename __get_node_value_type<_Tp>::type;
580
+
590
581
template <class _NodePtr , class _NodeT = typename pointer_traits<_NodePtr>::element_type>
591
582
struct __tree_node_types ;
592
583
@@ -599,7 +590,7 @@ public:
599
590
typedef typename pointer_traits<_NodePtr>::element_type __node_type;
600
591
typedef _NodePtr __node_pointer;
601
592
602
- typedef _Tp __node_value_type;
593
+ using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t <_Tp> ;
603
594
typedef __rebind_pointer_t <_VoidPtr, __node_value_type> __node_value_type_pointer;
604
595
typedef __rebind_pointer_t <_VoidPtr, const __node_value_type> __const_node_value_type_pointer;
605
596
@@ -650,11 +641,11 @@ public:
650
641
template <class _Tp , class _VoidPtr >
651
642
class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> {
652
643
public:
653
- typedef _Tp __node_value_type;
644
+ using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t <_Tp> ;
654
645
655
646
__node_value_type __value_;
656
647
657
- _LIBCPP_HIDE_FROM_ABI _Tp & __get_value () { return __value_; }
648
+ _LIBCPP_HIDE_FROM_ABI __node_value_type & __get_value () { return __value_; }
658
649
659
650
~__tree_node () = delete ;
660
651
__tree_node (__tree_node const &) = delete ;
@@ -685,7 +676,7 @@ public:
685
676
686
677
_LIBCPP_HIDE_FROM_ABI void operator ()(pointer __p) _NOEXCEPT {
687
678
if (__value_constructed)
688
- __alloc_traits::destroy (__na_, _NodeTypes::__get_ptr (__p->__value_ ));
679
+ __alloc_traits::destroy (__na_, std::addressof (__p->__value_ ));
689
680
if (__p)
690
681
__alloc_traits::deallocate (__na_, __p, 1 );
691
682
}
@@ -715,7 +706,7 @@ class __tree_iterator {
715
706
716
707
public:
717
708
typedef bidirectional_iterator_tag iterator_category;
718
- typedef _Tp value_type;
709
+ using value_type = __get_node_value_type_t <_Tp> ;
719
710
typedef _DiffType difference_type;
720
711
typedef value_type& reference;
721
712
typedef typename _NodeTypes::__node_value_type_pointer pointer;
@@ -789,7 +780,7 @@ class __tree_const_iterator {
789
780
790
781
public:
791
782
typedef bidirectional_iterator_tag iterator_category;
792
- typedef _Tp value_type;
783
+ using value_type = __get_node_value_type_t <_Tp> ;
793
784
typedef _DiffType difference_type;
794
785
typedef const value_type& reference;
795
786
typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
@@ -802,7 +793,7 @@ public:
802
793
}
803
794
804
795
private:
805
- typedef __tree_iterator<value_type , __node_pointer, difference_type> __non_const_iterator;
796
+ typedef __tree_iterator<_Tp , __node_pointer, difference_type> __non_const_iterator;
806
797
807
798
public:
808
799
_LIBCPP_HIDE_FROM_ABI __tree_const_iterator (__non_const_iterator __p) _NOEXCEPT : __ptr_(__p.__ptr_) {}
@@ -1107,6 +1098,18 @@ public:
1107
1098
return __emplace_hint_unique (__p, std::forward<_Vp>(__v));
1108
1099
}
1109
1100
1101
+ template <class _ValueT = _Tp, __enable_if_t <__is_tree_value_type<_ValueT>::value, int > = 0 >
1102
+ _LIBCPP_HIDE_FROM_ABI void
1103
+ __insert_unique_from_orphaned_node (const_iterator __p, __get_node_value_type_t <_Tp>&& __value) {
1104
+ using __key_type = typename _NodeTypes::key_type;
1105
+ __emplace_hint_unique (__p, const_cast <__key_type&&>(__value.first ), std::move (__value.second ));
1106
+ }
1107
+
1108
+ template <class _ValueT = _Tp, __enable_if_t <!__is_tree_value_type<_ValueT>::value, int > = 0 >
1109
+ _LIBCPP_HIDE_FROM_ABI void __insert_unique_from_orphaned_node (const_iterator __p, _Tp&& __value) {
1110
+ __emplace_hint_unique (__p, std::move (__value));
1111
+ }
1112
+
1110
1113
_LIBCPP_HIDE_FROM_ABI iterator __insert_multi (__container_value_type&& __v) {
1111
1114
return __emplace_multi (std::move (__v));
1112
1115
}
@@ -1125,6 +1128,18 @@ public:
1125
1128
return __emplace_hint_multi (__p, std::forward<_Vp>(__v));
1126
1129
}
1127
1130
1131
+ template <class _ValueT = _Tp, __enable_if_t <__is_tree_value_type<_ValueT>::value, int > = 0 >
1132
+ _LIBCPP_HIDE_FROM_ABI void
1133
+ __insert_multi_from_orphaned_node (const_iterator __p, __get_node_value_type_t <_Tp>&& __value) {
1134
+ using __key_type = typename _NodeTypes::key_type;
1135
+ __emplace_hint_multi (__p, const_cast <__key_type&&>(__value.first ), std::move (__value.second ));
1136
+ }
1137
+
1138
+ template <class _ValueT = _Tp, __enable_if_t <!__is_tree_value_type<_ValueT>::value, int > = 0 >
1139
+ _LIBCPP_HIDE_FROM_ABI void __insert_multi_from_orphaned_node (const_iterator __p, _Tp&& __value) {
1140
+ __emplace_hint_multi (__p, std::move (__value));
1141
+ }
1142
+
1128
1143
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool >
1129
1144
__node_assign_unique (const __container_value_type& __v, __node_pointer __dest);
1130
1145
@@ -1266,6 +1281,21 @@ private:
1266
1281
}
1267
1282
_LIBCPP_HIDE_FROM_ABI void __move_assign_alloc (__tree&, false_type) _NOEXCEPT {}
1268
1283
1284
+ template <class _From , __enable_if_t <__is_pair_v<__remove_cvref_t <_From> >, int > = 0 >
1285
+ _LIBCPP_HIDE_FROM_ABI static void __assign_value (__get_node_value_type_t <value_type>& __lhs, _From&& __rhs) {
1286
+ using __key_type = typename _NodeTypes::key_type;
1287
+
1288
+ // This is technically UB, since the object was constructed as `const`.
1289
+ // Clang doesn't optimize on this currently though.
1290
+ const_cast <__key_type&>(__lhs.first ) = const_cast <__copy_cvref_t <_From, __key_type>&&>(__rhs.first );
1291
+ __lhs.second = std::forward<_From>(__rhs).second ;
1292
+ }
1293
+
1294
+ template <class _To , class _From , class _ValueT = _Tp, __enable_if_t <!__is_pair_v<__remove_cvref_t <_From> >, int > = 0 >
1295
+ _LIBCPP_HIDE_FROM_ABI static void __assign_value (_To& __lhs, _From&& __rhs) {
1296
+ __lhs = std::forward<_From>(__rhs);
1297
+ }
1298
+
1269
1299
struct _DetachedTreeCache {
1270
1300
_LIBCPP_HIDE_FROM_ABI explicit _DetachedTreeCache (__tree* __t ) _NOEXCEPT
1271
1301
: __t_(__t ),
@@ -1406,14 +1436,14 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _
1406
1436
if (size () != 0 ) {
1407
1437
_DetachedTreeCache __cache (this );
1408
1438
for (; __cache.__get () && __first != __last; ++__first) {
1409
- __cache.__get ()->__value_ = *__first;
1439
+ __assign_value ( __cache.__get ()->__value_ , *__first) ;
1410
1440
__node_insert_multi (__cache.__get ());
1411
1441
__cache.__advance ();
1412
1442
}
1413
1443
}
1414
1444
const_iterator __e = end ();
1415
1445
for (; __first != __last; ++__first)
1416
- __insert_multi (__e, _NodeTypes::__get_value ( *__first) );
1446
+ __insert_multi (__e, *__first);
1417
1447
}
1418
1448
1419
1449
template <class _Tp , class _Compare , class _Allocator >
@@ -1492,13 +1522,14 @@ void __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) {
1492
1522
if (size () != 0 ) {
1493
1523
_DetachedTreeCache __cache (this );
1494
1524
while (__cache.__get () != nullptr && __t .size () != 0 ) {
1495
- __cache.__get ()->__value_ = std::move (__t .remove (__t .begin ())->__value_ );
1525
+ __assign_value ( __cache.__get ()->__value_ , std::move (__t .remove (__t .begin ())->__value_ ) );
1496
1526
__node_insert_multi (__cache.__get ());
1497
1527
__cache.__advance ();
1498
1528
}
1499
1529
}
1500
- while (__t .size () != 0 )
1501
- __insert_multi (__e, _NodeTypes::__move (__t .remove (__t .begin ())->__value_ ));
1530
+ while (__t .size () != 0 ) {
1531
+ __insert_multi_from_orphaned_node (__e, std::move (__t .remove (__t .begin ())->__value_ ));
1532
+ }
1502
1533
}
1503
1534
}
1504
1535
@@ -1524,7 +1555,7 @@ void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT {
1524
1555
destroy (static_cast <__node_pointer>(__nd->__left_ ));
1525
1556
destroy (static_cast <__node_pointer>(__nd->__right_ ));
1526
1557
__node_allocator& __na = __node_alloc ();
1527
- __node_traits::destroy (__na, _NodeTypes::__get_ptr (__nd->__value_ ));
1558
+ __node_traits::destroy (__na, std::addressof (__nd->__value_ ));
1528
1559
__node_traits::deallocate (__na, __nd, 1 );
1529
1560
}
1530
1561
}
@@ -1794,10 +1825,9 @@ template <class _Tp, class _Compare, class _Allocator>
1794
1825
template <class ... _Args>
1795
1826
typename __tree<_Tp, _Compare, _Allocator>::__node_holder
1796
1827
__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&&... __args) {
1797
- static_assert (!__is_tree_value_type<_Args...>::value, " Cannot construct from __value_type" );
1798
1828
__node_allocator& __na = __node_alloc ();
1799
1829
__node_holder __h (__node_traits::allocate (__na, 1 ), _Dp (__na));
1800
- __node_traits::construct (__na, _NodeTypes::__get_ptr (__h->__value_ ), std::forward<_Args>(__args)...);
1830
+ __node_traits::construct (__na, std::addressof (__h->__value_ ), std::forward<_Args>(__args)...);
1801
1831
__h.get_deleter ().__value_constructed = true ;
1802
1832
return __h;
1803
1833
}
@@ -1865,7 +1895,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const __container_value_
1865
1895
__node_pointer __r = static_cast <__node_pointer>(__child);
1866
1896
bool __inserted = false ;
1867
1897
if (__child == nullptr ) {
1868
- __nd->__value_ = __v;
1898
+ __assign_value ( __nd->__value_ , __v) ;
1869
1899
__insert_node_at (__parent, __child, static_cast <__node_base_pointer>(__nd));
1870
1900
__r = __nd;
1871
1901
__inserted = true ;
@@ -2027,7 +2057,7 @@ typename __tree<_Tp, _Compare, _Allocator>::iterator __tree<_Tp, _Compare, _Allo
2027
2057
__node_pointer __np = __p.__get_np ();
2028
2058
iterator __r = __remove_node_pointer (__np);
2029
2059
__node_allocator& __na = __node_alloc ();
2030
- __node_traits::destroy (__na, _NodeTypes::__get_ptr (const_cast <__node_value_type&>(*__p)));
2060
+ __node_traits::destroy (__na, std::addressof (const_cast <__node_value_type&>(*__p)));
2031
2061
__node_traits::deallocate (__na, __np, 1 );
2032
2062
return __r;
2033
2063
}
0 commit comments