@@ -1213,6 +1213,86 @@ private:
1213
1213
__node_pointer __cache_root_;
1214
1214
__node_pointer __cache_elem_;
1215
1215
};
1216
+
1217
+ class __tree_deleter {
1218
+ __node_allocator& __alloc_;
1219
+
1220
+ public:
1221
+ using pointer = __node_pointer;
1222
+
1223
+ _LIBCPP_HIDE_FROM_ABI __tree_deleter (__node_allocator& __alloc) : __alloc_(__alloc) {}
1224
+
1225
+ void operator ()(__node_pointer __ptr) {
1226
+ if (!__ptr)
1227
+ return ;
1228
+
1229
+ (*this )(static_cast <__node_pointer>(__ptr->__left_ ));
1230
+
1231
+ auto __right = __ptr->__right_ ;
1232
+
1233
+ __node_traits::destroy (__alloc_, std::addressof (__ptr->__value_ ));
1234
+ __node_traits::deallocate (__alloc_, __ptr, 1 );
1235
+
1236
+ (*this )(static_cast <__node_pointer>(__right));
1237
+ }
1238
+ };
1239
+
1240
+ class __allocate_node_builder {
1241
+ __tree& __base_;
1242
+
1243
+ public:
1244
+ __allocate_node_builder (__tree& __base) : __base_(__base) {}
1245
+
1246
+ template <class _Up >
1247
+ __node_holder operator ()(_Up&& __v) {
1248
+ return __base_.__construct_node (std::forward<_Up>(__v));
1249
+ }
1250
+ };
1251
+
1252
+ class __cache_node_builder {
1253
+ __tree& __base_;
1254
+ _DetachedTreeCache& __cache_;
1255
+
1256
+ public:
1257
+ __cache_node_builder (__tree& __base, _DetachedTreeCache& __cache) : __base_(__base), __cache_(__cache) {}
1258
+
1259
+ template <class _Up >
1260
+ __node_holder operator ()(_Up&& __v) {
1261
+ __node_pointer __ret = __cache_.__get ();
1262
+ if (__ret) {
1263
+ __assign_value (__ret->__value_ , std::forward<_Up>(__v));
1264
+ __cache_.__advance ();
1265
+ }
1266
+ return __node_holder (__ret, _Dp (__base_.__node_alloc_ ));
1267
+ }
1268
+ };
1269
+
1270
+ template <class _NodeBuilder >
1271
+ _LIBCPP_HIDE_FROM_ABI __node_pointer __copy_tree (_NodeBuilder& __builder, __node_pointer __src) {
1272
+ if (!__src)
1273
+ return nullptr ;
1274
+
1275
+ __node_holder __new_node = __builder (__src->__value_ );
1276
+ if (!__new_node) {
1277
+ __allocate_node_builder __alloc_builder (*this );
1278
+ return __copy_tree (__alloc_builder, __src);
1279
+ }
1280
+
1281
+ unique_ptr<__node, __tree_deleter> __left (
1282
+ __copy_tree (__builder, static_cast <__node_pointer>(__src->__left_ )), __node_alloc_);
1283
+ __node_pointer __right = __copy_tree (__builder, static_cast <__node_pointer>(__src->__right_ ));
1284
+
1285
+ __node_pointer __new_node_ptr = __new_node.release ();
1286
+
1287
+ __new_node_ptr->__is_black_ = __src->__is_black_ ;
1288
+ __new_node_ptr->__left_ = static_cast <__node_base_pointer>(__left.release ());
1289
+ __new_node_ptr->__right_ = static_cast <__node_base_pointer>(__right);
1290
+ if (__new_node_ptr->__left_ )
1291
+ __new_node_ptr->__left_ ->__parent_ = static_cast <__end_node_pointer>(__new_node_ptr);
1292
+ if (__right)
1293
+ __right->__parent_ = static_cast <__end_node_pointer>(__new_node_ptr);
1294
+ return __new_node_ptr;
1295
+ }
1216
1296
};
1217
1297
1218
1298
template <class _Tp , class _Compare , class _Allocator >
@@ -1277,11 +1357,31 @@ __tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_next(__node_poin
1277
1357
1278
1358
template <class _Tp , class _Compare , class _Allocator >
1279
1359
__tree<_Tp, _Compare, _Allocator>& __tree<_Tp, _Compare, _Allocator>::operator =(const __tree& __t ) {
1280
- if (this != std::addressof (__t )) {
1281
- value_comp () = __t .value_comp ();
1282
- __copy_assign_alloc (__t );
1283
- __assign_multi (__t .begin (), __t .end ());
1360
+ if (this == std::addressof (__t ))
1361
+ return *this ;
1362
+
1363
+ value_comp () = __t .value_comp ();
1364
+ __copy_assign_alloc (__t );
1365
+
1366
+ if (__t .size () == 0 ) {
1367
+ clear ();
1368
+ return *this ;
1369
+ }
1370
+
1371
+ if (__size_ != 0 ) {
1372
+ _DetachedTreeCache __cache (this );
1373
+ __cache_node_builder __builder (*this , __cache);
1374
+ __end_node_.__left_ =
1375
+ static_cast <__node_base_pointer>(__copy_tree (__builder, static_cast <__node_pointer>(__t .__end_node_ .__left_ )));
1376
+ } else {
1377
+ __allocate_node_builder __builder (*this );
1378
+ __end_node_.__left_ =
1379
+ static_cast <__node_base_pointer>(__copy_tree (__builder, static_cast <__node_pointer>(__t .__end_node_ .__left_ )));
1284
1380
}
1381
+ __end_node_.__left_ ->__parent_ = __end_node ();
1382
+ __begin_node_ = static_cast <__end_node_pointer>(std::__tree_min (static_cast <__node_base_pointer>(__end_node ())));
1383
+ __size_ = __t .__size_ ;
1384
+
1285
1385
return *this ;
1286
1386
}
1287
1387
@@ -1327,11 +1427,19 @@ void __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _
1327
1427
1328
1428
template <class _Tp , class _Compare , class _Allocator >
1329
1429
__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t )
1330
- : __begin_node_(),
1430
+ : __begin_node_(__end_node() ),
1331
1431
__node_alloc_ (__node_traits::select_on_container_copy_construction(__t .__node_alloc())),
1332
1432
__size_(0 ),
1333
1433
__value_comp_(__t .value_comp()) {
1334
- __begin_node_ = __end_node ();
1434
+ if (__t .__size_ == 0 )
1435
+ return ;
1436
+
1437
+ __allocate_node_builder __builder (*this );
1438
+ __end_node_.__left_ =
1439
+ static_cast <__node_base_pointer>(__copy_tree (__builder, static_cast <__node_pointer>(__t .__end_node_ .__left_ )));
1440
+ __end_node_.__left_ ->__parent_ = __end_node ();
1441
+ __begin_node_ = static_cast <__end_node_pointer>(std::__tree_min (static_cast <__node_base_pointer>(__end_node ())));
1442
+ __size_ = __t .__size_ ;
1335
1443
}
1336
1444
1337
1445
template <class _Tp , class _Compare , class _Allocator >
@@ -1430,13 +1538,7 @@ __tree<_Tp, _Compare, _Allocator>::~__tree() {
1430
1538
1431
1539
template <class _Tp , class _Compare , class _Allocator >
1432
1540
void __tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT {
1433
- if (__nd != nullptr ) {
1434
- destroy (static_cast <__node_pointer>(__nd->__left_ ));
1435
- destroy (static_cast <__node_pointer>(__nd->__right_ ));
1436
- __node_allocator& __na = __node_alloc ();
1437
- __node_traits::destroy (__na, std::addressof (__nd->__value_ ));
1438
- __node_traits::deallocate (__na, __nd, 1 );
1439
- }
1541
+ (__tree_deleter (__node_alloc_))(__nd);
1440
1542
}
1441
1543
1442
1544
template <class _Tp , class _Compare , class _Allocator >
0 commit comments