@@ -74,6 +74,9 @@ 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 >;
@@ -238,23 +241,42 @@ class DoublyLinkedList
238
241
// Offset the array start by the storage used by the address allocator
239
242
m_array = reinterpret_cast <node_t *>(reinterpret_cast <uint8_t *>(m_reservedSpace) + addressAllocatorStorageSize * sizeof (node_t ));
240
243
241
- m_addressAllocator = address_allocator_t (m_reservedSpace, 0u , 0u , 1u , capacity, 1u );
242
244
// If allocation failed, create list with no capacity to indicate creation failed
243
245
m_cap = m_reservedSpace ? capacity : 0 ;
244
- m_back = invalid_iterator;
245
- m_begin = invalid_iterator;
246
+ m_addressAllocator = address_allocator_t (m_reservedSpace, 0u , 0u , 1u , m_cap, 1u );
246
247
}
247
248
248
249
DoublyLinkedList () = default ;
249
250
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)
251
+ // Copy Constructor
252
+ explicit DoublyLinkedList (const DoublyLinkedList& other) : m_dispose_f(other.m_dispose_f), m_allocator(other.m_allocator)
253
253
{
254
+ const size_t addressAllocatorStorageSize = (address_allocator_t::reserved_size (1u , other.m_cap , 1u ) + sizeof (node_t ) - 1 ) / sizeof (node_t );
255
+ m_currentAllocationSize = addressAllocatorStorageSize + other.m_cap ;
256
+ m_reservedSpace = reinterpret_cast <void *>(allocator_traits_t::allocate (m_allocator, m_currentAllocationSize));
257
+ // If allocation failed, create a list with no capacity
258
+ m_cap = m_reservedSpace ? other.m_cap : 0 ;
254
259
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));
260
+ // Offset the array start by the storage used by the address allocator
261
+ m_array = reinterpret_cast <node_t *>(reinterpret_cast <uint8_t *>(m_reservedSpace) + addressAllocatorStorageSize * sizeof (node_t ));
262
+
263
+ if constexpr (std::is_trivially_copyable_v<Value>)
264
+ {
265
+ // Create new address allocator by copying state
266
+ m_addressAllocator = address_allocator_t (m_cap, other.m_addressAllocator , m_reservedSpace);
267
+ // Copy memory over
268
+ memcpy (m_array, other.m_array , m_cap * sizeof (node_t ));
269
+ m_back = other.m_back ;
270
+ m_begin = other.m_begin ;
271
+ }
272
+ else
273
+ {
274
+ m_addressAllocator = address_allocator_t (m_reservedSpace, 0u , 0u , 1u , m_cap, 1u );
275
+ // Reverse iteration since we push from the front
276
+ for (auto it = other.crbegin (); it != other.crend (); it++)
277
+ pushFront (value_t (*it));
278
+
279
+ }
258
280
}
259
281
260
282
DoublyLinkedList& operator =(const DoublyLinkedList& other) = delete ;
@@ -287,14 +309,14 @@ class DoublyLinkedList
287
309
}
288
310
289
311
// 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 ;
312
+ iterator begin ();
313
+ iterator end ();
314
+ const_iterator cbegin () const ;
315
+ const_iterator cend () const ;
316
+ std::reverse_iterator<iterator > rbegin ();
317
+ std::reverse_iterator<iterator > rend ();
318
+ std::reverse_iterator<const_iterator > crbegin () const ;
319
+ std::reverse_iterator<const_iterator > crend () const ;
298
320
299
321
private:
300
322
// allocate and get the address of the next free node
@@ -362,8 +384,8 @@ class DoublyLinkedList
362
384
node_t * m_array;
363
385
364
386
uint32_t m_cap;
365
- uint32_t m_back;
366
- uint32_t m_begin;
387
+ uint32_t m_back = invalid_iterator ;
388
+ uint32_t m_begin = invalid_iterator ;
367
389
disposal_func_t m_dispose_f;
368
390
};
369
391
@@ -437,51 +459,51 @@ class DoublyLinkedList<Value, allocator>::Iterator
437
459
};
438
460
439
461
template <typename Value, class allocator >
440
- DoublyLinkedList<Value, allocator>::Iterator< true > DoublyLinkedList<Value, allocator>::begin()
462
+ DoublyLinkedList<Value, allocator>::iterator DoublyLinkedList<Value, allocator>::begin()
441
463
{
442
- return Iterator< true > (this , m_begin);
464
+ return iterator (this , m_begin);
443
465
}
444
466
445
467
template <typename Value, class allocator >
446
- DoublyLinkedList<Value, allocator>::Iterator< false > DoublyLinkedList<Value, allocator>::cbegin() const
468
+ DoublyLinkedList<Value, allocator>::const_iterator DoublyLinkedList<Value, allocator>::cbegin() const
447
469
{
448
- return Iterator< false > (this , m_begin);
470
+ return const_iterator (this , m_begin);
449
471
}
450
472
451
473
template <typename Value, class allocator >
452
- DoublyLinkedList<Value, allocator>::Iterator< true > DoublyLinkedList<Value, allocator>::end()
474
+ DoublyLinkedList<Value, allocator>::iterator DoublyLinkedList<Value, allocator>::end()
453
475
{
454
- return Iterator< true > (this , invalid_iterator);
476
+ return iterator (this , invalid_iterator);
455
477
}
456
478
457
479
template <typename Value, class allocator >
458
- DoublyLinkedList<Value, allocator>::Iterator< false > DoublyLinkedList<Value, allocator>::cend() const
480
+ DoublyLinkedList<Value, allocator>::const_iterator DoublyLinkedList<Value, allocator>::cend() const
459
481
{
460
- return Iterator< false > (this , invalid_iterator);
482
+ return const_iterator (this , invalid_iterator);
461
483
}
462
484
463
485
template <typename Value, class allocator >
464
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< true > > DoublyLinkedList<Value, allocator>::rbegin()
486
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::iterator > DoublyLinkedList<Value, allocator>::rbegin()
465
487
{
466
- return std::reverse_iterator<Iterator< true >>(Iterator< true > (this , invalid_iterator));
488
+ return std::reverse_iterator<iterator>( iterator (this , invalid_iterator));
467
489
}
468
490
469
491
template <typename Value, class allocator >
470
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< false > > DoublyLinkedList<Value, allocator>::crbegin() const
492
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::const_iterator > DoublyLinkedList<Value, allocator>::crbegin() const
471
493
{
472
- return std::reverse_iterator<Iterator< false >>(Iterator< false > (this , invalid_iterator));
494
+ return std::reverse_iterator<const_iterator>( const_iterator (this , invalid_iterator));
473
495
}
474
496
475
497
template <typename Value, class allocator >
476
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< true > > DoublyLinkedList<Value, allocator>::rend()
498
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::iterator > DoublyLinkedList<Value, allocator>::rend()
477
499
{
478
- return std::reverse_iterator<Iterator< true >>(Iterator< true > (this , m_begin));
500
+ return std::reverse_iterator<iterator>( iterator (this , m_begin));
479
501
}
480
502
481
503
template <typename Value, class allocator >
482
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< false > > DoublyLinkedList<Value, allocator>::crend() const
504
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::const_iterator > DoublyLinkedList<Value, allocator>::crend() const
483
505
{
484
- return std::reverse_iterator<Iterator< false >>(Iterator< false > (this , m_begin));
506
+ return std::reverse_iterator<const_iterator>( const_iterator (this , m_begin));
485
507
}
486
508
487
509
} // namespace core
0 commit comments