SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
small_vector.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <array>
16 #include <type_traits>
17 
18 #if SEQAN3_WITH_CEREAL
19 #include <cereal/types/array.hpp>
20 #endif // SEQAN3_WITH_CEREAL
21 
27 #include <seqan3/std/algorithm>
28 #include <seqan3/std/ranges>
29 
30 namespace seqan3
31 {
32 
46 template <typename value_type_, size_t capacity_>
48 {
49 private:
51  static constexpr bool is_noexcept = std::is_nothrow_copy_constructible_v<value_type_>;
52 
53 public:
57  using value_type = value_type_;
58  using reference = value_type &;
59  using const_reference = const value_type &;
60  using iterator = value_type *;
61  using const_iterator = value_type const *;
62  using difference_type = ptrdiff_t;
64 
66 
68  // this signals to range-v3 that something is a container :|
69  using allocator_type = void;
71 
75  constexpr small_vector() noexcept = default;
76  constexpr small_vector(small_vector const &) noexcept = default;
77  constexpr small_vector(small_vector &&) noexcept = default;
78  constexpr small_vector & operator=(small_vector const &) noexcept = default;
79  constexpr small_vector & operator=(small_vector &&) noexcept = default;
80  ~small_vector() noexcept = default;
81 
93  explicit constexpr small_vector(std::array<value_type, capacity_> const & array) noexcept(is_noexcept) :
94  data_{array}, sz{capacity_}
95  {}
96 
98  template <size_t capacity2>
99  explicit constexpr small_vector(std::array<value_type, capacity2> const & array) noexcept(is_noexcept) :
100  sz{capacity2}
101  {
102  static_assert(capacity2 <= capacity_, "You can only initialize from array that has smaller or equal capacity.");
103  std::ranges::copy(array, data_.begin());
104  }
106 
118  template <size_t capacity2>
119  explicit constexpr small_vector(value_type const (&array)[capacity2]) noexcept(is_noexcept) :
120  sz{capacity2}
121  {
122  static_assert(capacity2 <= capacity_, "You can only initialize from array that has smaller or equal capacity.");
123  std::ranges::copy(array, data_.begin());
124  }
125 
137  template <typename ...other_value_type>
141  constexpr small_vector(other_value_type... args) noexcept(is_noexcept) :
142  data_{args...}, sz{sizeof...(other_value_type)}
143  {
144  static_assert(sizeof...(other_value_type) <= capacity_, "Value list must not exceed the capacity.");
145  }
146 
162  template <std::ForwardIterator begin_it_type, std::Sentinel<begin_it_type> end_it_type>
164  requires std::Constructible<value_type, /*ranges::iter_reference_t*/reference_t<begin_it_type>>
166  constexpr small_vector(begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept) :
167  small_vector{}
168  {
169  assign(begin_it, end_it);
170  }
171 
185  template <std::ranges::InputRange other_range_t>
187  requires !std::is_same_v<remove_cvref_t<other_range_t>, small_vector>
188  /*ICE: && std::Constructible<value_type, reference_t<other_range_t>>*/
190  explicit constexpr small_vector(other_range_t && range) noexcept(is_noexcept) :
192  {}
193 
206  constexpr small_vector(size_type n, value_type value) noexcept(is_noexcept) :
207  small_vector{}
208  {
209  assign(n, value);
210  }
211 
223  constexpr small_vector & operator=(std::initializer_list<value_type> ilist) noexcept(is_noexcept)
224  {
226  return *this;
227  }
228 
240  constexpr void assign(std::initializer_list<value_type> ilist) noexcept(is_noexcept)
241  {
243  }
244 
257  constexpr void assign(size_type const count, value_type const value) noexcept(is_noexcept)
258  {
259  clear();
260  auto tmp = view::repeat_n(value, count);
262  }
263 
277  template <std::ranges::InputRange other_range_t>
279  requires std::Constructible<value_type, /*ranges::range_reference_t*/reference_t<other_range_t>>
281  constexpr void assign(other_range_t && range) noexcept(is_noexcept)
282  {
284  }
285 
301  template <std::ForwardIterator begin_it_type, std::Sentinel<begin_it_type> end_it_type>
302  constexpr void assign(begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept)
304  requires std::Constructible<value_type, /*ranges::iter_reference_t*/reference_t<begin_it_type>>
306  {
307  clear();
308  insert(cbegin(), begin_it, end_it);
309  }
311 
315  constexpr iterator begin() noexcept
317  {
318  return &data_[0];
319  }
320 
322  constexpr const_iterator begin() const noexcept
323  {
324  return &data_[0];
325  }
326 
328  constexpr const_iterator cbegin() const noexcept
329  {
330  return &data_[0];
331  }
332 
334  constexpr iterator end() noexcept
335  {
336  return &data_[sz];
337  }
338 
340  constexpr const_iterator end() const noexcept
341  {
342  return &data_[sz];
343  }
344 
346  constexpr const_iterator cend() const noexcept
347  {
348  return &data_[sz];
349  }
351 
371  {
372  if (i >= size()) // [[unlikely]]
373  {
374  throw std::out_of_range{"Trying to access element behind the last in small_vector."};
375  }
376  return (*this)[i];
377  }
378 
380  const_reference at(size_type const i) const
381  {
382  if (i >= size()) // [[unlikely]]
383  {
384  throw std::out_of_range{"Trying to access element behind the last in small_vector."};
385  }
386  return (*this)[i];
387  }
388 
404  constexpr reference operator[](size_type const i) noexcept
405  {
406  assert(i < size());
407  return data_[i];
408  }
409 
411  constexpr const_reference operator[](size_type const i) const noexcept
412  {
413  assert(i < size());
414  return data_[i];
415  }
416 
430  constexpr reference front() noexcept
431  {
432  assert(size() > 0);
433  return (*this)[0];
434  }
435 
437  constexpr const_reference front() const noexcept
438  {
439  assert(size() > 0);
440  return (*this)[0];
441  }
442 
456  constexpr reference back() noexcept
457  {
458  assert(size() > 0);
459  return (*this)[size()-1];
460  }
461 
463  constexpr const_reference back() const noexcept
464  {
465  assert(size() > 0);
466  return (*this)[size()-1];
467  }
468 
470  constexpr value_type * data() noexcept
471  {
472  return data_.data();
473  }
474 
476  constexpr value_type const * data() const noexcept
477  {
478  return data_.data();
479  }
481 
496  constexpr bool empty() const noexcept
497  {
498  return size() == 0;
499  }
500 
512  constexpr size_type size() const noexcept
513  {
514  return sz;
515  }
516 
531  constexpr size_type max_size() const noexcept
532  {
533  return capacity_;
534  }
535 
547  constexpr size_type capacity() const noexcept
548  {
549  return capacity_;
550  }
551 
553  constexpr void reserve(size_type) const noexcept
554  {
555  // no-op
556  }
557 
559  constexpr void shrink_to_fit() const noexcept
560  {
561  // no-op
562  }
564 
578  constexpr void clear() noexcept
579  {
580  sz = 0;
581  }
582 
598  constexpr iterator insert(const_iterator pos, value_type const value) noexcept(is_noexcept)
599  {
600  return insert(pos, 1, value);
601  }
602 
619  constexpr iterator insert(const_iterator pos, size_type const count, value_type const value) noexcept(is_noexcept)
620  {
621  auto tmp = view::repeat_n(value, count);
622  return insert(pos, std::ranges::begin(tmp), std::ranges::end(tmp));
623  }
624 
645  template <std::ForwardIterator begin_it_type, std::Sentinel<begin_it_type> end_it_type>
647  requires std::Constructible<value_type, /*ranges::iter_reference_t*/reference_t<begin_it_type>>
649  constexpr iterator insert(const_iterator pos, begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept)
650  {
651  auto const pos_as_num = std::ranges::distance(cbegin(), pos);
652  auto const length = std::ranges::distance(begin_it, end_it);
653 
654  if (length == 0)
655  return begin(); // nothing to insert
656 
657  for (size_type i = sz + length - 1; i > pos_as_num + length - 1; --i)
658  data_[i] = data_[i - length];
659 
660  std::ranges::copy(begin_it, end_it, &data_[pos_as_num]);
661  sz += length;
662  return begin() + pos_as_num;
663  }
664 
680  constexpr iterator insert(const_iterator pos, std::initializer_list<value_type> const & ilist) noexcept(is_noexcept)
681  {
682  return insert(pos, ilist.begin(), ilist.end());
683  }
684 
703  constexpr iterator erase(const_iterator begin_it, const_iterator end_it) noexcept
704  {
705  if (begin_it >= end_it) // [[unlikely]]
706  return begin() + std::ranges::distance(cbegin(), end_it);
707 
708  size_type const length = std::ranges::distance(begin_it, end_it);
709  auto out_it = begin() + std::ranges::distance(cbegin(), begin_it);
710 
711  while (end_it != cend())
712  *(out_it++) = *(end_it++);
713 
714  sz -= length;
715  return begin() + std::ranges::distance(cbegin(), begin_it);
716  }
717 
736  constexpr iterator erase(const_iterator pos) noexcept
737  {
738  return erase(pos, pos + 1);
739  }
740 
754  constexpr void push_back(value_type const value) noexcept
755  {
756  assert(sz < capacity_);
757  data_[sz] = value;
758  ++sz;
759  }
760 
775  constexpr void pop_back() noexcept
776  {
777  assert(sz > 0);
778  --sz;
779  }
780 
794  constexpr void resize(size_type const count) noexcept
795  {
796  assert(count <= capacity_);
797  sz = count;
798  }
799 
804  constexpr void resize(size_type const count, value_type const value) noexcept
805  {
806  assert(count <= capacity_);
807  for (size_t i = sz; i < count; ++i)
808  data_[i] = value;
809  sz = count;
810  }
811 
823  constexpr void swap(small_vector & rhs) noexcept(is_noexcept)
824  {
825  auto tmp = *this;
826 
827  data_ = rhs.data_;
828  sz = rhs.sz;
829 
830  rhs.data_ = tmp.data_;
831  rhs.sz = tmp.sz;
832  }
833 
835  constexpr void swap(small_vector && rhs) noexcept(is_noexcept)
836  {
837  data_ = rhs.data_;
838  sz = rhs.sz;
839  }
841 
854  friend constexpr void swap(small_vector & lhs, small_vector & rhs) noexcept(is_noexcept)
855  {
856  lhs.swap(rhs);
857  }
858 
860  friend constexpr void swap(small_vector && lhs, small_vector && rhs) noexcept(is_noexcept)
861  {
862  lhs.swap(rhs);
863  }
864 
867 
869  template <size_t cap2>
871  requires cap2 <= capacity_ /* resolves ambiguousness when comparing two small_vectors of unequal capacity */
873  friend constexpr bool operator==(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
874  {
875  return std::ranges::equal(lhs, rhs);
876  }
877 
879  template <size_t cap2>
881  requires cap2 <= capacity_
883  friend constexpr bool operator!=(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
884  {
885  return !(lhs == rhs);
886  }
887 
889  template <size_t cap2>
891  requires cap2 <= capacity_
893  friend constexpr bool operator<(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
894  {
895  for (size_t i = 0; i < std::min(lhs.size(), rhs.size()); ++i)
896  if (lhs[i] > rhs[i])
897  return false;
898  else if (lhs[i] < rhs[i])
899  return true;
900  return lhs.size() < rhs.size();
901  }
902 
904  template <size_t cap2>
906  requires cap2 <= capacity_
908  friend constexpr bool operator>(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
909  {
910  for (size_t i = 0; i < std::min(lhs.size(), rhs.size()); ++i)
911  if (lhs[i] < rhs[i])
912  return false;
913  else if (lhs[i] > rhs[i])
914  return true;
915  return lhs.size() > rhs.size();
916  }
917 
919  template <size_t cap2>
921  requires cap2 <= capacity_
923  friend constexpr bool operator<=(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
924  {
925  return !(lhs > rhs);
926  }
927 
929  template <size_t cap2>
931  requires cap2 <= capacity_
933  friend constexpr bool operator>=(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
934  {
935  return !(lhs < rhs);
936  }
938 
939 protected:
944 
951  template <CerealArchive archive_t>
952  void CEREAL_SERIALIZE_FUNCTION_NAME(archive_t & archive)
953  {
954  archive(data_);
955  archive(sz);
956  }
957 };
958 
963 template <size_t capacity2, typename value_type>
965 small_vector(const value_type (&array)[capacity2]) -> small_vector<value_type, capacity2>;
967 
968 } // namespace seqan3
::ranges::equal equal
Alias for ranges::equal. Determines if two sets of elements are the same.
Definition: algorithm:54
constexpr reference front() noexcept
Return the first element. Calling front on an empty container is undefined.
Definition: small_vector.hpp:430
value_type const * const_iterator
The const_iterator type.
Definition: small_vector.hpp:61
::ranges::distance distance
Alias for ranges::distance. Returns the number of hops from first to last.
Definition: iterator:321
constexpr reference back() noexcept
Return the last element.
Definition: small_vector.hpp:456
constexpr small_vector(other_range_t &&range) noexcept(is_noexcept)
Construct from a different range.
Definition: small_vector.hpp:190
constexpr const_reference operator[](size_type const i) const noexcept
Return the i-th element.
Definition: small_vector.hpp:411
constexpr void push_back(value_type const value) noexcept
Appends the given element value to the end of the container.
Definition: small_vector.hpp:754
Provides metaprogramming utilities for integer types.
constexpr const_iterator begin() const noexcept
Returns the begin to the string.
Definition: small_vector.hpp:322
constexpr void pop_back() noexcept
Removes the last element of the container.
Definition: small_vector.hpp:775
constexpr const_iterator end() const noexcept
Returns iterator past the end of the vector.
Definition: small_vector.hpp:340
value_type * iterator
The iterator type.
Definition: small_vector.hpp:60
Provides seqan3::type_list and auxiliary type traits.
constexpr void resize(size_type const count, value_type const value) noexcept
Resizes the container to contain count elements.
Definition: small_vector.hpp:804
constexpr size_type capacity() const noexcept
Returns the number of elements that the container is able to hold and resolves to capacity_...
Definition: small_vector.hpp:547
small_vector(const value_type(&array)[capacity2]) -> small_vector< value_type, capacity2 >
Deducts the size and value type from an built-in array on construction.
SeqAn specific customisations in the standard namespace.
friend constexpr bool operator>(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:908
Provides seqan3::view::take.
constexpr small_vector & operator=(std::initializer_list< value_type > ilist) noexcept(is_noexcept)
Assign from std::initializer_list.
Definition: small_vector.hpp:223
constexpr small_vector() noexcept=default
Defaulted.
friend constexpr void swap(small_vector &lhs, small_vector &rhs) noexcept(is_noexcept)
Swap contents with another instance.
Definition: small_vector.hpp:854
The main SeqAn3 namespace.
constexpr void reserve(size_type) const noexcept
Since the capacity is fixed on compile time, this is a no-op.
Definition: small_vector.hpp:553
constexpr void swap(small_vector &rhs) noexcept(is_noexcept)
Swap contents with another instance.
Definition: small_vector.hpp:823
constexpr void assign(other_range_t &&range) noexcept(is_noexcept)
Assign from a different range.
Definition: small_vector.hpp:281
constexpr void resize(size_type const count) noexcept
Resizes the container to contain count elements.
Definition: small_vector.hpp:794
constexpr const_iterator cend() const noexcept
Returns iterator past the end of the vector.
Definition: small_vector.hpp:346
constexpr iterator end() noexcept
Returns iterator past the end of the vector.
Definition: small_vector.hpp:334
constexpr iterator insert(const_iterator pos, begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept)
Inserts elements from range [begin_it, end_it) before position in the container.
Definition: small_vector.hpp:649
constexpr small_vector(value_type const (&array)[capacity2]) noexcept(is_noexcept)
Construct from a (smaller or equally sized) built in array over the same value type.
Definition: small_vector.hpp:119
constexpr void swap(small_vector &&rhs) noexcept(is_noexcept)
Definition: small_vector.hpp:835
const_reference at(size_type const i) const
Return the i-th element.
Definition: small_vector.hpp:380
T min(T... args)
constexpr reference operator[](size_type const i) noexcept
Return the i-th element.
Definition: small_vector.hpp:404
constexpr value_type * data() noexcept
Direct access to the underlying array.
Definition: small_vector.hpp:470
T data(T... args)
constexpr iterator insert(const_iterator pos, std::initializer_list< value_type > const &ilist) noexcept(is_noexcept)
Inserts elements from initializer list before position in the container.
Definition: small_vector.hpp:680
Provides seqan3::view::repeat_n.
constexpr iterator begin() noexcept
Returns the begin to the string.
Definition: small_vector.hpp:316
constexpr const_reference back() const noexcept
Return the last element.
Definition: small_vector.hpp:463
ptrdiff_t difference_type
The difference_type type.
Definition: small_vector.hpp:62
Adaptations of concepts from the Ranges TS.
constexpr void assign(size_type const count, value_type const value) noexcept(is_noexcept)
Assign with count times value.
Definition: small_vector.hpp:257
friend constexpr bool operator!=(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:883
::ranges::begin begin
Alias for ranges::begin. Returns an iterator to the beginning of a range.
Definition: ranges:174
constexpr void shrink_to_fit() const noexcept
Since the capacity is fixed on compile time, this is a no-op.
Definition: small_vector.hpp:559
size_type sz
The size of the actual contained data_.
Definition: small_vector.hpp:943
Adaptions of concepts from the Cereal library.
constexpr small_vector(begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept)
Construct from two iterators.
Definition: small_vector.hpp:166
::ranges::copy copy
Alias for ranges::copy. Copies a range of elements to a new location.
Definition: algorithm:44
friend constexpr bool operator>=(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:933
const value_type & const_reference
The const_reference type.
Definition: small_vector.hpp:59
A constexpr vector implementation with dynamic size at compile time.
Definition: small_vector.hpp:47
constexpr value_type const * data() const noexcept
Direct access to the underlying array.
Definition: small_vector.hpp:476
constexpr void assign(begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept)
Assign from pair of iterators.
Definition: small_vector.hpp:302
constexpr bool empty() const noexcept
Checks whether the container is empty.
Definition: small_vector.hpp:496
The std::Constructible concept specifies that a variable of type T can be initialized with the given ...
constexpr void assign(std::initializer_list< value_type > ilist) noexcept(is_noexcept)
Assign from std::initializer_list.
Definition: small_vector.hpp:240
constexpr small_vector(size_type n, value_type value) noexcept(is_noexcept)
Construct with n times value.
Definition: small_vector.hpp:206
T begin(T... args)
constexpr iterator insert(const_iterator pos, size_type const count, value_type const value) noexcept(is_noexcept)
Inserts count copies of value before position in the container.
Definition: small_vector.hpp:619
constexpr const_reference front() const noexcept
Return the first element. Calling front on an empty container is undefined.
Definition: small_vector.hpp:437
constexpr const_iterator cbegin() const noexcept
Returns the begin to the string.
Definition: small_vector.hpp:328
Adaptations of algorithms from the Ranges TS.
constexpr size_type max_size() const noexcept
Returns the maximum number of elements the container is able to hold and resolves to capacity_...
Definition: small_vector.hpp:531
constexpr iterator erase(const_iterator pos) noexcept
Removes specified elements from the container.
Definition: small_vector.hpp:736
value_type & reference
The reference type.
Definition: small_vector.hpp:58
friend constexpr bool operator==(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:873
reference at(size_type const i)
Return the i-th element.
Definition: small_vector.hpp:370
constexpr auto repeat_n
A view factory that repeats a given value n times.
Definition: repeat_n.hpp:97
typename reference< t >::type reference_t
Shortcut for seqan3::reference (TransformationTrait shortcut).
Definition: pre.hpp:77
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
char value_type
The value_type type.
Definition: small_vector.hpp:57
constexpr iterator insert(const_iterator pos, value_type const value) noexcept(is_noexcept)
Inserts value before position in the container.
Definition: small_vector.hpp:598
constexpr void clear() noexcept
Removes all elements from the container.
Definition: small_vector.hpp:578
::ranges::end end
Alias for ranges::end. Returns an iterator to the end of a range.
Definition: ranges:179
constexpr iterator erase(const_iterator begin_it, const_iterator end_it) noexcept
Removes specified elements from the container.
Definition: small_vector.hpp:703
friend constexpr void swap(small_vector &&lhs, small_vector &&rhs) noexcept(is_noexcept)
Definition: small_vector.hpp:860
std::array< value_type, capacity_ > data_
Stores the actual data_.
Definition: small_vector.hpp:941
constexpr size_type size() const noexcept
Returns the number of elements in the container, i.e. std::distance(begin(), end()).
Definition: small_vector.hpp:512