2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2019,2020,2021, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Declares gmx::FixedCapacityVector
39 * \author Berk Hess <hess@kth.se>
41 * \ingroup module_utility
43 #ifndef GMX_UTILITY_FIXEDCAPACITYVECTOR_H
44 #define GMX_UTILITY_FIXEDCAPACITYVECTOR_H
49 #include "gromacs/utility/basedefinitions.h"
50 #include "gromacs/utility/gmxassert.h"
55 /*! \brief Vector that behaves likes std::vector but has fixed capacity.
57 * \tparam T Value type of elements.
58 * \tparam capacity The maximum number of elements that can be stored.
60 * This class provides a variable size container, but with constant
61 * memory usage and can be allocated on the stack and avoid the overhead
62 * of dynamic allocation. This is especially useful for small vectors
63 * which are set up frequently.
65 * The class supports all methods from \p std::array, but behaves more
66 * like \p std::vector since it has variable size. In addition to the methods
67 * from std::array, from \p std::vector the methods \p push_back(), \p pop_back(),
68 * emplace_back() and \p clear() are supported. In particular, methods that
69 * requires reordering, such as \p insert() and \p emplace() are not
70 * supported to keep the code simple.
72 * The size is 0 at construction and elements can only be added with
73 * \p push_back() and \p emplace_back().
75 * \note This class is very similar to the fixed_capacity_vector class
76 * proposed for the C++ standard in document P0843r see:
77 * http://open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0843r1.html
80 * \ingroup module_utility
82 template<typename T, size_t capacity>
83 class FixedCapacityVector
86 //! Type of values stored in the vector
88 //! Type for representing size of the vector
89 using size_type = size_t;
90 //! Type for representing difference between two indices
91 using difference_type = ptrdiff_t;
92 //! Const reference to an element
93 using const_reference = const T&;
94 //! Const pointer to an element
95 using const_pointer = const T*;
96 //! Const iterator type to an element
97 using const_iterator = const T*;
98 //! Reference to an element
100 //! Pointer to an element
102 //! Iterator type to an element
104 //! Standard reverse iterator
105 using reverse_iterator = std::reverse_iterator<iterator>;
106 //! Standard reverse iterator
107 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
109 //! Returns a const iterator to the beginning
110 const_iterator begin() const noexcept { return data(); }
111 //! Returns an iterator to the beginning
112 iterator begin() noexcept { return data(); }
113 //! Returns a const iterator to the end
114 const_iterator end() const noexcept { return end_; }
115 //! Returns an iterator to the end
116 iterator end() noexcept { return end_; }
117 //! Returns a const iterator to the reverse beginning
118 const_reverse_iterator rbegin() const noexcept { return reverse_iterator(end_); }
119 //! Returns an iterator to the reverse beginning
120 reverse_iterator rbegin() noexcept { return reverse_iterator(end_); }
121 //! Returns a const iterator to the reverse end
122 const_reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
123 //! Returns an iterator to the reverse end
124 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
126 /*! \brief Returns the size
128 * \note Use ssize for any expression involving arithmetic operations
129 (including loop indices).
131 size_type size() const noexcept { return end_ - data(); }
132 //! Returns the signed size
133 index ssize() const noexcept { return end_ - data(); }
134 //! Returns whether the vector is empty
135 bool empty() const noexcept { return data() == end_; }
137 //! Const access an element
138 const_reference operator[](size_type n) const noexcept
140 GMX_ASSERT(n < size(), "Index should be in range");
143 //! Access an element
144 reference operator[](size_type n) noexcept
146 GMX_ASSERT(n < size(), "Index should be in range");
149 //! Const access an element, throws an out_of_range exception when out of range
150 const_reference at(size_type n) const
154 throw std::out_of_range("Vector index out of range");
158 //! Access an element, throws an out_of_range exception when out of range
159 reference at(size_type n)
163 throw std::out_of_range("Vector index out of range");
167 //! Returns the first element
168 reference front() const noexcept { return data_.front(); }
169 //! Returns the last element
170 reference back() const noexcept { return *(end_ - 1); }
172 //! Returns a raw pointer to the contents of the array
173 const T* data() const noexcept { return data_.data(); }
175 //! Returns a raw pointer to the contents of the array
176 T* data() noexcept { return data_.data(); }
178 //! Adds element at the end
179 void push_back(const T& value) noexcept
181 GMX_ASSERT(size() < capacity, "Cannot add more elements than the capacity");
186 //! Deletes last element
187 void pop_back() noexcept
189 GMX_ASSERT(!empty(), "Can only delete last element when present");
193 //! Constructs an element at the end
194 template<class... Args>
195 reference emplace_back(Args&&... args)
197 GMX_ASSERT(size() < capacity, "Cannot add more elements than the capacity");
198 if (std::is_move_assignable<T>::value)
200 *end_ = std::move(T(args...));
212 void clear() noexcept { end_ = data(); }
215 //! The elements, stored in a fixed size array
216 std::array<T, capacity> data_;
217 //! The size of the vector
218 pointer end_ = data();