9
9
#include < type_traits> // ::std::conditional, ::std::enable_if, ::std::is_base_of
10
10
#include < cstdint> // ::std::uint*_t
11
11
#include < cstddef> // ::std::ptrdiff_t
12
- #include < algorithm> // ::std::swap
12
+ #include < algorithm> // ::std::swap, ::std::equal, ::std::lexicographical_compare
13
13
#include < tuple> // ::std::tie
14
14
#include < array> // ::std::array
15
+ #include < limits> // ::std::numeric_limits
15
16
16
17
17
- template <typename T, class TAllocator = ::std::allocator<T>>
18
+ template <typename T, class TAllocator = ::std::allocator<T>>
18
19
class xor_list
19
20
{
20
21
private:
@@ -134,7 +135,7 @@ class xor_list
134
135
}
135
136
}
136
137
137
- virtual ~xor_list ()
138
+ ~xor_list ()
138
139
{
139
140
clear ();
140
141
}
@@ -157,6 +158,11 @@ class xor_list
157
158
return *this ;
158
159
}
159
160
161
+ allocator_type get_allocator () const
162
+ {
163
+ return allocator_type (allocator);
164
+ }
165
+
160
166
void swap (xor_list &other)
161
167
{
162
168
swapImpl (other);
@@ -182,16 +188,16 @@ class xor_list
182
188
emplace_front (::std::move (data));
183
189
}
184
190
185
- template <typename ... Args>
191
+ template <typename ... Args>
186
192
void emplace_back (Args&&... args)
187
193
{
188
- (void )insertNodeToThisBefore (cend (), createNode ( ::std::forward<Args>(args)...) );
194
+ (void )emplace (cend (), ::std::forward<Args>(args)...);
189
195
}
190
196
191
- template <typename ... Args>
197
+ template <typename ... Args>
192
198
void emplace_front (Args&&... args)
193
199
{
194
- (void )insertNodeToThisBefore (cbegin (), createNode ( ::std::forward<Args>(args)...) );
200
+ (void )emplace (cbegin (), ::std::forward<Args>(args)...);
195
201
}
196
202
197
203
void pop_front ()
@@ -209,6 +215,11 @@ class xor_list
209
215
return length;
210
216
}
211
217
218
+ size_type max_size () const noexcept
219
+ {
220
+ return ::std::numeric_limits<size_type>::max () / sizeof (NodeWithValue);
221
+ }
222
+
212
223
bool empty () const noexcept
213
224
{
214
225
return (size () == 0 );
@@ -219,22 +230,22 @@ class xor_list
219
230
destroySequence (cbegin (), cend (), size ());
220
231
}
221
232
222
- T& back () noexcept
233
+ T& back ()
223
234
{
224
235
return *(--end ());
225
236
}
226
237
227
- const T& back () const noexcept
238
+ const T& back () const
228
239
{
229
240
return *(--cend ());
230
241
}
231
242
232
- T& front () noexcept
243
+ T& front ()
233
244
{
234
245
return *begin ();
235
246
}
236
247
237
- const T& front () const noexcept
248
+ const T& front () const
238
249
{
239
250
return *cbegin ();
240
251
}
@@ -270,13 +281,13 @@ class xor_list
270
281
return { reinterpret_cast <Node*>(afterTail.xorPtr ), &afterTail };
271
282
}
272
283
273
- void sort () noexcept
284
+ void sort ()
274
285
{
275
286
sort (::std::less<T>{});
276
287
}
277
288
278
- template < class Compare >
279
- void sort (Compare isLess) noexcept
289
+ template < typename Compare>
290
+ void sort (Compare isLess)
280
291
{
281
292
using Range = ::std::pair<const_iterator, const_iterator>;
282
293
struct NullableRange
@@ -347,13 +358,12 @@ class xor_list
347
358
// strong exception-safe guarantee
348
359
iterator insert (const_iterator position, const_reference val)
349
360
{
350
- // insertNodeToThisBefore noexcept!
351
- return insertNodeToThisBefore (position, createNode (val)).first ;
361
+ return emplace (position, val);
352
362
}
353
363
354
364
// WARNING! Iterators equal to position will become invalid
355
365
// strong exception-safe guarantee
356
- template < class InputIterator >
366
+ template < typename InputIterator>
357
367
iterator insert (const_iterator position, InputIterator first, InputIterator last)
358
368
{
359
369
if (first == last)
@@ -381,7 +391,17 @@ class xor_list
381
391
return result;
382
392
}
383
393
394
+ // WARNING! Iterators equal to position will become invalid
395
+ // strong exception-safe guarantee
396
+ template <typename ... Args>
397
+ iterator emplace (const_iterator position, Args&&... args)
398
+ {
399
+ // insertNodeToThisBefore noexcept!
400
+ return insertNodeToThisBefore (position, createNode (::std::forward<Args>(args)...)).first ;
401
+ }
402
+
384
403
// WARNING! All iterators will become invalid
404
+ // Complexity: O(1)
385
405
void reverse () noexcept
386
406
{
387
407
if (empty ())
@@ -418,6 +438,32 @@ class xor_list
418
438
return { first.prev , last.current };
419
439
}
420
440
441
+ size_type remove (const T &value)
442
+ {
443
+ return remove_if ([&value](const T &elem) { return (elem == value); });
444
+ }
445
+
446
+ template <typename UnaryPredicate>
447
+ size_type remove_if (UnaryPredicate p)
448
+ {
449
+ size_type result = 0 ;
450
+
451
+ for (const_iterator iter = cbegin (); iter != cend ();)
452
+ {
453
+ if (p (*iter))
454
+ {
455
+ iter = erase (iter);
456
+ ++result;
457
+ }
458
+ else
459
+ {
460
+ ++iter;
461
+ }
462
+ }
463
+
464
+ return result;
465
+ }
466
+
421
467
void resize (size_type count)
422
468
{
423
469
resizeImpl (count);
@@ -428,7 +474,7 @@ class xor_list
428
474
resizeImpl (count, val);
429
475
}
430
476
431
- template <typename InputIterator>
477
+ template <typename InputIterator>
432
478
typename ::std::enable_if<::std::is_base_of<::std::input_iterator_tag,
433
479
typename ::std::iterator_traits<InputIterator>::iterator_category>::value>::type
434
480
assign (InputIterator first, InputIterator last)
@@ -478,7 +524,7 @@ class xor_list
478
524
}
479
525
480
526
481
- void splice (const_iterator position, xor_list &x) noexcept
527
+ void splice (const_iterator position, xor_list &x)
482
528
{
483
529
if ((this == ::std::addressof (x)) || (x.empty ()))
484
530
{
@@ -491,7 +537,7 @@ class xor_list
491
537
(void )insertSequenceToThisBefore (position, range.first , range.second , distance);
492
538
}
493
539
494
- void splice (const_iterator position, xor_list &x, const_iterator i) noexcept
540
+ void splice (const_iterator position, xor_list &x, const_iterator i)
495
541
{
496
542
if ((this == ::std::addressof (x)) && ((position == i) || (position.prev == i.current )))
497
543
{
@@ -502,7 +548,7 @@ class xor_list
502
548
(void )insertNodeToThisBefore (position, static_cast <NodeWithValue*>(range.first .current ));
503
549
}
504
550
505
- void splice (const_iterator position, xor_list &x, const_iterator first, const_iterator last) noexcept
551
+ void splice (const_iterator position, xor_list &x, const_iterator first, const_iterator last)
506
552
{
507
553
if (first == last)
508
554
{
@@ -522,7 +568,7 @@ class xor_list
522
568
}
523
569
524
570
// All iterators will become invalid
525
- template <typename BinaryPredicate>
571
+ template <typename BinaryPredicate>
526
572
void unique (BinaryPredicate isEqual)
527
573
{
528
574
if (size () < 2 )
@@ -545,14 +591,14 @@ class xor_list
545
591
}
546
592
547
593
// All iterators from *this and x will become invalid
548
- void merge (xor_list &x) noexcept
594
+ void merge (xor_list &x)
549
595
{
550
596
merge (x, ::std::less<T>{});
551
597
}
552
598
553
599
// All iterators from *this and x will become invalid
554
- template <typename Compare>
555
- void merge (xor_list &x, Compare isLess) noexcept
600
+ template <typename Compare>
601
+ void merge (xor_list &x, Compare isLess)
556
602
{
557
603
if (!x.empty ())
558
604
{
@@ -595,14 +641,14 @@ class xor_list
595
641
596
642
Node (const Node&) noexcept = default ;
597
643
Node (Node &&) noexcept = default ;
598
-
644
+
599
645
virtual ~Node () = default ;
600
646
601
647
Node& operator =(const Node&) noexcept = default ;
602
648
Node& operator =(Node &&) noexcept = default ;
603
649
};
604
650
605
- struct NodeWithValue : Node
651
+ struct NodeWithValue final : Node
606
652
{
607
653
T value;
608
654
@@ -723,7 +769,7 @@ class xor_list
723
769
};
724
770
725
771
726
- struct CutResult
772
+ struct CutResult final
727
773
{
728
774
::std::pair<iterator, iterator> cutted;
729
775
iterator end;
@@ -788,10 +834,8 @@ class xor_list
788
834
return insertNodeBefore (position, node);
789
835
}
790
836
791
- /*
792
- * All iterators equal to <position> will become invalid
793
- * Returns valid range [inserted, position]
794
- */
837
+ // All iterators equal to <position> will become invalid
838
+ // Returns valid range [inserted, position]
795
839
static ::std::pair<iterator, iterator>
796
840
insertNodeBefore (const_iterator position, NodeWithValue *const node) noexcept
797
841
{
@@ -819,11 +863,10 @@ class xor_list
819
863
return insertSequenceBefore (position, begin, end);
820
864
}
821
865
822
- /*
823
- * All iterators equal to <position>, <begin> will become invalid
824
- * Iterators equal to end still remains valid (--end == result.second)
825
- * Returns valid range [begin, position]
826
- */
866
+
867
+ // All iterators equal to <position>, <begin> will become invalid
868
+ // Iterators equal to end still remains valid (--end == result.second)
869
+ // Returns valid range [begin, position]
827
870
static ::std::pair<iterator, iterator>
828
871
insertSequenceBefore (const_iterator position, const_iterator begin,
829
872
const_iterator end) noexcept
@@ -852,14 +895,12 @@ class xor_list
852
895
return cutSequence (first, last);
853
896
}
854
897
855
- /*
856
- * Returns iterators to the first cutted and following the last cutted elements
857
- * Decrement result.first or increment result.second is UB
858
- * Dereference result.second is UB
859
- * Increment and dereference result.first are still valid
860
- * Decrement result.second returns is an iterator to the last cutted element
861
- * Iterators equal to begin, end will become invalid
862
- */
898
+ // Returns iterators to the first cutted and following the last cutted elements
899
+ // Decrement result.first or increment result.second is UB
900
+ // Dereference result.second is UB
901
+ // Increment and dereference result.first are still valid
902
+ // Decrement result.second returns is an iterator to the last cutted element
903
+ // Iterators equal to begin, end will become invalid
863
904
static CutResult
864
905
cutSequence (const_iterator begin, const_iterator end) noexcept
865
906
{
@@ -1026,10 +1067,8 @@ class xor_list
1026
1067
return mergeSequences (beginTo, endTo, beginFrom, endFrom, ::std::forward<LessCompare>(isLess));
1027
1068
}
1028
1069
1029
- /*
1030
- * All iterators will become invalid
1031
- * Return new range [first, second)
1032
- */
1070
+ // All iterators will become invalid
1071
+ // Return new range [first, second)
1033
1072
template <typename LessCompare>
1034
1073
static ::std::pair<iterator, iterator>
1035
1074
mergeSequences (const_iterator beginTo, const_iterator endTo,
@@ -1080,4 +1119,43 @@ class xor_list
1080
1119
}
1081
1120
};
1082
1121
1122
+
1123
+ // Comparison operators
1124
+
1125
+ template <typename T, class TAllocator >
1126
+ bool operator ==(const xor_list<T, TAllocator> &lhs, const xor_list<T, TAllocator> &rhs)
1127
+ {
1128
+ return ((lhs.size () == rhs.size ()) && (::std::equal (lhs.cbegin (), lhs.cend (), rhs.cbegin ())));
1129
+ }
1130
+
1131
+ template <typename T, class TAllocator >
1132
+ bool operator !=(const xor_list<T, TAllocator> &lhs, const xor_list<T, TAllocator> &rhs)
1133
+ {
1134
+ return (!(lhs == rhs));
1135
+ }
1136
+
1137
+ template <typename T, class TAllocator >
1138
+ bool operator <(const xor_list<T, TAllocator> &lhs, const xor_list<T, TAllocator> &rhs)
1139
+ {
1140
+ return ::std::lexicographical_compare (lhs.cbegin (), lhs.cend (), rhs.cbegin (), rhs.cend ());
1141
+ }
1142
+
1143
+ template <typename T, class TAllocator >
1144
+ bool operator >(const xor_list<T, TAllocator> &lhs, const xor_list<T, TAllocator> &rhs)
1145
+ {
1146
+ return (rhs < lhs);
1147
+ }
1148
+
1149
+ template <typename T, class TAllocator >
1150
+ bool operator <=(const xor_list<T, TAllocator> &lhs, const xor_list<T, TAllocator> &rhs)
1151
+ {
1152
+ return (!(rhs < lhs));
1153
+ }
1154
+
1155
+ template <typename T, class TAllocator >
1156
+ bool operator >=(const xor_list<T, TAllocator> &lhs, const xor_list<T, TAllocator> &rhs)
1157
+ {
1158
+ return (!(lhs < rhs));
1159
+ }
1160
+
1083
1161
#endif // XORLIST_XOR_LIST_H
0 commit comments