2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2019, 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/gmxassert.h"
54 /*! \brief Vector that behaves likes std::vector but has fixed capacity.
56 * \tparam T Value type of elements.
57 * \tparam capacity The maximum number of elements that can be stored.
59 * This class provides a variable size container, but with constant
60 * memory usage and can be allocated on the stack and avoid the overhead
61 * of dynamic allocation. This is especially useful for small vectors
62 * which are set up frequently.
64 * The class supports all methods from \p std::array, but behaves more
65 * like \p std::vector since it has variable size. In addition to the methods
66 * from std::array, from \p std::vector the methods \p push_back(), \p pop_back(),
67 * emplace_back() and \p clear() are supported. In particular, methods that
68 * requires reordering, such as \p insert() and \p emplace() are not
69 * supported to keep the code simple.
71 * The size is 0 at construction and elements can only be added with
72 * \p push_back() and \p emplace_back().
74 * \note This class is very similar to the fixed_capacity_vector class
75 * proposed for the C++ standard in document P0843r see:
76 * http://open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0843r1.html
79 * \ingroup module_utility
81 template<typename T, size_t capacity>
82 class FixedCapacityVector
85 //! Type of values stored in the vector
87 //! Type for representing size of the vector
88 using size_type = size_t;
89 //! Type for representing difference between two indices
90 using difference_type = ptrdiff_t;
91 //! Const reference to an element
92 using const_reference = const T&;
93 //! Const pointer to an element
94 using const_pointer = const T*;
95 //! Const iterator type to an element
96 using const_iterator = const T*;
97 //! Reference to an element
99 //! Pointer to an element
101 //! Iterator type to an element
103 //! Standard reverse iterator
104 using reverse_iterator = std::reverse_iterator<iterator>;
105 //! Standard reverse iterator
106 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
108 //! Returns a const iterator to the beginning
109 const_iterator begin() const noexcept { return data(); }
110 //! Returns an iterator to the beginning
111 iterator begin() noexcept { return data(); }
112 //! Returns a const iterator to the end
113 const_iterator end() const noexcept { return end_; }
114 //! Returns an iterator to the end
115 iterator end() noexcept { return end_; }
116 //! Returns a const iterator to the reverse beginning
117 const_reverse_iterator rbegin() const noexcept { return reverse_iterator(end_); }
118 //! Returns an iterator to the reverse beginning
119 reverse_iterator rbegin() noexcept { return reverse_iterator(end_); }
120 //! Returns a const iterator to the reverse end
121 const_reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
122 //! Returns an iterator to the reverse end
123 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
125 /*! \brief Returns the size
127 * \note Use ssize for any expression involving arithmetic operations
128 (including loop indices).
130 size_type size() const noexcept { return end_ - data(); }
131 //! Returns the signed size
132 index ssize() const noexcept { return end_ - data(); }
133 //! Returns whether the vector is empty
134 bool empty() const noexcept { return data() == end_; }
136 //! Const access an element
137 const_reference operator[](size_type n) const noexcept
139 GMX_ASSERT(n < size(), "Index should be in range");
142 //! Access an element
143 reference operator[](size_type n) noexcept
145 GMX_ASSERT(n < size(), "Index should be in range");
148 //! Const access an element, throws an out_of_range exception when out of range
149 const_reference at(size_type n) const
153 throw std::out_of_range("Vector index out of range");
157 //! Access an element, throws an out_of_range exception when out of range
158 reference at(size_type n)
162 throw std::out_of_range("Vector index out of range");
166 //! Returns the first element
167 reference front() const noexcept { return data_.front(); }
168 //! Returns the last element
169 reference back() const noexcept { return *(end_ - 1); }
171 //! Returns a raw pointer to the contents of the array
172 const T* data() const noexcept { return data_.data(); }
174 //! Returns a raw pointer to the contents of the array
175 T* data() noexcept { return data_.data(); }
177 //! Adds element at the end
178 void push_back(const T& value) noexcept
180 GMX_ASSERT(size() < capacity, "Cannot add more elements than the capacity");
185 //! Deletes last element
186 void pop_back() noexcept
188 GMX_ASSERT(!empty(), "Can only delete last element when present");
192 //! Constructs an element at the end
193 template<class... Args>
194 reference emplace_back(Args&&... args)
196 GMX_ASSERT(size() < capacity, "Cannot add more elements than the capacity");
197 if (std::is_move_assignable<T>::value)
199 *end_ = std::move(T(args...));
211 void clear() noexcept { end_ = data(); }
214 //! The elements, stored in a fixed size array
215 std::array<T, capacity> data_;
216 //! The size of the vector
217 pointer end_ = data();