openMSX
static_vector.hh
Go to the documentation of this file.
1#ifndef STATIC_VECTOR_HH
2#define STATIC_VECTOR_HH
3
4#include "ranges.hh"
5
6#include <algorithm>
7#include <array>
8#include <cassert>
9#include <cstddef>
10#include <cstdint>
11#include <initializer_list>
12#include <limits>
13#include <span>
14#include <type_traits>
15#include <utility>
16
17// This is a _very_ minimal implementation of the following (we can easily
18// extend this when the need arises).
19//
20// static_vector
21// A dynamically-resizable vector with fixed capacity and embedded storage
22// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0843r2.html
23//
24// For us the main purpose of this class is to use it during constexpr
25// (compile-time) calculations. Because for now, it's no yet possible to use
26// heap memory in constexpr functions (there are proposals to loosen this
27// restriction in future C++ standards).
28
29struct from_range_t {};
30inline constexpr from_range_t from_range;
31
32template<typename T, size_t N>
34{
35 using SizeType =
36 std::conditional_t<N <= std::numeric_limits<uint8_t >::max(), uint8_t,
37 std::conditional_t<N <= std::numeric_limits<uint16_t>::max(), uint16_t,
38 std::conditional_t<N <= std::numeric_limits<uint32_t>::max(), uint32_t,
39 uint64_t>>>;
40
41public:
42 using value_type = T;
46 using const_iterator = const value_type*;
48 using const_pointer = const value_type*;
49 using size_type = size_t;
50 using difference_type = ptrdiff_t;
51 using reverse_iterator = std::reverse_iterator<iterator>;
52 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
53
54 constexpr static_vector() = default;
55
56 constexpr static_vector(std::initializer_list<T> list) {
57 assert(list.size() <= N);
58 ranges::copy(list, array);
59 sz = SizeType(list.size());
60 }
61
62 template<typename Range>
63 constexpr static_vector(from_range_t, Range&& range) {
64 for (auto&& elem : range) {
65 push_back(std::forward<decltype(elem)>(elem));
66 }
67 }
68
69 [[nodiscard]] constexpr auto begin() noexcept { return array.begin(); }
70 [[nodiscard]] constexpr auto begin() const noexcept { return array.begin(); }
71 [[nodiscard]] constexpr auto end() noexcept { return array.begin() + sz; }
72 [[nodiscard]] constexpr auto end() const noexcept { return array.begin() + sz; }
73 [[nodiscard]] constexpr auto rbegin() noexcept { return reverse_iterator(end()); }
74 [[nodiscard]] constexpr auto rbegin() const noexcept { return const_reverse_iterator(end()); }
75 [[nodiscard]] constexpr auto rend() noexcept { return reverse_iterator(begin()); }
76 [[nodiscard]] constexpr auto rend() const noexcept { return const_reverse_iterator(begin()); }
77
78 [[nodiscard]] constexpr size_t size() const noexcept { return sz; }
79 [[nodiscard]] constexpr size_t max_size() const noexcept { return array.max_size(); }
80 [[nodiscard]] constexpr bool empty() const noexcept { return sz == 0; }
81
82 [[nodiscard]] constexpr T& operator[](size_t index) noexcept { return array[index]; }
83 [[nodiscard]] constexpr const T& operator[](size_t index) const noexcept { return array[index]; }
84 [[nodiscard]] constexpr T& front() noexcept { assert(sz > 0); return array[0]; }
85 [[nodiscard]] constexpr const T& front() const noexcept { assert(sz > 0); return array[0]; }
86 [[nodiscard]] constexpr T& back() noexcept { assert(sz > 0); return array[sz - 1]; }
87 [[nodiscard]] constexpr const T& back() const noexcept { assert(sz > 0); return array[sz - 1]; }
88 [[nodiscard]] constexpr T* data() noexcept { return array.data(); }
89 [[nodiscard]] constexpr const T* data() const noexcept { return array.data(); }
90
91 constexpr void push_back(const T& a) { assert(sz < N); array[sz++] = a; }
92 constexpr void push_back(T&& a) { assert(sz < N); array[sz++] = std::move(a); }
93 template<typename... Args> constexpr T& emplace_back(Args&&... args) {
94 assert(sz < N);
95 array[sz++] = T(std::forward<Args>(args)...);
96 return array[sz - 1];
97 }
98 constexpr void pop_back() noexcept { assert(sz > 0); sz--; }
99 constexpr void clear() noexcept { sz = 0; }
100
101 operator std::span< T>() noexcept { return {array.data(), sz}; }
102 operator std::span<const T>() const noexcept { return {array.data(), sz}; }
103
104private:
105 std::array<T, N> array = {};
106 SizeType sz = 0;
107};
108
109#endif
value_type & reference
const value_type * const_iterator
constexpr auto rbegin() noexcept
constexpr T & operator[](size_t index) noexcept
constexpr size_t max_size() const noexcept
constexpr auto begin() const noexcept
ptrdiff_t difference_type
constexpr size_t size() const noexcept
constexpr void clear() noexcept
constexpr void pop_back() noexcept
constexpr static_vector(from_range_t, Range &&range)
constexpr T & front() noexcept
constexpr bool empty() const noexcept
constexpr static_vector(std::initializer_list< T > list)
std::reverse_iterator< iterator > reverse_iterator
constexpr static_vector()=default
constexpr void push_back(T &&a)
constexpr auto rend() const noexcept
constexpr auto rend() noexcept
constexpr T & back() noexcept
const value_type * const_pointer
constexpr const T & back() const noexcept
constexpr auto end() noexcept
constexpr T * data() noexcept
constexpr const T * data() const noexcept
constexpr auto begin() noexcept
constexpr auto end() const noexcept
constexpr auto rbegin() const noexcept
constexpr const T & front() const noexcept
value_type * pointer
constexpr T & emplace_back(Args &&... args)
const value_type & const_reference
constexpr const T & operator[](size_t index) const noexcept
value_type * iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
constexpr void push_back(const T &a)
constexpr auto copy(InputRange &&range, OutputIter out)
Definition ranges.hh:252
constexpr from_range_t from_range