@@ -74,13 +74,18 @@ class DoublyLinkedList
74
74
template <bool Mutable>
75
75
friend class Iterator ;
76
76
77
+ using iterator = Iterator<true >;
78
+ using const_iterator = Iterator<false >;
79
+
77
80
using allocator_t = allocator;
78
81
using allocator_traits_t = std::allocator_traits<allocator_t >;
79
82
using address_allocator_t = PoolAddressAllocator<uint32_t >;
80
83
using node_t = SDoublyLinkedNode<Value>;
81
84
using value_t = Value;
82
85
using disposal_func_t = std::function<void (value_t &)>;
83
86
87
+ static constexpr bool IsTriviallyCopyable = std::is_trivially_copyable_v<Value>;
88
+
84
89
_NBL_STATIC_INLINE_CONSTEXPR uint32_t invalid_iterator = node_t ::invalid_iterator;
85
90
86
91
// get the fixed capacity
@@ -238,23 +243,42 @@ class DoublyLinkedList
238
243
// Offset the array start by the storage used by the address allocator
239
244
m_array = reinterpret_cast <node_t *>(reinterpret_cast <uint8_t *>(m_reservedSpace) + addressAllocatorStorageSize * sizeof (node_t ));
240
245
241
- m_addressAllocator = address_allocator_t (m_reservedSpace, 0u , 0u , 1u , capacity, 1u );
242
246
// If allocation failed, create list with no capacity to indicate creation failed
243
247
m_cap = m_reservedSpace ? capacity : 0 ;
244
- m_back = invalid_iterator;
245
- m_begin = invalid_iterator;
248
+ m_addressAllocator = address_allocator_t (m_reservedSpace, 0u , 0u , 1u , m_cap, 1u );
246
249
}
247
250
248
251
DoublyLinkedList () = default ;
249
252
250
- // Unless there's a way of knowing whether for our type a shallow copy is the same as invoking the copy constructor,
251
- // we must iterate over the whole list and copy instance by instance
252
- explicit DoublyLinkedList (const DoublyLinkedList& other) : DoublyLinkedList(other.m_cap, disposal_func_t (other.m_dispose_f), other.m_allocator)
253
+ // Copy Constructor
254
+ explicit DoublyLinkedList (const DoublyLinkedList& other) : m_dispose_f(other.m_dispose_f), m_allocator(other.m_allocator)
253
255
{
256
+ const size_t addressAllocatorStorageSize = (address_allocator_t::reserved_size (1u , other.m_cap , 1u ) + sizeof (node_t ) - 1 ) / sizeof (node_t );
257
+ m_currentAllocationSize = addressAllocatorStorageSize + other.m_cap ;
258
+ m_reservedSpace = reinterpret_cast <void *>(allocator_traits_t::allocate (m_allocator, m_currentAllocationSize));
259
+ // If allocation failed, create a list with no capacity
260
+ m_cap = m_reservedSpace ? other.m_cap : 0 ;
254
261
if (!m_cap) return ; // Allocation failed
255
- // Reverse iteration since we push from the front
256
- for (auto it = other.crbegin (); it != other.crend (); it++)
257
- pushFront (value_t (*it));
262
+ // Offset the array start by the storage used by the address allocator
263
+ m_array = reinterpret_cast <node_t *>(reinterpret_cast <uint8_t *>(m_reservedSpace) + addressAllocatorStorageSize * sizeof (node_t ));
264
+
265
+ if constexpr (IsTriviallyCopyable)
266
+ {
267
+ // Create new address allocator by copying state
268
+ m_addressAllocator = address_allocator_t (m_cap, other.m_addressAllocator , m_reservedSpace);
269
+ // Copy memory over
270
+ memcpy (m_array, other.m_array , m_cap * sizeof (node_t ));
271
+ m_back = other.m_back ;
272
+ m_begin = other.m_begin ;
273
+ }
274
+ else
275
+ {
276
+ m_addressAllocator = address_allocator_t (m_reservedSpace, 0u , 0u , 1u , m_cap, 1u );
277
+ // Reverse iteration since we push from the front
278
+ for (auto it = other.crbegin (); it != other.crend (); it++)
279
+ pushFront (value_t (*it));
280
+
281
+ }
258
282
}
259
283
260
284
DoublyLinkedList& operator =(const DoublyLinkedList& other) = delete ;
@@ -287,14 +311,14 @@ class DoublyLinkedList
287
311
}
288
312
289
313
// Iterator stuff
290
- Iterator< true > begin ();
291
- Iterator< true > end ();
292
- Iterator< false > cbegin () const ;
293
- Iterator< false > cend () const ;
294
- std::reverse_iterator<Iterator< true > > rbegin ();
295
- std::reverse_iterator<Iterator< true > > rend ();
296
- std::reverse_iterator<Iterator< false > > crbegin () const ;
297
- std::reverse_iterator<Iterator< false > > crend () const ;
314
+ iterator begin ();
315
+ iterator end ();
316
+ const_iterator cbegin () const ;
317
+ const_iterator cend () const ;
318
+ std::reverse_iterator<iterator > rbegin ();
319
+ std::reverse_iterator<iterator > rend ();
320
+ std::reverse_iterator<const_iterator > crbegin () const ;
321
+ std::reverse_iterator<const_iterator > crend () const ;
298
322
299
323
private:
300
324
// allocate and get the address of the next free node
@@ -362,8 +386,8 @@ class DoublyLinkedList
362
386
node_t * m_array;
363
387
364
388
uint32_t m_cap;
365
- uint32_t m_back;
366
- uint32_t m_begin;
389
+ uint32_t m_back = invalid_iterator ;
390
+ uint32_t m_begin = invalid_iterator ;
367
391
disposal_func_t m_dispose_f;
368
392
};
369
393
@@ -437,51 +461,51 @@ class DoublyLinkedList<Value, allocator>::Iterator
437
461
};
438
462
439
463
template <typename Value, class allocator >
440
- DoublyLinkedList<Value, allocator>::Iterator< true > DoublyLinkedList<Value, allocator>::begin()
464
+ DoublyLinkedList<Value, allocator>::iterator DoublyLinkedList<Value, allocator>::begin()
441
465
{
442
- return Iterator< true > (this , m_begin);
466
+ return iterator (this , m_begin);
443
467
}
444
468
445
469
template <typename Value, class allocator >
446
- DoublyLinkedList<Value, allocator>::Iterator< false > DoublyLinkedList<Value, allocator>::cbegin() const
470
+ DoublyLinkedList<Value, allocator>::const_iterator DoublyLinkedList<Value, allocator>::cbegin() const
447
471
{
448
- return Iterator< false > (this , m_begin);
472
+ return const_iterator (this , m_begin);
449
473
}
450
474
451
475
template <typename Value, class allocator >
452
- DoublyLinkedList<Value, allocator>::Iterator< true > DoublyLinkedList<Value, allocator>::end()
476
+ DoublyLinkedList<Value, allocator>::iterator DoublyLinkedList<Value, allocator>::end()
453
477
{
454
- return Iterator< true > (this , invalid_iterator);
478
+ return iterator (this , invalid_iterator);
455
479
}
456
480
457
481
template <typename Value, class allocator >
458
- DoublyLinkedList<Value, allocator>::Iterator< false > DoublyLinkedList<Value, allocator>::cend() const
482
+ DoublyLinkedList<Value, allocator>::const_iterator DoublyLinkedList<Value, allocator>::cend() const
459
483
{
460
- return Iterator< false > (this , invalid_iterator);
484
+ return const_iterator (this , invalid_iterator);
461
485
}
462
486
463
487
template <typename Value, class allocator >
464
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< true > > DoublyLinkedList<Value, allocator>::rbegin()
488
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::iterator > DoublyLinkedList<Value, allocator>::rbegin()
465
489
{
466
- return std::reverse_iterator<Iterator< true >>(Iterator< true > (this , invalid_iterator));
490
+ return std::reverse_iterator<iterator>( iterator (this , invalid_iterator));
467
491
}
468
492
469
493
template <typename Value, class allocator >
470
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< false > > DoublyLinkedList<Value, allocator>::crbegin() const
494
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::const_iterator > DoublyLinkedList<Value, allocator>::crbegin() const
471
495
{
472
- return std::reverse_iterator<Iterator< false >>(Iterator< false > (this , invalid_iterator));
496
+ return std::reverse_iterator<const_iterator>( const_iterator (this , invalid_iterator));
473
497
}
474
498
475
499
template <typename Value, class allocator >
476
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< true > > DoublyLinkedList<Value, allocator>::rend()
500
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::iterator > DoublyLinkedList<Value, allocator>::rend()
477
501
{
478
- return std::reverse_iterator<Iterator< true >>(Iterator< true > (this , m_begin));
502
+ return std::reverse_iterator<iterator>( iterator (this , m_begin));
479
503
}
480
504
481
505
template <typename Value, class allocator >
482
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< false > > DoublyLinkedList<Value, allocator>::crend() const
506
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::const_iterator > DoublyLinkedList<Value, allocator>::crend() const
483
507
{
484
- return std::reverse_iterator<Iterator< false >>(Iterator< false > (this , m_begin));
508
+ return std::reverse_iterator<const_iterator>( const_iterator (this , m_begin));
485
509
}
486
510
487
511
} // namespace core
0 commit comments