1414#include " srsran/support/srsran_assert.h"
1515#include < array>
1616#include < iterator>
17+ #include < limits>
1718#include < memory>
1819
1920namespace srsran {
2021
2122namespace detail {
2223
24+ // / Selects the smallest unsigned integer type that can represent the range [0, N].
25+ template <size_t N>
26+ using size_type_selector = std::conditional_t <
27+ (N < std::numeric_limits<uint8_t >::max()),
28+ uint8_t ,
29+ std::conditional_t <
30+ (N < std::numeric_limits<uint16_t >::max()),
31+ uint16_t ,
32+ std::conditional_t <(N < std::numeric_limits<uint32_t >::max()),
33+ uint32_t ,
34+ std::conditional_t <(N < std::numeric_limits<uint64_t >::max()), uint64_t , size_t >>>>;
35+
2336template <typename T, size_t Capacity>
2437struct trivial_storage {
25- static_assert (std::is_trivial <T>::value , " Implementation only works for trivial types" );
38+ static_assert (std::is_trivial_v <T>, " Implementation only works for trivial types" );
2639
27- using array_type = std::conditional_t <std::is_const<T>::value,
28- const std::array<std::remove_const_t <T>, Capacity>,
29- std::array<T, Capacity>>;
40+ using array_type = std::
41+ conditional_t <std::is_const_v<T>, const std::array<std::remove_const_t <T>, Capacity>, std::array<T, Capacity>>;
3042 using iterator = T*;
3143 using const_iterator = const T*;
3244
@@ -89,16 +101,16 @@ struct trivial_storage {
89101 // do nothing.
90102 }
91103
92- array_type array;
93- size_t sz = 0 ;
104+ array_type array;
105+ size_type_selector<Capacity> sz = 0 ;
94106};
95107
96108template <typename T, size_t Capacity>
97109struct non_trivial_storage {
98- static_assert (not std::is_trivial <T>::value , " Implementation only works for non-trivial types" );
110+ static_assert (not std::is_trivial_v <T>, " Implementation only works for non-trivial types" );
99111
100112 using element_storage_t = std::aligned_storage_t <sizeof (T), alignof (T)>;
101- using array_type = std::conditional_t <std::is_const <T>::value ,
113+ using array_type = std::conditional_t <std::is_const_v <T>,
102114 const std::array<element_storage_t , Capacity>,
103115 std::array<element_storage_t , Capacity>>;
104116 using iterator = T*;
@@ -148,7 +160,7 @@ struct non_trivial_storage {
148160 const_iterator end () const noexcept { return begin () + sz; }
149161
150162 template <typename ... Args>
151- constexpr void construct_ (size_t idx, Args&&... args) noexcept (std::is_nothrow_constructible <T, Args...>::value )
163+ constexpr void construct_ (size_t idx, Args&&... args) noexcept (std::is_nothrow_constructible_v <T, Args...>)
152164 {
153165 static_assert (std::is_constructible<T, Args...>::value, " T(Args...) does not exist" );
154166 new (&array[idx]) T (std::forward<Args>(args)...);
@@ -157,13 +169,13 @@ struct non_trivial_storage {
157169 void destroy_ (size_t idx) noexcept { (*this )[idx].~T (); }
158170 void destroy_ (iterator it) noexcept { (*it).~T (); }
159171
160- array_type array;
161- size_t sz = 0 ;
172+ array_type array;
173+ size_type_selector<Capacity> sz = 0 ;
162174};
163175
164176template <typename T, size_t Capacity>
165177using static_vector_storage =
166- std::conditional_t <std::is_trivial <T>::value , trivial_storage<T, Capacity>, non_trivial_storage<T, Capacity>>;
178+ std::conditional_t <std::is_trivial_v <T>, trivial_storage<T, Capacity>, non_trivial_storage<T, Capacity>>;
167179
168180} // namespace detail
169181
@@ -173,7 +185,7 @@ using static_vector_storage =
173185// / @tparam T type of the elements
174186// / @tparam MAX_N Maximum number of elements of the static_vector
175187template <typename T, std::size_t MAX_N>
176- class static_vector : private detail ::static_vector_storage<T, MAX_N>
188+ class static_vector : public detail ::static_vector_storage<T, MAX_N>
177189{
178190 using base_type = detail::static_vector_storage<T, MAX_N>;
179191
@@ -197,7 +209,7 @@ class static_vector : private detail::static_vector_storage<T, MAX_N>
197209 // /
198210 // / Note: The ctor needs to be user-defined to forbid zero-initialization of the storage via = {}.
199211 constexpr static_vector () noexcept {}
200- explicit constexpr static_vector (size_type count) noexcept (std::is_nothrow_default_constructible <T>::value )
212+ explicit constexpr static_vector (size_type count) noexcept (std::is_nothrow_default_constructible_v <T>)
201213 {
202214 static_assert (std::is_default_constructible<T>::value, " T must be default-constructible" );
203215 srsran_assert (count <= MAX_N, " static vector maximum size={} was exceeded" , MAX_N);
@@ -208,18 +220,17 @@ class static_vector : private detail::static_vector_storage<T, MAX_N>
208220 }
209221 this ->sz = count;
210222 }
211- constexpr static_vector (size_type count,
212- const T& initial_value) noexcept (std::is_nothrow_copy_constructible<T>::value)
223+ constexpr static_vector (size_type count, const T& initial_value) noexcept (std::is_nothrow_copy_constructible_v<T>)
213224 {
214225 static_assert (std::is_copy_constructible<T>::value, " T must be copy-constructible" );
215226 assign_unsafe_ (count, initial_value);
216227 }
217- constexpr static_vector (const static_vector& other) noexcept (std::is_nothrow_copy_constructible <T>::value )
228+ constexpr static_vector (const static_vector& other) noexcept (std::is_nothrow_copy_constructible_v <T>)
218229 {
219230 static_assert (std::is_copy_constructible<T>::value, " T must be copyable" );
220231 assign_unsafe_ (other.begin (), other.end ());
221232 }
222- constexpr static_vector (static_vector&& other) noexcept (std::is_nothrow_move_constructible <value_type>::value )
233+ constexpr static_vector (static_vector&& other) noexcept (std::is_nothrow_move_constructible_v <value_type>)
223234 {
224235 static_assert (std::is_move_constructible<T>::value, " T must be move-constructible" );
225236 assign_unsafe_ (std::make_move_iterator (other.begin ()), std::make_move_iterator (other.end ()));
@@ -233,14 +244,14 @@ class static_vector : private detail::static_vector_storage<T, MAX_N>
233244 }
234245 constexpr static_vector (std::initializer_list<T> init) : static_vector(init.begin(), init.end()) {}
235246 ~static_vector () = default ;
236- constexpr static_vector& operator =(const static_vector& other) noexcept (std::is_nothrow_copy_assignable <T>::value )
247+ constexpr static_vector& operator =(const static_vector& other) noexcept (std::is_nothrow_copy_assignable_v <T>)
237248 {
238249 if (this != &other) {
239250 assign (other.begin (), other.end ());
240251 }
241252 return *this ;
242253 }
243- constexpr static_vector& operator =(static_vector&& other) noexcept (std::is_nothrow_move_assignable <value_type>::value )
254+ constexpr static_vector& operator =(static_vector&& other) noexcept (std::is_nothrow_move_assignable_v <value_type>)
244255 {
245256 size_t min_common_size = std::min (other.size (), size ());
246257 if (min_common_size > 0 ) {
@@ -266,21 +277,21 @@ class static_vector : private detail::static_vector_storage<T, MAX_N>
266277
267278 // modifiers
268279 template <typename ... Args>
269- constexpr T& emplace_back (Args&&... args) noexcept (std::is_nothrow_constructible <T, Args...>::value )
280+ constexpr T& emplace_back (Args&&... args) noexcept (std::is_nothrow_constructible_v <T, Args...>)
270281 {
271282 srsran_assert (size () < MAX_N, " Cannot emplace back in full vector" );
272283 this ->construct_ (size (), std::forward<Args>(args)...);
273284 this ->sz ++;
274285 return this ->back ();
275286 }
276287
277- constexpr void push_back (const T& value) noexcept (std::is_nothrow_copy_constructible <T>::value )
288+ constexpr void push_back (const T& value) noexcept (std::is_nothrow_copy_constructible_v <T>)
278289 {
279290 static_assert (std::is_copy_constructible<T>::value, " T must be copy-constructible" );
280291 emplace_back (value);
281292 }
282293
283- constexpr void push_back (T&& value) noexcept (std::is_nothrow_move_constructible <T>::value )
294+ constexpr void push_back (T&& value) noexcept (std::is_nothrow_move_constructible_v <T>)
284295 {
285296 static_assert (std::is_move_constructible<T>::value, " T must be move-constructible" );
286297 emplace_back (std::move (value));
@@ -331,7 +342,7 @@ class static_vector : private detail::static_vector_storage<T, MAX_N>
331342 this ->sz = new_size;
332343 }
333344
334- constexpr iterator erase (iterator pos) noexcept (std::is_move_assignable <T>::value )
345+ constexpr iterator erase (iterator pos) noexcept (std::is_move_assignable_v <T>)
335346 {
336347 srsran_assert (pos >= this ->begin () and pos < this ->end (), " Iterator to erase is out-of-bounds" );
337348 iterator ret = pos;
@@ -340,7 +351,7 @@ class static_vector : private detail::static_vector_storage<T, MAX_N>
340351 return ret;
341352 }
342353
343- constexpr iterator erase (iterator it_start, iterator it_end) noexcept (std::is_move_assignable <T>::value )
354+ constexpr iterator erase (iterator it_start, iterator it_end) noexcept (std::is_move_assignable_v <T>)
344355 {
345356 srsran_assert (it_start <= it_end, " Trying to erase invalid range" );
346357 srsran_assert (it_start >= begin () and it_end <= end (), " Range to erase is out-of-bounds" );
@@ -353,20 +364,20 @@ class static_vector : private detail::static_vector_storage<T, MAX_N>
353364 return ret;
354365 }
355366
356- constexpr void assign (size_type nof_elems, const T& value) noexcept (std::is_nothrow_copy_constructible <T>::value )
367+ constexpr void assign (size_type nof_elems, const T& value) noexcept (std::is_nothrow_copy_constructible_v <T>)
357368 {
358369 clear ();
359370 assign_unsafe_ (nof_elems, value);
360371 }
361372
362373 template <typename Iterator>
363- constexpr void assign (Iterator it_start, Iterator it_end) noexcept (std::is_nothrow_copy_constructible <T>::value )
374+ constexpr void assign (Iterator it_start, Iterator it_end) noexcept (std::is_nothrow_copy_constructible_v <T>)
364375 {
365376 clear ();
366377 assign_unsafe_ (it_start, it_end);
367378 }
368379
369- constexpr void assign (std::initializer_list<T> ilist) noexcept (std::is_nothrow_copy_constructible <T>::value )
380+ constexpr void assign (std::initializer_list<T> ilist) noexcept (std::is_nothrow_copy_constructible_v <T>)
370381 {
371382 assign (ilist.begin (), ilist.end ());
372383 }
@@ -404,7 +415,7 @@ class static_vector : private detail::static_vector_storage<T, MAX_N>
404415 this ->destroy_ (it);
405416 }
406417 }
407- constexpr void assign_unsafe_ (size_t N, const T& val) noexcept (std::is_nothrow_copy_constructible <T>::value )
418+ constexpr void assign_unsafe_ (size_t N, const T& val) noexcept (std::is_nothrow_copy_constructible_v <T>)
408419 {
409420 srsran_assert (N <= MAX_N, " static vector maximum size={} was exceeded" , MAX_N);
410421 // Note: Gcc 11 fails compilation without this hint. Potentially a bug.
@@ -415,8 +426,7 @@ class static_vector : private detail::static_vector_storage<T, MAX_N>
415426 this ->sz = N;
416427 }
417428 template <typename Iterator>
418- constexpr void assign_unsafe_ (Iterator it_begin,
419- Iterator it_end) noexcept (std::is_nothrow_copy_constructible<T>::value)
429+ constexpr void assign_unsafe_ (Iterator it_begin, Iterator it_end) noexcept (std::is_nothrow_copy_constructible_v<T>)
420430 {
421431 size_type N = std::distance (it_begin, it_end);
422432 srsran_assert (N <= MAX_N, " static vector maximum size={} was exceeded" , MAX_N);
0 commit comments