Skip to content

Commit 7680d4c

Browse files
authored
Missed methods #7 (#12)
* fix noexceptness; add final * template<class -> template<typename replace * Add emplace(pos, ...) method * remove virtual from list d'tor * add get_allocator method * add remove, remove_if methods * code style fix * Add max_size() method * Fix tests C++11 compatibility * add comparison operators * minor comments fix [skip ci] * Update README.md
1 parent 863b24d commit 7680d4c

File tree

3 files changed

+321
-56
lines changed

3 files changed

+321
-56
lines changed

README.md

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
# cpp-xor-list [![Build Status](https://travis-ci.org/NikitkoCent/cpp-xor-list.svg?branch=master)](https://travis-ci.org/NikitkoCent/cpp-xor-list) [![Code Coverage](https://codecov.io/gh/NikitkoCent/cpp-xor-list/branch/master/graph/badge.svg)](https://codecov.io/gh/NikitkoCent/cpp-xor-list) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/NikitkoCent/cpp-xor-list/blob/master/LICENSE)
22
C++11-compatible implementation of [XOR linked list](https://en.wikipedia.org/wiki/XOR_linked_list)
3-
with STL-like interface. Most of C++14 `std::list` methods are supported.
3+
with STL-like interface. Most of C++14 `std::list` methods are also supported.
44

55
<details>
66
<summary>Notes</summary>
77

88
### Not supported methods:
9-
* `std::list::emplace` (but `std::list::emplace_<front|back>` are supported) - may be added later
10-
* comparison operators (`operator==`, `operator<=` etc) - may be added later
11-
* `std::list::max_size` - may be added later
12-
* `std::list::get_allocator` - may be added later
13-
* `std::list::remove_if` - may be added later
14-
* `std::erase_if` - may be added later
9+
* `std::erase_if` - will be added after C++20 release
1510
</details>
1611

1712
## Example

include/xor_list/xor_list.h

+127-49
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
#include <type_traits> // ::std::conditional, ::std::enable_if, ::std::is_base_of
1010
#include <cstdint> // ::std::uint*_t
1111
#include <cstddef> // ::std::ptrdiff_t
12-
#include <algorithm> // ::std::swap
12+
#include <algorithm> // ::std::swap, ::std::equal, ::std::lexicographical_compare
1313
#include <tuple> // ::std::tie
1414
#include <array> // ::std::array
15+
#include <limits> // ::std::numeric_limits
1516

1617

17-
template <typename T, class TAllocator = ::std::allocator<T>>
18+
template<typename T, class TAllocator = ::std::allocator<T>>
1819
class xor_list
1920
{
2021
private:
@@ -134,7 +135,7 @@ class xor_list
134135
}
135136
}
136137

137-
virtual ~xor_list()
138+
~xor_list()
138139
{
139140
clear();
140141
}
@@ -157,6 +158,11 @@ class xor_list
157158
return *this;
158159
}
159160

161+
allocator_type get_allocator() const
162+
{
163+
return allocator_type(allocator);
164+
}
165+
160166
void swap(xor_list &other)
161167
{
162168
swapImpl(other);
@@ -182,16 +188,16 @@ class xor_list
182188
emplace_front(::std::move(data));
183189
}
184190

185-
template <typename... Args>
191+
template<typename... Args>
186192
void emplace_back(Args&&... args)
187193
{
188-
(void)insertNodeToThisBefore(cend(), createNode(::std::forward<Args>(args)...));
194+
(void)emplace(cend(), ::std::forward<Args>(args)...);
189195
}
190196

191-
template <typename... Args>
197+
template<typename... Args>
192198
void emplace_front(Args&&... args)
193199
{
194-
(void)insertNodeToThisBefore(cbegin(), createNode(::std::forward<Args>(args)...));
200+
(void)emplace(cbegin(), ::std::forward<Args>(args)...);
195201
}
196202

197203
void pop_front()
@@ -209,6 +215,11 @@ class xor_list
209215
return length;
210216
}
211217

218+
size_type max_size() const noexcept
219+
{
220+
return ::std::numeric_limits<size_type>::max() / sizeof(NodeWithValue);
221+
}
222+
212223
bool empty() const noexcept
213224
{
214225
return (size() == 0);
@@ -219,22 +230,22 @@ class xor_list
219230
destroySequence(cbegin(), cend(), size());
220231
}
221232

222-
T& back() noexcept
233+
T& back()
223234
{
224235
return *(--end());
225236
}
226237

227-
const T& back() const noexcept
238+
const T& back() const
228239
{
229240
return *(--cend());
230241
}
231242

232-
T& front() noexcept
243+
T& front()
233244
{
234245
return *begin();
235246
}
236247

237-
const T& front() const noexcept
248+
const T& front() const
238249
{
239250
return *cbegin();
240251
}
@@ -270,13 +281,13 @@ class xor_list
270281
return { reinterpret_cast<Node*>(afterTail.xorPtr), &afterTail };
271282
}
272283

273-
void sort() noexcept
284+
void sort()
274285
{
275286
sort(::std::less<T>{});
276287
}
277288

278-
template <class Compare>
279-
void sort(Compare isLess) noexcept
289+
template<typename Compare>
290+
void sort(Compare isLess)
280291
{
281292
using Range = ::std::pair<const_iterator, const_iterator>;
282293
struct NullableRange
@@ -347,13 +358,12 @@ class xor_list
347358
// strong exception-safe guarantee
348359
iterator insert(const_iterator position, const_reference val)
349360
{
350-
//insertNodeToThisBefore noexcept!
351-
return insertNodeToThisBefore(position, createNode(val)).first;
361+
return emplace(position, val);
352362
}
353363

354364
// WARNING! Iterators equal to position will become invalid
355365
// strong exception-safe guarantee
356-
template <class InputIterator>
366+
template<typename InputIterator>
357367
iterator insert(const_iterator position, InputIterator first, InputIterator last)
358368
{
359369
if (first == last)
@@ -381,7 +391,17 @@ class xor_list
381391
return result;
382392
}
383393

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+
384403
// WARNING! All iterators will become invalid
404+
// Complexity: O(1)
385405
void reverse() noexcept
386406
{
387407
if (empty())
@@ -418,6 +438,32 @@ class xor_list
418438
return { first.prev, last.current };
419439
}
420440

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+
421467
void resize(size_type count)
422468
{
423469
resizeImpl(count);
@@ -428,7 +474,7 @@ class xor_list
428474
resizeImpl(count, val);
429475
}
430476

431-
template <typename InputIterator>
477+
template<typename InputIterator>
432478
typename ::std::enable_if<::std::is_base_of<::std::input_iterator_tag,
433479
typename ::std::iterator_traits<InputIterator>::iterator_category>::value>::type
434480
assign(InputIterator first, InputIterator last)
@@ -478,7 +524,7 @@ class xor_list
478524
}
479525

480526

481-
void splice(const_iterator position, xor_list &x) noexcept
527+
void splice(const_iterator position, xor_list &x)
482528
{
483529
if ((this == ::std::addressof(x)) || (x.empty()))
484530
{
@@ -491,7 +537,7 @@ class xor_list
491537
(void)insertSequenceToThisBefore(position, range.first, range.second, distance);
492538
}
493539

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)
495541
{
496542
if ((this == ::std::addressof(x)) && ((position == i) || (position.prev == i.current)))
497543
{
@@ -502,7 +548,7 @@ class xor_list
502548
(void)insertNodeToThisBefore(position, static_cast<NodeWithValue*>(range.first.current));
503549
}
504550

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)
506552
{
507553
if (first == last)
508554
{
@@ -522,7 +568,7 @@ class xor_list
522568
}
523569

524570
// All iterators will become invalid
525-
template <typename BinaryPredicate>
571+
template<typename BinaryPredicate>
526572
void unique(BinaryPredicate isEqual)
527573
{
528574
if (size() < 2)
@@ -545,14 +591,14 @@ class xor_list
545591
}
546592

547593
// All iterators from *this and x will become invalid
548-
void merge(xor_list &x) noexcept
594+
void merge(xor_list &x)
549595
{
550596
merge(x, ::std::less<T>{});
551597
}
552598

553599
// 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)
556602
{
557603
if (!x.empty())
558604
{
@@ -595,14 +641,14 @@ class xor_list
595641

596642
Node(const Node&) noexcept = default;
597643
Node(Node &&) noexcept = default;
598-
644+
599645
virtual ~Node() = default;
600646

601647
Node& operator=(const Node&) noexcept = default;
602648
Node& operator=(Node &&) noexcept = default;
603649
};
604650

605-
struct NodeWithValue : Node
651+
struct NodeWithValue final : Node
606652
{
607653
T value;
608654

@@ -723,7 +769,7 @@ class xor_list
723769
};
724770

725771

726-
struct CutResult
772+
struct CutResult final
727773
{
728774
::std::pair<iterator, iterator> cutted;
729775
iterator end;
@@ -788,10 +834,8 @@ class xor_list
788834
return insertNodeBefore(position, node);
789835
}
790836

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]
795839
static ::std::pair<iterator, iterator>
796840
insertNodeBefore(const_iterator position, NodeWithValue *const node) noexcept
797841
{
@@ -819,11 +863,10 @@ class xor_list
819863
return insertSequenceBefore(position, begin, end);
820864
}
821865

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]
827870
static ::std::pair<iterator, iterator>
828871
insertSequenceBefore(const_iterator position, const_iterator begin,
829872
const_iterator end) noexcept
@@ -852,14 +895,12 @@ class xor_list
852895
return cutSequence(first, last);
853896
}
854897

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
863904
static CutResult
864905
cutSequence(const_iterator begin, const_iterator end) noexcept
865906
{
@@ -1026,10 +1067,8 @@ class xor_list
10261067
return mergeSequences(beginTo, endTo, beginFrom, endFrom, ::std::forward<LessCompare>(isLess));
10271068
}
10281069

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)
10331072
template<typename LessCompare>
10341073
static ::std::pair<iterator, iterator>
10351074
mergeSequences(const_iterator beginTo, const_iterator endTo,
@@ -1080,4 +1119,43 @@ class xor_list
10801119
}
10811120
};
10821121

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+
10831161
#endif //XORLIST_XOR_LIST_H

0 commit comments

Comments
 (0)