AnySet Documentation
AnyList.h
1 #ifndef ANY_LIST_H
2 #define ANY_LIST_H
3 
4 #ifdef _MSC_VER
5 # include <iso646.h>
6 #endif
7 
8 #include "AnyNode.h"
9 #include <iterator>
10 #include <memory>
11 #include <algorithm>
12 #include <iosfwd>
13 
15 namespace te::detail {
16 
17 template <class Hash, class Compare>
18 struct AnyList
19 {
21  using reference = value_type&;
22  using const_reference = const value_type&;
23  using pointer = value_type*;
24  using const_pointer = const value_type*;
25  using size_type = std::size_t;
27 private:
29 
30 
31  template <bool IsConst>
32  struct Iterator {
33  using value_type = typename self_type::value_type;
34  using reference = std::conditional_t<
35  IsConst,
37  typename self_type::reference
38  >;
40  using pointer = std::conditional_t<
41  IsConst,
42  typename self_type::const_pointer,
43  typename self_type::pointer
44  >;
45  using iterator_category = std::forward_iterator_tag;
46 
47  Iterator() = default;
48 
49  Iterator(const Iterator<false>& other):
50  pos_(other.pos_)
51  {
52 
53  }
54 
55  reference operator*() const
56  {
57  assert(pos_);
58  assert(*pos_);
59  return **pos_;
60  }
61 
62  pointer operator->() const
63  {
64  assert(pos_);
65  assert(*pos_);
66  return *pos_;
67  }
68 
69  friend bool operator==(Iterator<IsConst> left, Iterator<IsConst> right)
70  {
71  return left.pos_ == right.pos_;
72  }
73 
74  friend bool operator!=(Iterator<IsConst> left, Iterator<IsConst> right)
75  { return not (left == right); }
76 
77  Iterator& operator++()
78  {
79  assert(pos_);
80  assert(*pos_);
81  pos_ = std::addressof((*pos_)->next);
82  return *this;
83  }
84 
85  Iterator operator++(int)
86  {
87  assert(pos_);
88  assert(*pos_);
89  auto cpy = *this;
90  ++(*this);
91  return cpy;
92  }
93 
94  bool is_end() const
95  {
96  assert(pos_);
97  return not static_cast<bool>(*pos_);
98  }
99 
100 
101  bool is_null() const
102  {
103  return not static_cast<bool>(pos_);
104  }
105 
106  private:
107  using pos_type = std::conditional_t<IsConst, value_type* const*, value_type**>;
108 
109  Iterator(pos_type p):
110  pos_(p)
111  {
112 
113  }
114 
115  Iterator<false> to_non_const() const
116  {
117  return Iterator<false>(&const_cast<value_type*&>(*pos_));
118  }
119 
120  pos_type pos_ = nullptr;
121 
122  friend struct AnyList<Hash, Compare>;
123  template <class, class, class>
124  friend struct ::te::AnySet;
125  };
126 
127 public:
128  using iterator = Iterator<false>;
129  using const_iterator = Iterator<true>;
130 
131  void _assert_invariants() const
132  {
133  assert(not static_cast<bool>(*tail_));
134  if(empty())
135  {
136  assert(size() == 0u);
137  assert(tail_ == std::addressof(head_));
138  assert(not static_cast<bool>(head_));
139  }
140  else
141  {
142  assert(size() != 0u);
143  assert(tail_ != std::addressof(head_));
144  assert(static_cast<bool>(head_));
145  }
146  assert(static_cast<size_type>(std::distance(begin(), end())) == size());
147  }
148 
149  AnyList() noexcept = default;
150 
151  AnyList(const self_type&) = delete;
152 
153  AnyList(self_type&& other) noexcept:
154  head_(other.head_), tail_(other.tail_), count_(other.count_)
155  {
156  other.head_ = nullptr;
157  other.tail_ = &(other.head_);
158  other.count_ = 0u;
159  if(size() == 0)
160  {
161  assert(tail_ == std::addressof(other.head_));
162  tail_ = std::addressof(head_);
163  }
164  }
165 
166  AnyList& operator=(const self_type&) = delete;
167 
168  struct MakeCopyTag{};
169 
170  // Make copying possible, but not conventionally
171  AnyList(const self_type& other, MakeCopyTag)
172  {
173  auto it = begin();
174  for(const auto& any_v: other)
175  {
176  splice(it, any_v.clone());
177  ++it;
178  }
179  }
180 
181  ~AnyList()
182  {
183  clear();
184  }
185 
186  self_type& operator=(self_type&& other) noexcept
187  {
188  clear();
189  head_ = other.head_;
190  count_ = other.count_;
191  tail_ = (other.tail_ == &(other.head_)) ? &head_ : other.tail_;
192  other.head_ = nullptr;
193  other.tail_ = &(other.head_);
194  other.count_ = 0u;
195  return *this;
196  }
197 
198  iterator begin()
199  { return iterator(&head_); }
200  const_iterator begin() const
201  { return const_iterator(&head_); }
202  const_iterator cbegin() const
203  { return const_iterator(&head_); }
204 
205  iterator end()
206  {
207  assert(static_cast<bool>(tail_));
208  assert(not static_cast<bool>(*tail_));
209  return iterator(tail_);
210  }
211  const_iterator end() const
212  {
213  assert(static_cast<bool>(tail_));
214  assert(not static_cast<bool>(*tail_));
215  return const_iterator(tail_);
216  }
217 
218  const_iterator cend() const
219  {
220  assert(static_cast<bool>(tail_));
221  assert(not static_cast<bool>(*tail_));
222  return const_iterator(tail_);
223  }
224 
225 
226  void swap(self_type& other) noexcept
227  {
228  std::swap(head_, other.head_);
229  std::swap(tail_, other.tail_);
230  std::swap(count_, other.count_);
231  if(tail_ == std::addressof(other.head_))
232  {
233  assert(size() == 0);
234  tail_ = std::addressof(head_);
235  }
236  if(other.tail_ == std::addressof(head_))
237  {
238  assert(other.size() == 0);
239  other.tail_ = std::addressof(other.head_);
240  }
241  }
242 
243  std::size_t clear() noexcept
244  {
245  auto cnt = count_;
246  erase(begin(), end());
247  assert(not static_cast<bool>(head_));
248  assert(std::addressof(head_) == tail_);
249  assert(empty());
250  return cnt;
251  }
252 
253  iterator push_back(std::unique_ptr<value_type>&& node)
254  {
255  assert(not static_cast<bool>(*tail_));
256  assert(static_cast<bool>(node));
257  assert(not static_cast<bool>(node->next));
258  *tail_ = node.release();
259  iterator old_tail(tail_);
260  ++count_;
261  tail_ = std::addressof((*tail_)->next);
262  assert(not static_cast<bool>(*tail_));
263  return old_tail;
264  }
265 
266  std::pair<std::unique_ptr<value_type>, iterator> pop(const_iterator p)
267  {
268  assert(not static_cast<bool>(*tail_));
269  assert(not empty());
270  std::unique_ptr<value_type> node(*p.pos_);
271  value_type*& pos = *p.to_non_const().pos_;
272  if(not static_cast<bool>(pos->next))
273  tail_ = &pos;
274  pos = pos->next;
275  node->next = nullptr;
276  --count_;
277  assert(not static_cast<bool>(*tail_));
278  return std::make_pair(std::move(node), iterator(&pos));
279  }
280 
281  iterator splice(const_iterator p, std::unique_ptr<value_type>&& node) noexcept
282  {
283  assert(not static_cast<bool>(*tail_));
284  value_type*& pos = *p.to_non_const().pos_;
285  if(not static_cast<bool>(pos))
286  tail_ = std::addressof(node->next);
287  node->next = pos;
288  pos = node.release();
289  ++count_;
290  assert(not static_cast<bool>(*tail_));
291  return p.to_non_const();
292  }
293 
294  iterator erase(const_iterator p)
295  {
296  assert(not empty());
297  pop(p);
298  return p.to_non_const();
299  }
300 
301  std::pair<iterator, std::size_t> erase(const_iterator first, const_iterator last)
302  {
303  if(first == last)
304  return std::make_pair(first.to_non_const(), 0);
305  std::size_t init_size = size();
306  auto* last_pos = *last.pos_;
307  while(*first.pos_ != last_pos)
308  first = erase(first);
309  return std::make_pair(first.to_non_const(), init_size - size());
310  }
311 
312  size_type size() const noexcept
313  { return count_; }
314 
315  bool empty() const noexcept
316  {
317  assert(static_cast<bool>(size()) == static_cast<bool>(head_));
318  assert((tail_ == &head_) ? size() == 0u : size() > 0u);
319  return not static_cast<bool>(size());
320  }
321 
322  friend void swap(self_type& left, self_type& right)
323  { left.swap(right); }
324 
325  static constexpr const MakeCopyTag make_copy = MakeCopyTag{};
326 private:
327 
328  // Can't use unique_ptr because iterators need to be able to
329  // store a pointer-to-pointer.
330  value_type* head_{nullptr};
331  value_type** tail_{&head_};
332  size_type count_{0u};
333 };
334 
335 template <class Hash, class Compare>
336 bool operator==(const AnyList<Hash, Compare>& left, const AnyList<Hash, Compare>& right)
337 {
338  auto lpos = left.begin();
339  auto rpos = right.begin();
340  while((not lpos.is_end()) and (not rpos.is_end()))
341  {
342  if(not (*lpos++ == *rpos++))
343  return false;
344  }
345  assert(lpos.is_end() or rpos.is_end());
346  return lpos.is_end() and rpos.is_end();
347 }
348 
349 template <class Hash, class Compare>
350 bool operator!=(const AnyList<Hash, Compare>& left, const AnyList<Hash, Compare>& right)
351 { return not (left == right); }
352 
353 } /* namespace te::detail */
354 
356 
357 #endif /* ANY_LIST_H */
T distance(T... args)
T swap(T... args)
Definition: AnyList.h:168
T make_pair(T... args)
T addressof(T... args)
Definition: AnyList.h:18
T move(T... args)
Definition: AnyNode.h:93
Definition: SetOperations.h:23