11#pragma once
22#pragma GCC diagnostic ignored "-Wunused-parameter"
33
4+ #include < beman/inplace_vector/config.hpp>
5+ #ifndef BEMAN_INPLACE_VECTOR_CONFIG
6+ #error "Config file not run"
7+ #endif
8+
49/*
510 * SPDX-FileCopyrightText: Copyright (c) 2023 Gonzalo Brito Gadeschi. All rights
611reserved.
@@ -282,15 +287,31 @@ namespace beman::details::inplace_vector {
282287
283288// clang-format off
284289// Smallest unsigned integer that can represent values in [0, N].
285- template <size_t N>
290+ template <std:: size_t N>
286291using smallest_size_t
287292= std::conditional_t <(N < std::numeric_limits<uint8_t >::max()), uint8_t ,
288293 std::conditional_t <(N < std::numeric_limits<uint16_t >::max()), uint16_t ,
289294 std::conditional_t <(N < std::numeric_limits<uint32_t >::max()), uint32_t ,
290295 std::conditional_t <(N < std::numeric_limits<uint64_t >::max()), uint64_t ,
291- size_t >>>>;
296+ std:: size_t >>>>;
292297// clang-format on
293298
299+ /*
300+ * This is generally for managing the size type in the storage block.
301+ * This behavior can be turned off by setting the
302+ * BEMAN_INPLACE_VECTOR_FIXED_SIZE_T build option as there has been report of
303+ * performance impact.
304+ *
305+ * This macro is set in the config.hpp.
306+ */
307+ template <std::size_t N>
308+ using size_t_for =
309+ #if BEMAN_INPLACE_VECTOR_FIXED_SIZE_T == 1
310+ std::size_t ;
311+ #else
312+ smallest_size_t <N>;
313+ #endif
314+
294315// Index a random-access and sized range doing bound checks in debug builds
295316template <std::ranges::random_access_range Rng, std::integral Index>
296317static constexpr decltype (auto ) index(Rng &&rng, Index i) noexcept
@@ -317,7 +338,7 @@ template <class T> struct zero_sized {
317338 using size_type = uint8_t ;
318339 static constexpr T *storage_data () noexcept { return nullptr ; }
319340 static constexpr size_type storage_size () noexcept { return 0 ; }
320- static constexpr void unsafe_set_size (size_t new_size) noexcept {
341+ static constexpr void unsafe_set_size (std:: size_t new_size) noexcept {
321342 IV_EXPECT (new_size == 0 &&
322343 " tried to change size of empty storage to non-zero value" );
323344 }
@@ -332,13 +353,13 @@ template <class T> struct zero_sized {
332353};
333354
334355// Storage for trivial types.
335- template <class T , size_t N> struct trivial {
356+ template <class T , std:: size_t N> struct trivial {
336357 static_assert (std::is_trivial_v<T>,
337358 " storage::trivial<T, C> requires Trivial<T>" );
338- static_assert (N != size_t {0 }, " N == 0, use zero_sized" );
359+ static_assert (N != std:: size_t {0 }, " N == 0, use zero_sized" );
339360
340361protected:
341- using size_type = smallest_size_t <N>;
362+ using size_type = size_t_for <N>;
342363
343364private:
344365 // If value_type is const, then const std::array of non-const elements:
@@ -354,7 +375,7 @@ template <class T, size_t N> struct trivial {
354375 }
355376 constexpr T *storage_data () noexcept { return storage_data_.data (); }
356377 constexpr size_type storage_size () const noexcept { return storage_size_; }
357- constexpr void unsafe_set_size (size_t new_size) noexcept {
378+ constexpr void unsafe_set_size (std:: size_t new_size) noexcept {
358379 IV_EXPECT (size_type (new_size) <= N && " new_size out-of-bounds [0, N]" );
359380 storage_size_ = size_type (new_size);
360381 }
@@ -368,26 +389,27 @@ template <class T, size_t N> struct trivial {
368389 constexpr ~trivial () = default ;
369390};
370391
371- template <class T , size_t N> struct raw_byte_based_storage {
392+ template <class T , std::size_t N> struct raw_byte_based_storage {
393+ public:
372394 alignas (T) std::byte _d[sizeof (T) * N];
373- constexpr T *storage_data (size_t i) noexcept {
395+ constexpr T *storage_data (std:: size_t i) noexcept {
374396 IV_EXPECT (i < N);
375397 return reinterpret_cast <T *>(_d) + i;
376398 }
377- constexpr const T *storage_data (size_t i) const noexcept {
399+ constexpr const T *storage_data (std:: size_t i) const noexcept {
378400 IV_EXPECT (i < N);
379401 return reinterpret_cast <const T *>(_d) + i;
380402 }
381403};
382404
383405// / Storage for non-trivial elements.
384- template <class T , size_t N> struct non_trivial {
406+ template <class T , std:: size_t N> struct non_trivial {
385407 static_assert (!std::is_trivial_v<T>,
386408 " use storage::trivial for Trivial<T> elements" );
387- static_assert (N != size_t {0 }, " use storage::zero for N==0" );
409+ static_assert (N != std:: size_t {0 }, " use storage::zero for N==0" );
388410
389411protected:
390- using size_type = smallest_size_t <N>;
412+ using size_type = size_t_for <N>;
391413
392414private:
393415 using byte_based_storage = std::conditional_t <
@@ -402,7 +424,7 @@ template <class T, size_t N> struct non_trivial {
402424 }
403425 constexpr T *storage_data () noexcept { return storage_data_.storage_data (0 ); }
404426 constexpr size_type storage_size () const noexcept { return storage_size_; }
405- constexpr void unsafe_set_size (size_t new_size) noexcept {
427+ constexpr void unsafe_set_size (std:: size_t new_size) noexcept {
406428 IV_EXPECT (size_type (new_size) <= N && " new_size out-of-bounds [0, N)" );
407429 storage_size_ = size_type (new_size);
408430 }
@@ -423,7 +445,7 @@ template <class T, size_t N> struct non_trivial {
423445};
424446
425447// Selects the vector storage.
426- template <class T , size_t N>
448+ template <class T , std:: size_t N>
427449using storage_for = std::conditional_t <
428450 N == 0 , zero_sized<T>,
429451 std::conditional_t <std::is_trivial_v<T>, trivial<T, N>, non_trivial<T, N>>>;
@@ -433,7 +455,7 @@ using storage_for = std::conditional_t<
433455namespace beman {
434456
435457// / Dynamically-resizable fixed-N vector with inplace storage.
436- template <class T , size_t N>
458+ template <class T , std:: size_t N>
437459struct inplace_vector
438460 : private details::inplace_vector::storage::storage_for<T, N> {
439461private:
@@ -450,7 +472,8 @@ struct inplace_vector
450472 using const_pointer = const T *;
451473 using reference = value_type &;
452474 using const_reference = const value_type &;
453- using size_type = size_t ;
475+ // Note: This may be different from base_t::size_t.
476+ using size_type = std::size_t ;
454477 using difference_type = std::ptrdiff_t ;
455478 using iterator = pointer;
456479 using const_iterator = const_pointer;
@@ -518,7 +541,9 @@ struct inplace_vector
518541 [[nodiscard]] constexpr bool empty () const noexcept {
519542 return storage_size () == 0 ;
520543 };
521- constexpr size_type size () const noexcept { return storage_size (); }
544+ constexpr size_type size () const noexcept {
545+ return size_type (storage_size ());
546+ }
522547 static constexpr size_type max_size () noexcept { return N; }
523548 static constexpr size_type capacity () noexcept { return N; }
524549 // constexpr void resize(size_type sz);
@@ -730,8 +755,8 @@ struct inplace_vector
730755 {
731756 assert_iterator_in_range (position);
732757 if constexpr (std::random_access_iterator<InputIterator>) {
733- if (size () + static_cast < size_type> (std::distance (first, last)) >
734- capacity ()) [[unlikely]]
758+ if (size () + size_type (std::distance (first, last)) > capacity ())
759+ [[unlikely]]
735760 throw std::bad_alloc{};
736761 }
737762 auto b = end ();
@@ -764,7 +789,7 @@ struct inplace_vector
764789 {
765790 assert_iterator_in_range (position);
766791 auto b = end ();
767- for (size_type i = 0 ; i < n; ++i)
792+ for (auto i = size_type ( 0 ) ; i < n; ++i)
768793 emplace_back (x);
769794 auto pos = begin () + (position - begin ());
770795 std::rotate (pos, b, end ());
@@ -827,7 +852,7 @@ struct inplace_vector
827852 iterator f = begin () + (first - begin ());
828853 if (first != last) {
829854 unsafe_destroy (std::move (f + (last - first), end (), f), end ());
830- unsafe_set_size (size () - static_cast < size_type> (last - first));
855+ unsafe_set_size (size () - size_type (last - first));
831856 }
832857 return f;
833858 }
0 commit comments