49#include <gtest/gtest.h>
65 explicit Probe(
int v) :
value(v) { ++live; }
66 Probe(
const Probe &p) :
value(p.
value) { ++live; }
67 Probe(Probe &&p) noexcept :
value(p.value) { ++live; }
68 Probe &operator=(
const Probe &) =
default;
69 Probe &operator=(Probe &&) noexcept = default;
75struct CopyAssignableOnly
79 explicit CopyAssignableOnly(
int v) :
value(v) {}
80 CopyAssignableOnly(
const CopyAssignableOnly &) =
delete;
81 CopyAssignableOnly(CopyAssignableOnly &&) noexcept = default;
82 CopyAssignableOnly &operator=(const CopyAssignableOnly &) = default;
83 CopyAssignableOnly &operator=(CopyAssignableOnly &&) noexcept = default;
86static_assert(
std::is_copy_assignable_v<CopyAssignableOnly>);
87static_assert(not
std::is_copy_constructible_v<CopyAssignableOnly>);
89template <typename U, typename =
void>
90struct Has_Const_Put_Overwrite :
std::false_type
95struct Has_Const_Put_Overwrite
96 <U,
std::void_t<decltype(std::declval<RingBuffer<U> &>().put_overwrite
97 (std::declval<const U &>()))>> : std::true_type
101static_assert(not Has_Const_Put_Overwrite<CopyAssignableOnly>::value);
108 EXPECT_EQ(rb.
size(), 0u);
124 EXPECT_EQ(rb.
get(), 1);
125 EXPECT_EQ(rb.
get(), 2);
130 EXPECT_EQ(rb.
get(), 3);
131 EXPECT_EQ(rb.
get(), 4);
132 EXPECT_EQ(rb.
get(), 5);
141 EXPECT_THROW(rb.
put(3), std::overflow_error);
142 EXPECT_THROW(rb.
emplace(3), std::overflow_error);
146 EXPECT_THROW((
void) rb.
get(), std::underflow_error);
147 EXPECT_THROW((
void) rb.
get_first(), std::underflow_error);
148 EXPECT_THROW((
void) rb.
get_last(), std::underflow_error);
162 ASSERT_EQ(rb.
size(), 3u);
179 EXPECT_EQ(rb[0],
"b");
180 EXPECT_EQ(rb[1],
"c");
181 EXPECT_EQ(rb[2],
"d");
182 EXPECT_EQ(rb.
front(),
"b");
183 EXPECT_EQ(rb.
back(),
"d");
184 EXPECT_THROW((
void) rb[3], std::out_of_range);
193 for (
int i = 1; i <= 4; ++i)
200 std::deque<int> seen;
203 EXPECT_EQ(seen, (std::deque<int>{3, 4, 5, 6}));
206 auto it = rb.
begin();
207 EXPECT_EQ(rb.
end() - it, 4);
209 EXPECT_EQ(*(it + 3), 6);
210 auto tail = rb.
end();
213 EXPECT_EQ(tail[-2], 4);
214 auto mid = rb.
begin() + 1;
228 EXPECT_EQ(rb[0], 30);
229 EXPECT_EQ(rb[3], 60);
247 EXPECT_TRUE(rb.
traverse([&sum] (
int &x) { sum += x; return true; }));
252 EXPECT_FALSE(crb.
traverse([&visited] (
const int &x)
257 EXPECT_EQ(visited, 2);
263 rb.
put(std::make_unique<int>(1));
264 rb.
emplace(std::make_unique<int>(2));
267 std::unique_ptr<int> p = rb.
get();
272 ASSERT_EQ(rb.
size(), 2u);
273 EXPECT_EQ(*rb[0], 3);
274 EXPECT_EQ(*rb[1], 4);
279 ASSERT_EQ(Probe::live, 0);
282 EXPECT_EQ(Probe::live, 0);
286 EXPECT_EQ(Probe::live, 3);
288 EXPECT_EQ(Probe::live, 2);
291 EXPECT_EQ(Probe::live, 3);
293 EXPECT_EQ(Probe::live, 0);
296 EXPECT_EQ(Probe::live, 0);
310 EXPECT_EQ(copy.capacity(), rb.
capacity());
311 EXPECT_EQ(copy.get(), 2);
312 EXPECT_EQ(rb.
size(), 3u);
315 ASSERT_EQ(moved.
size(), 3u);
316 EXPECT_EQ(moved[0], 2);
317 EXPECT_EQ(moved[2], 4);
322 EXPECT_EQ(assigned, moved);
355 std::mt19937
rng(20260702);
356 std::uniform_int_distribution<int> val_dist(0, 1000000);
357 std::uniform_int_distribution<int> op_dist(0, 3);
358 constexpr size_t cap = 8;
363 for (
int step = 0; step < 4000; ++step)
365 const int v = val_dist(
rng);
366 switch (op_dist(
rng))
369 if (ref.size() < cap)
375 EXPECT_THROW(rb.
put(v), std::overflow_error);
380 if (ref.size() > cap)
385 EXPECT_THROW((
void) rb.
get(), std::underflow_error);
388 EXPECT_EQ(rb.
get(), ref.front());
393 ASSERT_EQ(rb.
size(), ref.size());
394 for (
size_t i = 0; i < ref.size(); ++i)
395 EXPECT_EQ(rb[i], ref[i]);
size_t size_t int32_t value
Fixed-capacity circular FIFO buffer over contiguous storage.
void empty() noexcept
Destroy all elements (Aleph convention).
T & front()
Oldest element (checked). Alias of get_first().
size_t size() const noexcept
Return the number of stored elements. O(1).
iterator begin() noexcept
Iterator on the oldest element. O(1).
T & emplace(Args &&...args)
Construct an element in place at the tail.
T & put(const T &item)
Append a copy of item at the tail.
bool is_empty() const noexcept
Return true if no elements are stored. O(1).
T & get_last()
Newest element — the last one inserted (checked).
void clear() noexcept
Destroy all elements. Alias of empty(). Capacity is kept.
T & get_first()
Oldest element — the next to leave (checked).
bool is_full() const noexcept
Return true if the buffer holds capacity() elements. O(1).
iterator end() noexcept
Iterator past the newest element. O(1).
T & back()
Newest element (checked). Alias of get_last().
T get()
Extract the oldest element from the head.
bool traverse(Operation operation)
Traverse from oldest to newest while operation returns true.
size_t capacity() const noexcept
Return the fixed capacity chosen at construction. O(1).
bool put_overwrite(const T &item)
Append at the tail, evicting the oldest element when full.
size_t available() const noexcept
Return the number of free slots. O(1).
Bounded circular buffer (Aleph::RingBuffer) for FIFO streaming.