@@ -69,7 +69,9 @@ 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
75
77
using allocator_t = allocator;
@@ -245,7 +247,15 @@ class DoublyLinkedList
245
247
246
248
DoublyLinkedList () = default ;
247
249
248
- DoublyLinkedList (const DoublyLinkedList& other) = delete ;
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
+ {
254
+ 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));
258
+ }
249
259
250
260
DoublyLinkedList& operator =(const DoublyLinkedList& other) = delete ;
251
261
@@ -277,14 +287,14 @@ class DoublyLinkedList
277
287
}
278
288
279
289
// 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 ;
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 ;
288
298
289
299
private:
290
300
// allocate and get the address of the next free node
@@ -361,13 +371,14 @@ class DoublyLinkedList
361
371
362
372
// Satifies std::bidirectional_iterator
363
373
template <typename Value, class allocator >
374
+ template <bool Mutable>
364
375
class DoublyLinkedList <Value, allocator>::Iterator
365
376
{
366
- using iterable_t = DoublyLinkedList<Value, allocator>;
367
- using this_t = iterable_t ::Iterator ;
368
- friend class iterable_t ;
377
+ using base_iterable_t = DoublyLinkedList<Value, allocator>;
378
+ using iterable_t = std:: conditional_t <Mutable, base_iterable_t , const base_iterable_t > ;
379
+ friend class base_iterable_t ;
369
380
public:
370
- using value_type = const Value;
381
+ using value_type = std:: conditional_t <Mutable, Value, const Value> ;
371
382
using pointer = value_type*;
372
383
using reference = value_type&;
373
384
using difference_type = int32_t ;
@@ -409,68 +420,68 @@ class DoublyLinkedList<Value, allocator>::Iterator
409
420
}
410
421
411
422
// Deref
412
- value_type& operator *() const
423
+ reference operator *() const
413
424
{
414
425
return m_iterable->get (m_current)->data ;
415
426
}
416
427
417
- value_type* operator ->() const
428
+ pointer operator ->() const
418
429
{
419
430
return & operator *();
420
431
}
421
432
private:
422
- DoublyLinkedList<Value, allocator>:: Iterator(const iterable_t * const iterable, uint32_t idx) : m_iterable(iterable), m_current(idx) {}
433
+ Iterator (iterable_t * const iterable, uint32_t idx) : m_iterable(iterable), m_current(idx) {}
423
434
424
- const iterable_t * m_iterable;
435
+ iterable_t * m_iterable;
425
436
uint32_t m_current;
426
437
};
427
438
428
439
template <typename Value, class allocator >
429
- DoublyLinkedList<Value, allocator>::Iterator DoublyLinkedList<Value, allocator>::begin()
440
+ DoublyLinkedList<Value, allocator>::Iterator< true > DoublyLinkedList<Value, allocator>::begin()
430
441
{
431
- return Iterator (this , m_begin);
442
+ return Iterator< true > (this , m_begin);
432
443
}
433
444
434
445
template <typename Value, class allocator >
435
- DoublyLinkedList<Value, allocator>::Iterator DoublyLinkedList<Value, allocator>::cbegin() const
446
+ DoublyLinkedList<Value, allocator>::Iterator< false > DoublyLinkedList<Value, allocator>::cbegin() const
436
447
{
437
- return Iterator (this , m_begin);
448
+ return Iterator< false > (this , m_begin);
438
449
}
439
450
440
451
template <typename Value, class allocator >
441
- DoublyLinkedList<Value, allocator>::Iterator DoublyLinkedList<Value, allocator>::end()
452
+ DoublyLinkedList<Value, allocator>::Iterator< true > DoublyLinkedList<Value, allocator>::end()
442
453
{
443
- return Iterator (this , invalid_iterator);
454
+ return Iterator< true > (this , invalid_iterator);
444
455
}
445
456
446
457
template <typename Value, class allocator >
447
- DoublyLinkedList<Value, allocator>::Iterator DoublyLinkedList<Value, allocator>::cend() const
458
+ DoublyLinkedList<Value, allocator>::Iterator< false > DoublyLinkedList<Value, allocator>::cend() const
448
459
{
449
- return Iterator (this , invalid_iterator);
460
+ return Iterator< false > (this , invalid_iterator);
450
461
}
451
462
452
463
template <typename Value, class allocator >
453
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator> DoublyLinkedList<Value, allocator>::rbegin()
464
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< true > > DoublyLinkedList<Value, allocator>::rbegin()
454
465
{
455
- return std::reverse_iterator<Iterator> (Iterator (this , invalid_iterator));
466
+ return std::reverse_iterator<Iterator< true >> (Iterator< true > (this , invalid_iterator));
456
467
}
457
468
458
469
template <typename Value, class allocator >
459
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator> DoublyLinkedList<Value, allocator>::crbegin() const
470
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< false > > DoublyLinkedList<Value, allocator>::crbegin() const
460
471
{
461
- return std::reverse_iterator<Iterator> (Iterator (this , invalid_iterator));
472
+ return std::reverse_iterator<Iterator< false >> (Iterator< false > (this , invalid_iterator));
462
473
}
463
474
464
475
template <typename Value, class allocator >
465
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator> DoublyLinkedList<Value, allocator>::rend()
476
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< true > > DoublyLinkedList<Value, allocator>::rend()
466
477
{
467
- return std::reverse_iterator<Iterator> (Iterator (this , m_begin));
478
+ return std::reverse_iterator<Iterator< true >> (Iterator< true > (this , m_begin));
468
479
}
469
480
470
481
template <typename Value, class allocator >
471
- std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator> DoublyLinkedList<Value, allocator>::crend() const
482
+ std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::Iterator< false > > DoublyLinkedList<Value, allocator>::crend() const
472
483
{
473
- return std::reverse_iterator<Iterator> (Iterator (this , m_begin));
484
+ return std::reverse_iterator<Iterator< false >> (Iterator< false > (this , m_begin));
474
485
}
475
486
476
487
} // namespace core
0 commit comments