openMSX
inplace_buffer.hh
Go to the documentation of this file.
1#ifndef INPLACE_BUFFER_HH
2#define INPLACE_BUFFER_HH
3
4#include "ranges.hh"
5#include "stl.hh"
6
7#include <algorithm>
8#include <array>
9#include <cassert>
10#include <cstdint>
11#include <iterator>
12#include <limits>
13#include <span>
14#include <type_traits>
15
16// A run-time-sized buffer of (possibly) uninitialized data with a known
17// upper-bound for the size.
18
19// Typically objects of this type are used as local variables. Not as member
20// variables of a larger class.
21
22// This class is similar to 'static_vector<T, N>' (new name will be
23// 'inplace_vector'). Except that this one leaves the initial content
24// uninitialized.
25
26// If you're unsure about the upper-bound for the size, or if that upper-bound
27// is only rarely needed, then consider using 'small_uninitialized_buffer'.
28
29template<typename T, size_t BUF_SIZE>
31{
32 static_assert(std::is_trivially_constructible_v<T>);
33
34 using SizeType =
35 std::conditional_t<BUF_SIZE <= std::numeric_limits<uint8_t >::max(), uint8_t,
36 std::conditional_t<BUF_SIZE <= std::numeric_limits<uint16_t>::max(), uint16_t,
37 std::conditional_t<BUF_SIZE <= std::numeric_limits<uint32_t>::max(), uint32_t,
38 uint64_t>>>;
39
40public:
41 explicit inplace_buffer(uninitialized_tag, size_t size) : sz(SizeType(size))
42 {
43 assert(size <= BUF_SIZE);
44 }
45
46 explicit inplace_buffer(size_t size, const T& t)
48 {
49 ranges::fill(std::span{buffer.data(), sz}, t);
50 }
51
52 template<typename Range>
53 explicit inplace_buffer(const Range& range)
54 : inplace_buffer(uninitialized_tag{}, std::distance(std::begin(range), std::end(range)))
55 {
56 std::copy(std::begin(range), std::end(range), begin());
57 }
58
59 [[nodiscard]] explicit(false) operator std::span<T>() noexcept {
60 return {buffer.data(), sz};
61 }
62
63 [[nodiscard]] size_t size() const noexcept { return sz; }
64 [[nodiscard]] bool empty() const noexcept { return sz == 0; }
65 [[nodiscard]] T* data() noexcept { return buffer.data(); }
66 [[nodiscard]] auto begin() noexcept { return buffer.begin(); }
67 [[nodiscard]] auto end() noexcept { return buffer.begin() + sz; }
68
69 [[nodiscard]] T& operator[](size_t index) {
70 assert(index < sz);
71 return buffer[index];
72 }
73 [[nodiscard]] T& front() {
74 assert(!empty());
75 return buffer.front();
76 }
77 [[nodiscard]] T& back() {
78 assert(!empty());
79 return buffer[sz - 1];
80 }
81
82private:
83 std::array<T, BUF_SIZE> buffer;
84 SizeType sz;
85};
86
87#endif
TclObject t
inplace_buffer(size_t size, const T &t)
inplace_buffer(const Range &range)
inplace_buffer(uninitialized_tag, size_t size)
constexpr void fill(ForwardRange &&range, const T &value)
Definition ranges.hh:315
STL namespace.
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)