SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
small_vector.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2021, 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
26
27namespace seqan3
28{
29
45template <typename value_type_, size_t capacity_>
47{
48private:
50 static constexpr bool is_noexcept = std::is_nothrow_copy_constructible_v<value_type_>;
51
52public:
60 using value_type = value_type_;
61
67
72 using const_reference = const value_type &;
73
79
84 using const_iterator = value_type const *;
85
90 using difference_type = ptrdiff_t;
91
97
99
101 // this signals to range-v3 that something is a container :|
102 using allocator_type = void;
104
108 constexpr small_vector() noexcept = default;
109 constexpr small_vector(small_vector const &) noexcept = default;
110 constexpr small_vector(small_vector &&) noexcept = default;
111 constexpr small_vector & operator=(small_vector const &) noexcept = default;
112 constexpr small_vector & operator=(small_vector &&) noexcept = default;
113 ~small_vector() noexcept = default;
114
128 explicit constexpr small_vector(std::array<value_type, capacity_> const & array) noexcept(is_noexcept) :
129 data_{array}, sz{capacity_}
130 {}
131
133 template <size_t capacity2>
134 explicit constexpr small_vector(std::array<value_type, capacity2> const & array) noexcept(is_noexcept) :
135 sz{capacity2}
136 {
137 static_assert(capacity2 <= capacity_, "You can only initialize from array that has smaller or equal capacity.");
138 std::ranges::copy(array, data_.begin());
139 }
141
155 template <size_t capacity2>
156 explicit constexpr small_vector(value_type const (&array)[capacity2]) noexcept(is_noexcept) :
157 sz{capacity2}
158 {
159 static_assert(capacity2 <= capacity_, "You can only initialize from array that has smaller or equal capacity.");
160 std::ranges::copy(array, data_.begin());
161 }
162
176 template <typename ...other_value_type>
178 requires (std::same_as<value_type, other_value_type> && ...)
180 constexpr small_vector(other_value_type... args) noexcept(is_noexcept) :
181 data_{args...}, sz{sizeof...(other_value_type)}
182 {
183 static_assert(sizeof...(other_value_type) <= capacity_, "Value list must not exceed the capacity.");
184 }
185
203 template <std::forward_iterator begin_it_type, typename end_it_type>
205 requires std::sentinel_for<end_it_type, begin_it_type> &&
206 std::constructible_from<value_type, std::iter_reference_t<begin_it_type>>
208 constexpr small_vector(begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept) :
210 {
211 assign(begin_it, end_it);
212 }
213
229 template <std::ranges::input_range other_range_t>
231 requires (!std::is_same_v<std::remove_cvref_t<other_range_t>, small_vector>)
232 /*ICE: && std::constructible_from<value_type, std::ranges::range_reference_t<other_range_t>>*/
234 explicit constexpr small_vector(other_range_t && range) noexcept(is_noexcept) :
235 small_vector{std::ranges::begin(range), std::ranges::end(range)}
236 {}
237
252 constexpr small_vector(size_type n, value_type value) noexcept(is_noexcept) :
254 {
255 assign(n, value);
256 }
257
271 constexpr small_vector & operator=(std::initializer_list<value_type> ilist) noexcept(is_noexcept)
272 {
273 assign(std::ranges::begin(ilist), std::ranges::end(ilist));
274 return *this;
275 }
276
290 constexpr void assign(std::initializer_list<value_type> ilist) noexcept(is_noexcept)
291 {
292 assign(std::ranges::begin(ilist), std::ranges::end(ilist));
293 }
294
309 constexpr void assign(size_type const count, value_type const value) noexcept(is_noexcept)
310 {
311 clear();
312 auto tmp = views::repeat_n(value, count);
313 assign(std::ranges::begin(tmp), std::ranges::end(tmp));
314 }
315
331 template <std::ranges::input_range other_range_t>
333 requires std::constructible_from<value_type, std::ranges::range_reference_t<other_range_t>>
335 constexpr void assign(other_range_t && range) noexcept(is_noexcept)
336 {
337 assign(std::ranges::begin(range), std::ranges::end(range));
338 }
339
357 template <std::forward_iterator begin_it_type, typename end_it_type>
359 requires std::sentinel_for<end_it_type, begin_it_type> &&
360 std::constructible_from<value_type, std::iter_reference_t<begin_it_type>>
362 constexpr void assign(begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept)
363 {
364 clear();
365 insert(cbegin(), begin_it, end_it);
366 }
368
376 constexpr iterator begin() noexcept
377 {
378 return data_.data();
379 }
380
382 constexpr const_iterator begin() const noexcept
383 {
384 return data_.data();
385 }
386
388 constexpr const_iterator cbegin() const noexcept
389 {
390 return data_.data();
391 }
392
397 constexpr iterator end() noexcept
398 {
399 return data_.data() + sz;
400 }
401
403 constexpr const_iterator end() const noexcept
404 {
405 return data_.data() + sz;
406 }
407
409 constexpr const_iterator cend() const noexcept
410 {
411 return data_.data() + sz;
412 }
414
436 {
437 if (i >= size()) // [[unlikely]]
438 {
439 throw std::out_of_range{"Trying to access element behind the last in small_vector."};
440 }
441 return (*this)[i];
442 }
443
446 {
447 if (i >= size()) // [[unlikely]]
448 {
449 throw std::out_of_range{"Trying to access element behind the last in small_vector."};
450 }
451 return (*this)[i];
452 }
453
471 constexpr reference operator[](size_type const i) noexcept
472 {
473 assert(i < size());
474 return data_[i];
475 }
476
478 constexpr const_reference operator[](size_type const i) const noexcept
479 {
480 assert(i < size());
481 return data_[i];
482 }
483
499 constexpr reference front() noexcept
500 {
501 assert(size() > 0);
502 return (*this)[0];
503 }
504
506 constexpr const_reference front() const noexcept
507 {
508 assert(size() > 0);
509 return (*this)[0];
510 }
511
527 constexpr reference back() noexcept
528 {
529 assert(size() > 0);
530 return (*this)[size()-1];
531 }
532
534 constexpr const_reference back() const noexcept
535 {
536 assert(size() > 0);
537 return (*this)[size()-1];
538 }
539
544 constexpr value_type * data() noexcept
545 {
546 return data_.data();
547 }
548
550 constexpr value_type const * data() const noexcept
551 {
552 return data_.data();
553 }
555
572 constexpr bool empty() const noexcept
573 {
574 return size() == 0;
575 }
576
590 constexpr size_type size() const noexcept
591 {
592 return sz;
593 }
594
611 constexpr size_type max_size() const noexcept
612 {
613 return capacity_;
614 }
615
629 constexpr size_type capacity() const noexcept
630 {
631 return capacity_;
632 }
633
638 constexpr void reserve(size_type) const noexcept
639 {
640 // no-op
641 }
642
647 constexpr void shrink_to_fit() const noexcept
648 {
649 // no-op
650 }
652
668 constexpr void clear() noexcept
669 {
670 sz = 0;
671 }
672
690 constexpr iterator insert(const_iterator pos, value_type const value) noexcept(is_noexcept)
691 {
692 return insert(pos, 1, value);
693 }
694
713 constexpr iterator insert(const_iterator pos, size_type const count, value_type const value) noexcept(is_noexcept)
714 {
715 auto tmp = views::repeat_n(value, count);
716 return insert(pos, std::ranges::begin(tmp), std::ranges::end(tmp));
717 }
718
741 template <std::forward_iterator begin_it_type, typename end_it_type>
743 requires std::sentinel_for<end_it_type, begin_it_type> &&
744 std::constructible_from<value_type, std::iter_reference_t<begin_it_type>>
746 constexpr iterator insert(const_iterator pos, begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept)
747 {
748 auto const pos_as_num = std::ranges::distance(cbegin(), pos);
749 auto const length = std::ranges::distance(begin_it, end_it);
750
751 assert(pos_as_num + length <= capacity());
752
753 if (length == 0)
754 return begin(); // nothing to insert
755
756 for (size_type i = sz + length - 1; i > pos_as_num + length - 1; --i)
757 data_[i] = data_[i - length];
758
759 std::ranges::copy(begin_it, end_it, &data_[pos_as_num]);
760 sz += length;
761 return begin() + pos_as_num;
762 }
763
781 constexpr iterator insert(const_iterator pos, std::initializer_list<value_type> const & ilist) noexcept(is_noexcept)
782 {
783 return insert(pos, ilist.begin(), ilist.end());
784 }
785
806 constexpr iterator erase(const_iterator begin_it, const_iterator end_it) noexcept
807 {
808 if (begin_it >= end_it) // [[unlikely]]
809 return begin() + std::ranges::distance(cbegin(), end_it);
810
811 size_type const length = std::ranges::distance(begin_it, end_it);
812 auto out_it = begin() + std::ranges::distance(cbegin(), begin_it);
813
814 while (end_it != cend())
815 *(out_it++) = *(end_it++);
816
817 sz -= length;
818 return begin() + std::ranges::distance(cbegin(), begin_it);
819 }
820
841 constexpr iterator erase(const_iterator pos) noexcept
842 {
843 return erase(pos, pos + 1);
844 }
845
861 constexpr void push_back(value_type const value) noexcept
862 {
863 assert(sz < capacity_);
864 data_[sz] = value;
865 ++sz;
866 }
867
884 constexpr void pop_back() noexcept
885 {
886 assert(sz > 0);
887 --sz;
888 }
889
905 constexpr void resize(size_type const count) noexcept
906 {
907 assert(count <= capacity_);
908 sz = count;
909 }
910
915 constexpr void resize(size_type const count, value_type const value) noexcept
916 {
917 assert(count <= capacity_);
918 for (size_t i = sz; i < count; ++i)
919 data_[i] = value;
920 sz = count;
921 }
922
936 constexpr void swap(small_vector & rhs) noexcept(is_noexcept)
937 {
938 auto tmp = *this;
939
940 data_ = rhs.data_;
941 sz = rhs.sz;
942
943 rhs.data_ = tmp.data_;
944 rhs.sz = tmp.sz;
945 }
946
948 constexpr void swap(small_vector && rhs) noexcept(is_noexcept)
949 {
950 data_ = rhs.data_;
951 sz = rhs.sz;
952 }
954
969 friend constexpr void swap(small_vector & lhs, small_vector & rhs) noexcept(is_noexcept)
970 {
971 lhs.swap(rhs);
972 }
973
975 friend constexpr void swap(small_vector && lhs, small_vector && rhs) noexcept(is_noexcept)
976 {
977 lhs.swap(rhs);
978 }
979
987 template <size_t cap2>
988 friend constexpr bool operator==(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
989 {
990 return std::ranges::equal(lhs, rhs);
991 }
992
997 template <size_t cap2>
998 friend constexpr bool operator!=(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
999 {
1000 return !(lhs == rhs);
1001 }
1002
1007 template <size_t cap2>
1008 friend constexpr bool operator<(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
1009 {
1010 for (size_t i = 0; i < std::min(lhs.size(), rhs.size()); ++i)
1011 if (lhs[i] > rhs[i])
1012 return false;
1013 else if (lhs[i] < rhs[i])
1014 return true;
1015 return lhs.size() < rhs.size();
1016 }
1017
1022 template <size_t cap2>
1023 friend constexpr bool operator>(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
1024 {
1025 for (size_t i = 0; i < std::min(lhs.size(), rhs.size()); ++i)
1026 if (lhs[i] < rhs[i])
1027 return false;
1028 else if (lhs[i] > rhs[i])
1029 return true;
1030 return lhs.size() > rhs.size();
1031 }
1032
1037 template <size_t cap2>
1038 friend constexpr bool operator<=(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
1039 {
1040 return !(lhs > rhs);
1041 }
1042
1047 template <size_t cap2>
1048 friend constexpr bool operator>=(small_vector const & lhs, small_vector<value_type, cap2> const & rhs) noexcept
1049 {
1050 return !(lhs < rhs);
1051 }
1053
1054public:
1056
1060 size_type sz{0};
1061
1063
1069 template <cereal_archive archive_t>
1070 void CEREAL_SERIALIZE_FUNCTION_NAME(archive_t & archive)
1071 {
1072 archive(data_);
1073 archive(sz);
1074 }
1076};
1077
1086template <size_t capacity2, typename value_type>
1087small_vector(value_type const (&array)[capacity2]) -> small_vector<value_type, capacity2>;
1089
1090} // namespace seqan3
Adaptions of concepts from the Cereal library.
A constexpr vector implementation with dynamic size at compile time.
Definition: small_vector.hpp:47
constexpr void swap(small_vector &rhs) noexcept(is_noexcept)
Swap contents with another instance.
Definition: small_vector.hpp:936
constexpr reference operator[](size_type const i) noexcept
Return the i-th element.
Definition: small_vector.hpp:471
constexpr bool empty() const noexcept
Checks whether the container is empty.
Definition: small_vector.hpp:572
constexpr friend bool operator>(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:1023
constexpr reference front() noexcept
Return the first element. Calling front on an empty container is undefined.
Definition: small_vector.hpp:499
constexpr friend bool operator==(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:988
constexpr friend bool operator<(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:1008
constexpr small_vector(begin_it_type begin_it, end_it_type end_it) noexcept(is_noexcept)
Construct from two iterators.
Definition: small_vector.hpp:208
constexpr void shrink_to_fit() const noexcept
Since the capacity is fixed on compile time, this is a no-op.
Definition: small_vector.hpp:647
constexpr const_iterator cbegin() const noexcept
Returns the begin to the string.
Definition: small_vector.hpp:388
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:713
constexpr void resize(size_type const count) noexcept
Resizes the container to contain count elements.
Definition: small_vector.hpp:905
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:629
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:362
constexpr small_vector() noexcept=default
Defaulted.
const value_type & const_reference
The const_reference type.
Definition: small_vector.hpp:72
constexpr void assign(size_type const count, value_type const value) noexcept(is_noexcept)
Assign with count times value.
Definition: small_vector.hpp:309
constexpr void swap(small_vector &&rhs) noexcept(is_noexcept)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: small_vector.hpp:948
constexpr const_reference operator[](size_type const i) const noexcept
Return the i-th element.
Definition: small_vector.hpp:478
constexpr void push_back(value_type const value) noexcept
Appends the given element value to the end of the container.
Definition: small_vector.hpp:861
constexpr void pop_back() noexcept
Removes the last element of the container.
Definition: small_vector.hpp:884
constexpr void assign(std::initializer_list< value_type > ilist) noexcept(is_noexcept)
Assign from std::initializer_list.
Definition: small_vector.hpp:290
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:746
value_type * iterator
The iterator type.
Definition: small_vector.hpp:78
constexpr small_vector & operator=(std::initializer_list< value_type > ilist) noexcept(is_noexcept)
Assign from std::initializer_list.
Definition: small_vector.hpp:271
constexpr small_vector(size_type n, value_type value) noexcept(is_noexcept)
Construct with n times value.
Definition: small_vector.hpp:252
constexpr iterator erase(const_iterator pos) noexcept
Removes specified elements from the container.
Definition: small_vector.hpp:841
constexpr friend void swap(small_vector &&lhs, small_vector &&rhs) noexcept(is_noexcept)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: small_vector.hpp:975
value_type const * const_iterator
The const_iterator type.
Definition: small_vector.hpp:84
constexpr iterator erase(const_iterator begin_it, const_iterator end_it) noexcept
Removes specified elements from the container.
Definition: small_vector.hpp:806
constexpr iterator insert(const_iterator pos, value_type const value) noexcept(is_noexcept)
Inserts value before position in the container.
Definition: small_vector.hpp:690
constexpr void resize(size_type const count, value_type const value) noexcept
Resizes the container to contain count elements.
Definition: small_vector.hpp:915
value_type_ value_type
The value_type type.
Definition: small_vector.hpp:60
constexpr const_iterator begin() const noexcept
Returns the begin to the string.
Definition: small_vector.hpp:382
constexpr small_vector(other_range_t &&range) noexcept(is_noexcept)
Construct from a different range.
Definition: small_vector.hpp:234
detail::min_viable_uint_t< capacity_ > size_type
The size_type type.
Definition: small_vector.hpp:96
constexpr void assign(other_range_t &&range) noexcept(is_noexcept)
Assign from a different range.
Definition: small_vector.hpp:335
constexpr size_type size() const noexcept
Returns the number of elements in the container, i.e. std::distance(begin(), end()).
Definition: small_vector.hpp:590
constexpr const_iterator cend() const noexcept
Returns iterator past the end of the vector.
Definition: small_vector.hpp:409
constexpr reference back() noexcept
Return the last element.
Definition: small_vector.hpp:527
constexpr value_type const * data() const noexcept
Direct access to the underlying array.
Definition: small_vector.hpp:550
constexpr friend bool operator<=(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:1038
const_reference at(size_type const i) const
Return the i-th element.
Definition: small_vector.hpp:445
constexpr iterator begin() noexcept
Returns the begin to the string.
Definition: small_vector.hpp:376
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:156
constexpr void clear() noexcept
Removes all elements from the container.
Definition: small_vector.hpp:668
ptrdiff_t difference_type
The difference_type type.
Definition: small_vector.hpp:90
constexpr iterator end() noexcept
Returns iterator past the end of the vector.
Definition: small_vector.hpp:397
constexpr value_type * data() noexcept
Direct access to the underlying array.
Definition: small_vector.hpp:544
value_type & reference
The reference type.
Definition: small_vector.hpp:66
constexpr friend void swap(small_vector &lhs, small_vector &rhs) noexcept(is_noexcept)
Swap contents with another instance.
Definition: small_vector.hpp:969
constexpr const_reference front() const noexcept
Return the first element. Calling front on an empty container is undefined.
Definition: small_vector.hpp:506
constexpr friend bool operator!=(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:998
reference at(size_type const i)
Return the i-th element.
Definition: small_vector.hpp:435
constexpr void reserve(size_type) const noexcept
Since the capacity is fixed on compile time, this is a no-op.
Definition: small_vector.hpp:638
constexpr const_reference back() const noexcept
Return the last element.
Definition: small_vector.hpp:534
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:611
constexpr const_iterator end() const noexcept
Returns iterator past the end of the vector.
Definition: small_vector.hpp:403
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:781
constexpr small_vector(other_value_type... args) noexcept(is_noexcept)
Construct from a list of values of value_type.
Definition: small_vector.hpp:180
constexpr friend bool operator>=(small_vector const &lhs, small_vector< value_type, cap2 > const &rhs) noexcept
Performs element-wise comparison.
Definition: small_vector.hpp:1048
constexpr ptrdiff_t count
Count the occurrences of a type in a pack.
Definition: traits.hpp:169
constexpr auto repeat_n
A view factory that repeats a given value n times.
Definition: repeat_n.hpp:91
Provides metaprogramming utilities for integer types.
T min(T... args)
The main SeqAn3 namespace.
Definition: cigar_operation_table.hpp:2
small_vector(value_type const (&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.
Provides seqan3::views::repeat_n.
Provides type traits for working with templates.