22 using difference_type = sringbuffer_detail::difference_type;
23 using size_type = sringbuffer_detail::size_type;
30 sringbuffer_detail::size_type m_tail;
31 sringbuffer_detail::size_type m_size;
32 sringbuffer_detail::size_type m_index;
39 sringbuffer_detail::size_type tail,
41 sringbuffer_detail::size_type size,
43 sringbuffer_detail::size_type index): m_ptr(ptr), m_tail(tail), m_size(size), m_index(index) {}
45 T& operator*()
const {
46 return m_ptr[(m_tail + m_index) % N];
48 T* operator->()
const {
49 return &m_ptr[(m_tail + m_index) % N];
51 iterator operator[](size_type offset)
const {
52 return m_ptr[(m_tail + m_index + offset) % N];
55 iterator& operator+=(size_type diff) {
59 iterator& operator-=(size_type diff) {
81 iterator operator+(size_type offset)
const {
82 return {m_index + offset};
84 iterator operator-(size_type offset)
const {
85 return {m_index - offset};
87 difference_type operator-(
const iterator& other)
const {
88 GAIA_ASSERT(m_ptr == other.m_ptr);
89 return (difference_type)(m_index - other.m_index);
91 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
92 GAIA_ASSERT(m_ptr == other.m_ptr);
93 return m_index == other.m_index;
95 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
96 GAIA_ASSERT(m_ptr == other.m_ptr);
97 return m_index != other.m_index;
99 GAIA_NODISCARD
bool operator>(
const iterator& other)
const {
100 GAIA_ASSERT(m_ptr == other.m_ptr);
101 return m_index > other.m_index;
103 GAIA_NODISCARD
bool operator>=(
const iterator& other)
const {
104 GAIA_ASSERT(m_ptr == other.m_ptr);
105 return m_index >= other.m_index;
107 GAIA_NODISCARD
bool operator<(
const iterator& other)
const {
108 GAIA_ASSERT(m_ptr == other.m_ptr);
109 return m_index < other.m_index;
111 GAIA_NODISCARD
bool operator<=(
const iterator& other)
const {
112 GAIA_ASSERT(m_ptr == other.m_ptr);
113 return m_index <= other.m_index;
124 static_assert(N > 1);
126 using value_type = T;
127 using reference = T&;
128 using const_reference =
const T&;
130 using const_pointer =
const T*;
131 using difference_type = sringbuffer_detail::size_type;
132 using size_type = sringbuffer_detail::size_type;
138 static constexpr size_type extent = N;
146 template <
typename InputIt>
147 constexpr sringbuffer(InputIt first, InputIt last)
noexcept {
148 const auto count = (size_type)core::distance(first, last);
149 GAIA_ASSERT(count <= max_size());
156 if constexpr (std::is_pointer_v<InputIt>) {
157 for (size_type i = 0; i < count; ++i)
158 m_data[i] = first[i];
159 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
160 for (size_type i = 0; i < count; ++i)
161 m_data[i] = *(first[i]);
164 for (
auto it = first; it != last; ++it)
172 mem::copy_elements<T, false>(m_data, other.m_data, other.size(), 0, extent, other.extent);
176 mem::move_elements<T, false>(m_data, other.m_data, other.size(), 0, extent, other.extent);
178 other.m_tail = size_type(0);
179 other.m_size = size_type(0);
182 constexpr sringbuffer& operator=(std::initializer_list<T> il)
noexcept {
188 GAIA_ASSERT(core::addressof(other) !=
this);
190 mem::copy_elements<T, false>(&m_data[0], other.m_data, other.size(), 0, extent, other.extent);
192 m_tail = other.m_tail;
193 m_size = other.m_size;
199 GAIA_ASSERT(core::addressof(other) !=
this);
201 mem::move_elements<T, false>(m_data, other.m_data, other.size(), 0, extent, other.extent);
203 m_tail = other.m_tail;
204 m_size = other.m_size;
206 other.m_tail = size_type(0);
207 other.m_size = size_type(0);
214 constexpr void push_back(
const T& arg) {
215 GAIA_ASSERT(m_size < N);
216 const auto head = (m_tail + m_size) % N;
221 constexpr void push_back(T&& arg) {
222 GAIA_ASSERT(m_size < N);
223 const auto head = (m_tail + m_size) % N;
224 m_data[head] = GAIA_MOV(arg);
228 constexpr void pop_front(T& out) {
229 GAIA_ASSERT(!empty());
230 out = m_data[m_tail];
231 m_tail = (m_tail + 1) % N;
235 constexpr void pop_front(T&& out) {
236 GAIA_ASSERT(!empty());
237 out = GAIA_MOV(m_data[m_tail]);
238 m_tail = (m_tail + 1) % N;
242 constexpr void pop_back(T& out) {
243 GAIA_ASSERT(m_size < N);
244 const auto head = (m_tail + m_size - 1) % N;
249 constexpr void pop_back(T&& out) {
250 GAIA_ASSERT(m_size < N);
251 const auto head = (m_tail + m_size - 1) % N;
252 out = GAIA_MOV(m_data[head]);
256 GAIA_NODISCARD
constexpr size_type size()
const noexcept {
260 GAIA_NODISCARD
constexpr bool empty()
const noexcept {
264 GAIA_NODISCARD
constexpr size_type capacity()
const noexcept {
268 GAIA_NODISCARD
constexpr size_type max_size()
const noexcept {
272 GAIA_NODISCARD
constexpr reference front()
noexcept {
273 GAIA_ASSERT(!empty());
274 return m_data[m_tail];
277 GAIA_NODISCARD
constexpr const_reference front()
const noexcept {
278 GAIA_ASSERT(!empty());
279 return m_data[m_tail];
282 GAIA_NODISCARD
constexpr reference back()
noexcept {
283 GAIA_ASSERT(!empty());
284 const auto head = (m_tail + m_size - 1) % N;
288 GAIA_NODISCARD
constexpr const_reference back()
const noexcept {
289 GAIA_ASSERT(!empty());
290 const auto head = (m_tail + m_size - 1) % N;
294 GAIA_NODISCARD
constexpr auto begin()
noexcept {
295 return iterator((T*)&m_data[0], m_tail, m_size, 0);
298 GAIA_NODISCARD
constexpr auto begin()
const noexcept {
302 GAIA_NODISCARD
constexpr auto cbegin()
const noexcept {
306 GAIA_NODISCARD
constexpr auto end()
noexcept {
307 return iterator((T*)&m_data[0], m_tail, m_size, m_size);
310 GAIA_NODISCARD
constexpr auto end()
const noexcept {
314 GAIA_NODISCARD
constexpr auto cend()
const noexcept {
318 GAIA_NODISCARD
constexpr bool operator==(
const sringbuffer& other)
const {
319 for (size_type i = 0; i < N; ++i) {
320 if (m_data[i] == other.m_data[i])