-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlinkedlistiterator.h
143 lines (123 loc) · 4.73 KB
/
linkedlistiterator.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#ifndef LINKEDLISTITERATOR_H
#define LINKEDLISTITERATOR_H
// LinkListIterator
//
// A C++ iterator for C linked lists
#include <cassert>
#include <iterator>
#include <type_traits>
namespace lli
{
///////////////////////////////////////////////////////////////////////////////
// The iterator type is templated on a functor for advancing to the next
// available node. Here are implementations of the two most common cases.
//
// Callers should provide additional implementations for list with different
// interfaces.
template <typename NODE>
struct default_next {
auto operator()(NODE* ptr) -> NODE* { return ptr->next; }
};
template <typename NODE>
struct default_prev {
auto operator()(NODE* ptr) -> NODE* { return ptr->prev; }
};
///////////////////////////////////////////////////////////////////////////////
// The iterator
template <typename NODE, class NEXT = default_next<NODE>>
class LinkedListIterator {
public:
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = typename std::remove_const<NODE>::type;
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
using next_type = NEXT;
LinkedListIterator(pointer ptr = nullptr) : _ptr(ptr) {}
LinkedListIterator(const LinkedListIterator &) = default;
LinkedListIterator(LinkedListIterator &&) = default;
LinkedListIterator& operator=(const LinkedListIterator&) = default;
LinkedListIterator& operator=(LinkedListIterator&&) = default;
const_reference operator*() const { return *_ptr; }
reference operator*() { return *_ptr; }
const_pointer operator->() const { return _ptr; }
pointer operator->() { return _ptr; }
bool operator!=(const LinkedListIterator &other) const;
bool operator==(const LinkedListIterator &other) const;
LinkedListIterator operator++();
LinkedListIterator operator++(int);
private:
pointer _ptr = nullptr;
};
// TODO: implement one in terms of the other.
template <typename NODE, class NEXT>
bool LinkedListIterator<NODE, NEXT>::operator!=(const LinkedListIterator &other) const
{
return (this->_ptr != other._ptr);
}
template <typename NODE, class NEXT>
bool LinkedListIterator<NODE, NEXT>::operator==(const LinkedListIterator &other) const
{
return (this->_ptr == other._ptr);
}
template <typename NODE, class NEXT>
auto LinkedListIterator<NODE, NEXT>::operator++() -> LinkedListIterator
{
assert(_ptr != NULL);
NEXT next;
_ptr = next(_ptr);
return _ptr;
}
template <typename NODE, class NEXT>
auto LinkedListIterator<NODE, NEXT>::operator++(int) -> LinkedListIterator {
assert(_ptr != NULL);
NODE *current = _ptr;
NEXT next;
_ptr = next(_ptr);
return current;
}
///////////////////////////////////////////////////////////////////////////////
// C liked lists aren't classes and won't have [c][r]begin() and [c][r]end()
// members, but we can define ::being(NODE*) and ::end(NODE*) for our types to
// allow algorithms to work.
//
// As with the advance functor we provide default implmentations for the naive
// cases. Specializations should be provided for more elaborate lists.
//
// The "r" reverse variants use default_prev<>.
template <typename NODE, class NEXT = default_next<NODE>, typename LIST=NODE*>
LinkedListIterator<NODE, NEXT> begin(LIST& list) {
return LinkedListIterator<NODE, NEXT>(list);
}
template <typename NODE, class NEXT = default_next<NODE>, typename LIST=NODE*>
LinkedListIterator<const NODE, NEXT> cbegin(const LIST& list) {
return LinkedListIterator<NODE, NEXT>(list);
}
template <typename NODE, class NEXT = default_prev<NODE>, typename LIST=NODE*>
LinkedListIterator<NODE, NEXT> rbegin(LIST& list) {
return LinkedListIterator<NODE, NEXT>(list);
}
template <typename NODE, class NEXT = default_prev<NODE>, typename LIST=NODE*>
LinkedListIterator<const NODE, NEXT> crbegin(const LIST& list) {
return LinkedListIterator<NODE, NEXT>(list);
}
template <typename NODE, class NEXT = default_next<NODE>, typename LIST=NODE*>
LinkedListIterator<NODE, NEXT> end(LIST& list) {
return LinkedListIterator<NODE, NEXT>(nullptr);
}
template <typename NODE, class NEXT = default_next<NODE>, typename LIST=NODE*>
LinkedListIterator<const NODE, NEXT> cend(const LIST& list) {
return LinkedListIterator<NODE, NEXT>(nullptr);
}
template <typename NODE, class NEXT = default_prev<NODE>, typename LIST=NODE*>
LinkedListIterator<NODE, NEXT> rend(LIST& list) {
return LinkedListIterator<NODE, NEXT>(nullptr);
}
template <typename NODE, class NEXT = default_prev<NODE>, typename LIST=NODE*>
LinkedListIterator<const NODE, NEXT> crend(const LIST& list) {
return LinkedListIterator<NODE, NEXT>(nullptr);
}
}
#endif//LINKEDLISTITERATOR_H