@@ -69,9 +69,14 @@ template<typename Value, class allocator = core::allocator<SDoublyLinkedNode<Val
69
69
class DoublyLinkedList
70
70
{
71
71
public:
72
+ template <bool Mutable>
72
73
class Iterator ;
74
+ template <bool Mutable>
73
75
friend class Iterator ;
74
76
77
+ using iterator = Iterator<true >;
78
+ using const_iterator = Iterator<false >;
79
+
75
80
using allocator_t = allocator;
76
81
using allocator_traits_t = std::allocator_traits<allocator_t >;
77
82
using address_allocator_t = PoolAddressAllocator<uint32_t >;
@@ -236,16 +241,43 @@ class DoublyLinkedList
236
241
// Offset the array start by the storage used by the address allocator
237
242
m_array = reinterpret_cast <node_t *>(reinterpret_cast <uint8_t *>(m_reservedSpace) + addressAllocatorStorageSize * sizeof (node_t ));
238
243
239
- m_addressAllocator = address_allocator_t (m_reservedSpace, 0u , 0u , 1u , capacity, 1u );
240
244
// If allocation failed, create list with no capacity to indicate creation failed
241
245
m_cap = m_reservedSpace ? capacity : 0 ;
242
- m_back = invalid_iterator;
243
- m_begin = invalid_iterator;
246
+ m_addressAllocator = address_allocator_t (m_reservedSpace, 0u , 0u , 1u , m_cap, 1u );
244
247
}
245
248
246
249
DoublyLinkedList () = default ;
247
250
248
- DoublyLinkedList (const DoublyLinkedList& other) = delete ;
251
+ // Copy Constructor
252
+ explicit DoublyLinkedList (const DoublyLinkedList& other) : m_dispose_f(other.m_dispose_f), m_allocator(other.m_allocator)
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 ;
259
+ if (!m_cap) return ; // Allocation failed
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
+ }
280
+ }
249
281
250
282
DoublyLinkedList& operator =(const DoublyLinkedList& other) = delete ;
251
283
@@ -277,14 +309,14 @@ class DoublyLinkedList
277
309
}
278
310
279
311
// Iterator stuff
280
- Iterator begin ();
281
- Iterator end ();
282
- Iterator cbegin () const ;
283
- Iterator cend () const ;
284
- std::reverse_iterator<Iterator > rbegin ();
285
- std::reverse_iterator<Iterator > rend ();
286
- std::reverse_iterator<Iterator > crbegin () const ;
287
- std::reverse_iterator<Iterator > 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 ;
288
320
289
321
private:
290
322
// allocate and get the address of the next free node
@@ -352,22 +384,23 @@ class DoublyLinkedList
352
384
node_t * m_array;
353
385
354
386
uint32_t m_cap;
355
- uint32_t m_back;
356
- uint32_t m_begin;
387
+ uint32_t m_back = invalid_iterator ;
388
+ uint32_t m_begin = invalid_iterator ;
357
389
disposal_func_t m_dispose_f;
358
390
};
359
391
360
392
// ---------------------------------------------------- ITERATOR -----------------------------------------------------------
361
393
362
394
// Satifies std::bidirectional_iterator
363
395
template <typename Value, class allocator >
396
+ template <bool Mutable>
364
397
class DoublyLinkedList <Value, allocator>::Iterator
365
398
{
366
- using iterable_t = DoublyLinkedList<Value, allocator>;
367
- using this_t = iterable_t ::Iterator ;
368
- friend class iterable_t ;
399
+ using base_iterable_t = DoublyLinkedList<Value, allocator>;
400
+ using iterable_t = std:: conditional_t <Mutable, base_iterable_t , const base_iterable_t > ;
401
+ friend class base_iterable_t ;
369
402
public:
370
- using value_type = const Value;
403
+ using value_type = std:: conditional_t <Mutable, Value, const Value> ;
371
404
using pointer = value_type*;
372
405
using reference = value_type&;
373
406
using difference_type = int32_t ;
@@ -409,68 +442,68 @@ class DoublyLinkedList<Value, allocator>::Iterator
409
442
}
410
443
411
444
// Deref
412
- value_type& operator *() const
445
+ reference operator *() const
413
446
{
414
447
return m_iterable->get (m_current)->data ;
415
448
}
416
449
417
- value_type* operator ->() const
450
+ pointer operator ->() const
418
451
{
419
452
return & operator *();
420
453
}
421
454
private:
422
- DoublyLinkedList<Value, allocator>:: Iterator(const iterable_t * const iterable, uint32_t idx) : m_iterable(iterable), m_current(idx) {}
455
+ Iterator (iterable_t * const iterable, uint32_t idx) : m_iterable(iterable), m_current(idx) {}
423
456
424
- const iterable_t * m_iterable;
457
+ iterable_t * m_iterable;
425
458
uint32_t m_current;
426
459
};
427
460
428
461
template <typename Value, class allocator >
429
- DoublyLinkedList<Value, allocator>::Iterator DoublyLinkedList<Value, allocator>::begin()
462
+ DoublyLinkedList<Value, allocator>::iterator DoublyLinkedList<Value, allocator>::begin()
430
463
{
431
- return Iterator (this , m_begin);
464
+ return iterator (this , m_begin);
432
465
}
433
466
434
467
template <typename Value, class allocator >
435
- DoublyLinkedList<Value, allocator>::Iterator DoublyLinkedList<Value, allocator>::cbegin() const
468
+ DoublyLinkedList<Value, allocator>::const_iterator DoublyLinkedList<Value, allocator>::cbegin() const
436
469
{
437
- return Iterator (this , m_begin);
470
+ return const_iterator (this , m_begin);
438
471
}
439
472
440
473
template <typename Value, class allocator >
441
- DoublyLinkedList<Value, allocator>::Iterator DoublyLinkedList<Value, allocator>::end()
474
+ DoublyLinkedList<Value, allocator>::iterator DoublyLinkedList<Value, allocator>::end()
442
475
{
443
- return Iterator (this , invalid_iterator);
476
+ return iterator (this , invalid_iterator);
444
477
}
445
478
446
479
template <typename Value, class allocator >
447
- DoublyLinkedList<Value, allocator>::Iterator DoublyLinkedList<Value, allocator>::cend() const
480
+ DoublyLinkedList<Value, allocator>::const_iterator DoublyLinkedList<Value, allocator>::cend() const
448
481
{
449
- return Iterator (this , invalid_iterator);
482
+ return const_iterator (this , invalid_iterator);
450
483
}
451
484
452
485
template <typename Value, class allocator >
453
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator > DoublyLinkedList<Value, allocator>::rbegin()
486
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::iterator > DoublyLinkedList<Value, allocator>::rbegin()
454
487
{
455
- return std::reverse_iterator<Iterator>( Iterator (this , invalid_iterator));
488
+ return std::reverse_iterator<iterator>( iterator (this , invalid_iterator));
456
489
}
457
490
458
491
template <typename Value, class allocator >
459
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator > DoublyLinkedList<Value, allocator>::crbegin() const
492
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::const_iterator > DoublyLinkedList<Value, allocator>::crbegin() const
460
493
{
461
- return std::reverse_iterator<Iterator>( Iterator (this , invalid_iterator));
494
+ return std::reverse_iterator<const_iterator>( const_iterator (this , invalid_iterator));
462
495
}
463
496
464
497
template <typename Value, class allocator >
465
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator > DoublyLinkedList<Value, allocator>::rend()
498
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::iterator > DoublyLinkedList<Value, allocator>::rend()
466
499
{
467
- return std::reverse_iterator<Iterator>( Iterator (this , m_begin));
500
+ return std::reverse_iterator<iterator>( iterator (this , m_begin));
468
501
}
469
502
470
503
template <typename Value, class allocator >
471
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator > DoublyLinkedList<Value, allocator>::crend() const
504
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::const_iterator > DoublyLinkedList<Value, allocator>::crend() const
472
505
{
473
- return std::reverse_iterator<Iterator>( Iterator (this , m_begin));
506
+ return std::reverse_iterator<const_iterator>( const_iterator (this , m_begin));
474
507
}
475
508
476
509
} // namespace core
0 commit comments