Molassembler  3.0.0
Molecule graph and conformer library
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Array.h
Go to the documentation of this file.
1 
12 #ifndef INCLUDE_MOLASSEMBLER_TEMPLE_ARRAY_H
13 #define INCLUDE_MOLASSEMBLER_TEMPLE_ARRAY_H
14 
16 
17 #include <cstddef>
18 #include <type_traits>
19 #include <utility>
20 
21 namespace Scine {
22 namespace Molassembler {
23 namespace Temple {
24 
25 template<typename T, std::size_t nItems>
26 class Array {
27 public:
30  using value_type = T;
32 
35 
42  template<std::size_t ... Inds>
43  constexpr Array(
44  const Array& other,
45  std::index_sequence<Inds...> /* inds */
46  ) :items_ {other[Inds]...} {}
47 
56  constexpr Array(const Array& other)
57  : Array(other, std::make_index_sequence<nItems>{}) {}
58 
66  template<std::size_t ... Inds>
67  constexpr Array(
68  Array&& other,
69  std::index_sequence<Inds...> /* inds */
70  ) :items_ {std::move(other[Inds])...} {}
71 
80  constexpr Array(Array&& other) noexcept
81  : Array(std::move(other), std::make_index_sequence<nItems>{}) {}
82 
87  constexpr Array& operator = (const Array& other) {
88  for(std::size_t i = 0; i < nItems; ++i) {
89  items_[i] = other.items_[i];
90  }
91 
92  return *this;
93  }
94 
99  constexpr Array& operator = (Array&& other) noexcept {
100  for(std::size_t i = 0; i < nItems; ++i) {
101  items_[i] = std::move(other.items_[i]);
102  }
103 
104  return *this;
105  }
106 
108  ~Array() = default;
110 
114  template<size_t ... Inds>
115  constexpr Array(
116  const std::array<T, nItems>& other,
117  std::index_sequence<Inds...> /* inds */
118  ) :items_ {other[Inds]...} {}
119 
124  constexpr Array(const std::array<T, nItems>& other)
125  : Array(other, std::make_index_sequence<nItems>{})
126  {}
127 
132  template<typename ...Args>
133  constexpr Array(Args... args)
134  : items_ {static_cast<T>(args)...}
135  {}
137 
140 
147  constexpr T& operator[] (const std::size_t index) noexcept {
148  return items_[index];
149  }
150 
152  constexpr T& at(const std::size_t index) noexcept {
153  return items_[index];
154  }
155 
157  constexpr const T& operator[] (const std::size_t index) const noexcept {
158  return items_[index];
159  }
160 
162  constexpr const T& at(const std::size_t index) const noexcept {
163  return items_[index];
164  }
165 
170  constexpr const T& front() const noexcept {
171  return items_[0];
172  }
173 
178  constexpr const T& back() const noexcept {
179  return items_[nItems - 1];
180  }
182 
183  constexpr size_t size() const noexcept {
184  return nItems;
185  }
186 
191  constexpr bool operator == (const Array& other) const noexcept {
192  for(std::size_t i = 0; i < nItems; ++i) {
193  if(items_[i] != other.items_[i]) {
194  return false;
195  }
196  }
197 
198  return true;
199  }
200 
202  constexpr bool operator != (const Array& other) const noexcept {
203  for(std::size_t i = 0; i < nItems; ++i) {
204  if(items_[i] != other.items_[i]) {
205  return true;
206  }
207  }
208 
209  return false;
210  }
211 
216  constexpr bool operator < (const Array& other) const noexcept {
217  for(std::size_t i = 0; i < nItems; ++i) {
218  if(items_[i] < other.items_[i]) {
219  return true;
220  }
221 
222  if(items_[i] > other.items_[i]) {
223  return false;
224  }
225  }
226 
227  return false;
228  }
229 
231  constexpr bool operator > (const Array& other) const noexcept {
232  return (other < *this);
233  }
234 
238  class iterator {
239  public:
240  using iterator_category = std::random_access_iterator_tag;
241  using value_type = T;
242  using difference_type = int;
243  using pointer = const T*;
244  using reference = T&;
245 
246  constexpr iterator(
247  Array& instance,
248  std::size_t initPosition
249  ) noexcept
250  : baseRef_(instance),
251  position_(initPosition)
252  {}
253 
254  constexpr iterator() = delete;
255  constexpr iterator(const iterator& other) noexcept
256  : baseRef_(other.baseRef_),
257  position_(other.position_)
258  {}
259  constexpr iterator(iterator&& other) noexcept = default;
260  constexpr iterator& operator = (const iterator& other) noexcept {
261  baseRef_ = other.baseRef_;
262  position_ = other.position_;
263 
264  return *this;
265  }
266  constexpr iterator& operator = (iterator&& other) noexcept = default;
267  ~iterator() = default;
268 
269  constexpr iterator& operator ++ () noexcept {
270  position_ += 1;
271  return *this;
272  }
273 
274  constexpr iterator operator ++ (int) noexcept {
275  iterator retval = *this;
276  ++(*this);
277  return retval;
278  }
279 
280  constexpr iterator& operator --() noexcept {
281  position_ -= 1;
282  return *this;
283  }
284 
285  constexpr iterator operator -- (int) noexcept {
286  iterator retval = *this;
287  --(*this);
288  return retval;
289  }
290 
291  constexpr iterator operator + (const int increment) noexcept {
292  iterator retval = *this;
293  retval += increment;
294  return retval;
295  }
296 
297  constexpr iterator operator - (const int increment) noexcept {
298  iterator retval = *this;
299  retval -= increment;
300  return retval;
301  }
302 
303  constexpr iterator& operator += (const int increment) noexcept {
304  position_ += increment;
305  return *this;
306  }
307 
308  constexpr iterator& operator -= (const int increment) noexcept {
309  position_ -= increment;
310  return *this;
311  }
312 
313  PURITY_WEAK constexpr int operator - (const iterator& other) const noexcept {
314  return (
315  static_cast<int>(position_)
316  - static_cast<int>(other.position_)
317  );
318  }
319 
320  PURITY_WEAK constexpr bool operator == (const iterator& other) const noexcept {
321  return (
322  &baseRef_ == &other.baseRef_
323  && position_ == other.position_
324  );
325  }
326 
327  PURITY_WEAK constexpr bool operator != (const iterator& other) const noexcept {
328  return !(
329  *this == other
330  );
331  }
332 
333  PURITY_WEAK constexpr reference operator * () const noexcept {
334  return baseRef_[position_];
335  }
336 
337  PURITY_WEAK constexpr bool operator < (const iterator& other) const noexcept {
338  return position_ < other.position_;
339  }
340 
341  PURITY_WEAK constexpr bool operator <= (const iterator& other) const noexcept {
342  return position_ <= other.position_;
343  }
344 
345  PURITY_WEAK constexpr bool operator > (const iterator& other) const noexcept {
346  return position_ > other.position_;
347  }
348 
349  PURITY_WEAK constexpr bool operator >= (const iterator& other) const noexcept {
350  return position_ >= other.position_;
351  }
352 
353  private:
354  Array& baseRef_;
355  std::size_t position_;
356  };
357 
358  PURITY_WEAK constexpr iterator begin() noexcept {
359  return iterator(*this, 0);
360  }
361 
362  PURITY_WEAK constexpr iterator end() noexcept {
363  return iterator(*this, nItems);
364  }
365 
370  public:
371  using iterator_category = std::random_access_iterator_tag;
372  using value_type = T;
373  using difference_type = int;
374  using pointer = const T*;
375  using reference = const T&;
376 
377  constexpr explicit const_iterator(
378  const Array& instance,
379  std::size_t initPosition
380  ) noexcept
381  : baseRef_(instance),
382  position_(initPosition)
383  {}
384 
385  constexpr const_iterator() = delete;
386  constexpr const_iterator(const const_iterator& other) noexcept
387  : baseRef_(other.baseRef_),
388  position_(other.position_)
389  {}
390  constexpr const_iterator(const_iterator&& other) noexcept = default;
391  constexpr const_iterator& operator = (const const_iterator& other) {
392  if(baseRef_ != other.baseRef_) {
393  throw "Trying to assign constIterator to other base Array!";
394  }
395 
396  position_ = other.position_;
397 
398  return *this;
399  }
400  constexpr const_iterator& operator = (const_iterator&& other) noexcept = default;
401  ~const_iterator() = default;
402 
403  constexpr const_iterator& operator ++ () noexcept {
404  position_ += 1;
405  return *this;
406  }
407 
408  constexpr const_iterator operator ++ (int) noexcept {
409  const_iterator retval = *this;
410  ++(*this);
411  return retval;
412  }
413 
414  constexpr const_iterator& operator --() noexcept {
415  position_ -= 1;
416  return *this;
417  }
418 
419  constexpr const_iterator operator -- (int) noexcept {
420  const_iterator retval = *this;
421  --(*this);
422  return retval;
423  }
424 
425  constexpr const_iterator operator + (const int increment) noexcept {
426  const_iterator retval = *this;
427  retval += increment;
428  return retval;
429  }
430 
431  constexpr const_iterator operator - (const int increment) noexcept {
432  const_iterator retval = *this;
433  retval -= increment;
434  return retval;
435  }
436 
437  constexpr const_iterator& operator += (const int increment) noexcept {
438  position_ += increment;
439  return *this;
440  }
441 
442  constexpr const_iterator& operator -= (const int increment) noexcept {
443  position_ -= increment;
444  return *this;
445  }
446 
447  constexpr int operator - (const const_iterator& other) const noexcept {
448  return (
449  static_cast<int>(position_)
450  - static_cast<int>(other.position_)
451  );
452  }
453 
454  constexpr bool operator == (const const_iterator& other) const noexcept {
455  return (
456  &baseRef_ == &other.baseRef_
457  && position_ == other.position_
458  );
459  }
460 
461  constexpr bool operator != (const const_iterator& other) const noexcept {
462  return !(
463  *this == other
464  );
465  }
466 
467  constexpr reference operator * () const noexcept {
468  return baseRef_[position_];
469  }
470 
471  private:
472  const Array& baseRef_;
473  std::size_t position_;
474  };
475 
476  constexpr const_iterator begin() const noexcept {
477  return const_iterator(*this, 0);
478  }
479 
480  constexpr const_iterator end() const noexcept {
481  return const_iterator(*this, nItems);
482  }
483 
485  constexpr operator std::array<T, nItems> () const {
486  return makeArray_(std::make_index_sequence<nItems>{});
487  }
488 
490  constexpr std::array<T, nItems> getArray() const {
491  return makeArray_(std::make_index_sequence<nItems>{});
492  }
493 
494 private:
495  T items_[nItems];
496 
497  template<size_t ... Inds>
498  constexpr std::array<T, nItems> makeArray_(std::index_sequence<Inds...> /* inds */) const {
499  return {{items_[Inds]...}};
500  }
501 };
502 
503 template<typename T, typename... Tail>
504 constexpr auto makeArray(T head, Tail... tail) -> Array<T, 1 + sizeof...(Tail)> {
505  // This way, makeArray must be called with at least one argument
506  return { head, tail ... };
507 }
508 
509 } // namespace Temple
510 } // namespace Molassembler
511 } // namespace Scine
512 
513 #endif
auto at(Container &&container)
Make functor calling at on arguments.
Definition: Functor.h:58
#define PURITY_WEAK
Definition: Preprocessor.h:36
constexpr Array(const std::array< T, nItems > &other, std::index_sequence< Inds...>)
Delegate std::array ctor, using same trick as copy ctor.
Definition: Array.h:115
unsigned size(Shape shape)
Fetch the number of vertices of a shape.
constexpr Array(const std::array< T, nItems > &other)
Construct from std::array using same trick as copy ctor.
Definition: Array.h:124
constexpr Array(const Array &other)
Copy constructor.
Definition: Array.h:56
Nonmodifiable data iterator.
Definition: Array.h:369
constexpr Array(const Array &other, std::index_sequence< Inds...>)
Helper copy constructor.
Definition: Array.h:43
Functional-style constexpr container algorithms.
constexpr std::array< T, nItems > getArray() const
Explicit conversion to a std::array.
Definition: Array.h:490