SPH
List.h
Go to the documentation of this file.
1 #pragma once
2 
7 
8 #include "common/Traits.h"
11 
13 
14 template <typename T, typename TAllocator = Mallocator>
15 class List;
16 
17 template <typename T>
18 struct ListNode {
20 
23 
26 
29 
30  template <typename U>
32  : value(std::forward<U>(value))
33  , next(next)
34  , prev(prev) {
35  // update pointers of neighbouring nodes
36  if (prev) {
37  prev->next = this;
38  }
39  if (next) {
40  next->prev = this;
41  }
42  }
43 
46  void detach() {
47  if (prev) {
48  prev->next = next;
49  }
50  if (next) {
51  next->prev = prev;
52  }
53  }
54 };
55 
56 template <typename T>
57 class ListIterator {
58  template <typename, typename>
59  friend class List;
60 
61 private:
62  RawPtr<ListNode<T>> node;
63 
64 public:
65  using iterator_category = std::bidirectional_iterator_tag;
66  using value_type = T;
67  using difference_type = std::ptrdiff_t;
68  using pointer = T*;
69  using reference = T&;
70 
72  : node(node) {}
73 
75  if (node) {
76  node = node->next;
77  }
78  return *this;
79  }
80 
82  ListIterator next = *this;
83  ++next;
84  return next;
85  }
86 
88  if (node) {
89  node = node->prev;
90  }
91  return *this;
92  }
93 
95  ListIterator prev = *this;
96  --prev;
97  return prev;
98  }
99 
100  INLINE T& operator*() const {
101  SPH_ASSERT(node);
102  return node->value;
103  }
104 
106  SPH_ASSERT(node);
107  return &node->value;
108  }
109 
110  INLINE explicit operator bool() const {
111  return bool(node);
112  }
113 
114  INLINE bool operator!() const {
115  return !node;
116  }
117 
118  bool operator==(const ListIterator& other) const {
119  return node == other.node;
120  }
121 
122  bool operator!=(const ListIterator& other) const {
123  return node != other.node;
124  }
125 };
126 
130 template <typename T, typename TAllocator>
131 class List : private TAllocator, public Noncopyable {
132 private:
133  using StorageType = typename WrapReferenceType<T>::Type;
134 
135  RawPtr<ListNode<T>> first;
136  RawPtr<ListNode<T>> last;
137 
138 public:
141  : first(nullptr)
142  , last(nullptr) {}
143 
145  List(std::initializer_list<StorageType> list) {
146  for (const StorageType& value : list) {
147  this->pushBack(value);
148  }
149  }
150 
152  List(List&& other)
153  : first(other.first)
154  , last(other.last) {
155  other.first = other.last = nullptr;
156  }
157 
158  ~List() {
159  this->clear();
160  }
161 
163  List& operator=(List&& other) {
164  std::swap(first, other.first);
165  std::swap(last, other.last);
166  return *this;
167  }
168 
170  INLINE bool empty() const {
171  return first == nullptr;
172  }
173 
177  INLINE Size size() const {
178  Size counter = 0;
179  for (RawPtr<ListNode<T>> ptr = first; ptr != nullptr; ptr = ptr->next) {
180  ++counter;
181  }
182  return counter;
183  }
184 
188  template <typename U>
189  void pushBack(U&& value) {
190  RawPtr<ListNode<T>> node = newNode(std::forward<U>(value), last, nullptr);
191  last = node;
192  if (first == nullptr) {
193  // this is the first element, update also first ptr.
194  first = node;
195  }
196  }
197 
201  template <typename U>
202  void pushFront(U&& value) {
203  RawPtr<ListNode<T>> node = newNode(std::forward<U>(value), nullptr, first);
204  first = node;
205  if (last == nullptr) {
206  // this is the first element, update also last ptr.
207  last = node;
208  }
209  }
210 
213  template <typename U>
214  void insert(const ListIterator<T> iter, U&& value) {
215  SPH_ASSERT(iter);
216  RawPtr<ListNode<T>> node = newNode(std::forward<U>(value), iter.node, iter.node->next);
217  if (iter.node == last) {
218  // we added to the back of the list, update the pointer
219  last = node;
220  }
221  }
222 
230  SPH_ASSERT(iter);
231  ListIterator<T> next = iter;
232  ++next;
233  RawPtr<ListNode<T>> node = iter.node;
234  node->detach();
235  if (node == first) {
236  // erasing first element, adjust pointer
237  first = first->next;
238  }
239  if (node == last) {
240  // erasing last element, adjust pointer
241  last = last->prev;
242  }
243  if (node) {
244  deleteNode(node.get());
245  }
246  return next;
247  }
248 
250  void clear() {
251  for (RawPtr<ListNode<T>> ptr = first; ptr != nullptr;) {
252  RawPtr<ListNode<T>> next = ptr->next;
253  if (ptr) {
254  deleteNode(ptr.get());
255  }
256  ptr = next;
257  }
258  first = last = nullptr;
259  }
260 
262  INLINE T& front() {
263  SPH_ASSERT(!this->empty());
264  return first->value;
265  }
266 
268  INLINE const T& front() const {
269  SPH_ASSERT(!this->empty());
270  return first->value;
271  }
272 
274  INLINE T& back() {
275  SPH_ASSERT(!this->empty());
276  return last->value;
277  }
278 
280  INLINE const T& back() const {
281  SPH_ASSERT(!this->empty());
282  return last->value;
283  }
284 
286  List clone() const {
287  List copy;
288  for (auto& value : *this) {
289  copy.pushBack(value);
290  }
291  return copy;
292  }
293 
296  return ListIterator<T>(first);
297  }
298 
301  // same types, only differ by const-ness
303  return ListIterator<const T>(reinterpret_cast<ListNode<const T>*>(first.get()));
304  }
305 
308  return ListIterator<T>(nullptr);
309  }
310 
313  return ListIterator<const T>(nullptr);
314  }
315 
317  const TAllocator& allocator() const {
318  return *this;
319  }
320 
322  TAllocator& allocator() {
323  return *this;
324  }
325 
327  template <typename TStream>
328  friend TStream& operator<<(TStream& stream, const List& array) {
329  for (const T& t : array) {
330  stream << t << std::endl;
331  }
332  return stream;
333  }
334 
335 private:
336  template <typename... TArgs>
337  RawPtr<ListNode<T>> newNode(TArgs&&... args) {
338  MemoryBlock block = TAllocator::allocate(sizeof(ListNode<T>), alignof(ListNode<T>));
339  SPH_ASSERT(block.ptr);
340  return new (block.ptr) ListNode<T>(std::forward<TArgs>(args)...);
341  }
342 
343  void deleteNode(ListNode<T>* node) {
344  node->~ListNode<T>();
345  MemoryBlock block(node, sizeof(ListNode<T>));
346  TAllocator::deallocate(block);
347  }
348 };
349 
Allocators used by containers.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
Simple non-owning wrapper of pointer.
Few non-standard type traits.
INLINE T & operator*() const
Definition: List.h:100
INLINE ListIterator operator++(int)
Definition: List.h:81
std::ptrdiff_t difference_type
Definition: List.h:67
bool operator==(const ListIterator &other) const
Definition: List.h:118
T value_type
Definition: List.h:66
T & reference
Definition: List.h:69
INLINE RawPtr< T > operator->() const
Definition: List.h:105
T * pointer
Definition: List.h:68
INLINE bool operator!() const
Definition: List.h:114
INLINE ListIterator & operator++()
Definition: List.h:74
INLINE ListIterator & operator--()
Definition: List.h:87
std::bidirectional_iterator_tag iterator_category
Definition: List.h:65
bool operator!=(const ListIterator &other) const
Definition: List.h:122
ListIterator(RawPtr< ListNode< T >> node)
Definition: List.h:71
INLINE ListIterator operator--(int)
Definition: List.h:94
Doubly-linked list.
Definition: List.h:131
INLINE const T & back() const
Returns the reference to the last element in the list.
Definition: List.h:280
List(std::initializer_list< StorageType > list)
Constructs the list given initializer_list of elements.
Definition: List.h:145
~List()
Definition: List.h:158
INLINE Size size() const
Returns the number of elements in the list.
Definition: List.h:177
void insert(const ListIterator< T > iter, U &&value)
Definition: List.h:214
List & operator=(List &&other)
Move operator.
Definition: List.h:163
ListIterator< const T > end() const
Returns a bidirectional iterator pointing to the one-past-last element of the list.
Definition: List.h:312
List(List &&other)
Move constructor.
Definition: List.h:152
ListIterator< T > end()
Returns a bidirectional iterator pointing to the one-past-last element of the list.
Definition: List.h:307
TAllocator & allocator()
Returns the interface to the allocator.
Definition: List.h:322
INLINE bool empty() const
Returns true if there are no elements in the list.
Definition: List.h:170
List clone() const
Creates a copy of the list.
Definition: List.h:286
INLINE T & front()
Returns the reference to the first element in the list.
Definition: List.h:262
ListIterator< const T > begin() const
Returns a bidirectional iterator pointing to the first element of the list.
Definition: List.h:300
friend TStream & operator<<(TStream &stream, const List &array)
Prints content of the list to stream. Stored values must have overloaded << operator.
Definition: List.h:328
void pushFront(U &&value)
Adds a new element to the beginning of the list.
Definition: List.h:202
void clear()
Removes all elements from the list.
Definition: List.h:250
const TAllocator & allocator() const
Returns the interface to the allocator.
Definition: List.h:317
INLINE T & back()
Returns the reference to the last element in the list.
Definition: List.h:274
INLINE const T & front() const
Returns the reference to the first element in the list.
Definition: List.h:268
List()
Constructs the list with no elements.
Definition: List.h:140
void pushBack(U &&value)
Adds a new element to the back of the list.
Definition: List.h:189
ListIterator< T > erase(const ListIterator< T > iter)
Removes an element given by the iterator.
Definition: List.h:229
ListIterator< T > begin()
Returns a bidirectional iterator pointing to the first element of the list.
Definition: List.h:295
INLINE T * get() const
Definition: RawPtr.h:67
Overload of std::swap for Sph::Array.
Definition: Array.h:578
void swap(Sph::Array< T, TCounter > &ar1, Sph::Array< T, TCounter > &ar2)
Definition: Array.h:580
Definition: List.h:18
RawPtr< ListNode > next
Next element in the list, can be nullptr.
Definition: List.h:25
StorageType value
Stored value.
Definition: List.h:22
RawPtr< ListNode > prev
Previous element in the list, can be nullptr.
Definition: List.h:28
ListNode(U &&value, RawPtr< ListNode > prev, RawPtr< ListNode > next)
Definition: List.h:31
typename WrapReferenceType< T >::Type StorageType
Definition: List.h:19
void detach()
Definition: List.h:46
void * ptr
Definition: Allocators.h:15
Object with deleted copy constructor and copy operator.
Definition: Object.h:54