FE 0.6.0
A header-only C++ library for writing frontends
Loading...
Searching...
No Matches
ring.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4
5#include <algorithm>
6#include <array>
7#include <initializer_list>
8
9#include <fe/assert.h>
10
11namespace fe {
12
13/// A ring buffer with @p N elements.
14template<class T, size_t N>
15class Ring {
16public:
17 /// @name Construction
18 ///@{
19 Ring(std::initializer_list<T> list) { std::copy(list.begin(), list.end(), array_); }
20 Ring() noexcept = default;
21 Ring(const Ring&) = default;
22 Ring(Ring&& other) noexcept
23 : Ring() {
24 swap(*this, other);
25 }
26 Ring& operator=(Ring other) noexcept { return swap(*this, other), *this; }
27 ///@}
28
29 /// @name Access
30 ///@{
31 T& front() { return array_[first_]; }
32 const T& front() const { return array_[first_]; }
33 T& operator[](size_t i) {
34 assert(i < N);
35 return array_[(first_ + i) % N];
36 }
37 const T& operator[](size_t i) const {
38 assert(i < N);
39 return array_[(first_ + i) % N];
40 }
41 ///@}
42
43 /// @name Modifiers
44 ///@{
45 void reset() { first_ = 0; }
46
47 /// Puts @p item into buffer.
48 /// @returns item that falls out.
49 T put(T item) {
50 auto res = array_[first_];
51 array_[first_] = item;
52 first_ = (first_ + 1) % N;
53 return res;
54 }
55 ///@}
56
57 friend void swap(Ring& r1, Ring& r2) noexcept {
58 using std::swap;
59 swap(r1.array_, r2.array_);
60 swap(r1.first_, r2.first_);
61 }
62
63private:
64 std::array<T, N> array_;
65 size_t first_ = 0;
66};
67
68/// Specialization if `N == 1` - doesn't need a ring.
69template<class T>
70class Ring<T, 1> {
71public:
72 /// @name Construction
73 ///@{
74 Ring(std::initializer_list<T> list)
75 : item_(*list.begin()) {}
76 Ring() = default; // no noexcept: we don't know whether T's default constructor throws
77 Ring(const Ring&) = default;
78 Ring(Ring&& other)
79 : Ring() {
80 swap(*this, other);
81 }
82 Ring& operator=(Ring other) noexcept { return swap(*this, other), *this; }
83 ///@}
84
85 /// @name Access
86 ///@{
87 T& front() { return item_; }
88 const T& front() const { return item_; }
89 T& operator[](size_t i) {
90 assert_unused(i == 0);
91 return item_;
92 }
93 const T& operator[](size_t i) const {
94 assert_unused(i == 0);
95 return item_;
96 }
97 ///@}
98
99 /// @name Modifiers
100 ///@{
101 void reset() {}
102 T put(T item) {
103 auto res = item_;
104 item_ = item;
105 return res;
106 }
107 ///@}
108
109 friend void swap(Ring& r1, Ring& r2) noexcept {
110 using std::swap;
111 swap(r1.item_, r2.item_);
112 }
113
114private:
115 T item_;
116};
117
118/// Specialization if `N == 2`; doesn't need a ring, we just copy.
119template<class T>
120class Ring<T, 2> {
121public:
122 /// @name Construction
123 ///@{
124 Ring(std::initializer_list<T> list) { std::copy(list.begin(), list.end(), array_); }
125 Ring() noexcept = default;
126 Ring(const Ring&) = default;
127 Ring(Ring&& other) noexcept
128 : Ring() {
129 swap(*this, other);
130 }
131 Ring& operator=(Ring other) noexcept { return swap(*this, other), *this; }
132 ///@}
133
134 /// @name Access
135 ///@{
136 T& front() { return array_[0]; }
137 const T& front() const { return array_[0]; }
138 T& operator[](size_t i) {
139 assert_unused(i < 2);
140 return array_[i];
141 }
142 const T& operator[](size_t i) const {
143 assert_unused(i < 2);
144 return array_[i];
145 }
146 ///@}
147
148 /// @name Modifiers
149 ///@{
150 void reset() {}
151 T put(T item) {
152 auto res = array_[0];
153 array_[0] = array_[1];
154 array_[1] = item;
155 return res;
156 }
157 ///@}
158
159 friend void swap(Ring& r1, Ring& r2) noexcept {
160 using std::swap;
161 swap(r1.array_, r2.array_);
162 }
163
164private:
165 std::array<T, 2> array_;
166};
167
168} // namespace fe
#define assert_unused(x)
Definition assert.h:35
const T & front() const
Definition ring.h:88
Ring & operator=(Ring other) noexcept
Definition ring.h:82
Ring(const Ring &)=default
const T & operator[](size_t i) const
Definition ring.h:93
Ring(Ring &&other)
Definition ring.h:78
T & operator[](size_t i)
Definition ring.h:89
T put(T item)
Definition ring.h:102
T & front()
Definition ring.h:87
friend void swap(Ring &r1, Ring &r2) noexcept
Definition ring.h:109
Ring(std::initializer_list< T > list)
Definition ring.h:74
void reset()
Definition ring.h:101
T & front()
Definition ring.h:136
const T & front() const
Definition ring.h:137
const T & operator[](size_t i) const
Definition ring.h:142
Ring & operator=(Ring other) noexcept
Definition ring.h:131
Ring() noexcept=default
friend void swap(Ring &r1, Ring &r2) noexcept
Definition ring.h:159
void reset()
Definition ring.h:150
T & operator[](size_t i)
Definition ring.h:138
T put(T item)
Definition ring.h:151
Ring(std::initializer_list< T > list)
Definition ring.h:124
A ring buffer with N elements.
Definition ring.h:15
void reset()
Definition ring.h:45
Ring & operator=(Ring other) noexcept
Definition ring.h:26
const T & operator[](size_t i) const
Definition ring.h:37
Ring() noexcept=default
T put(T item)
Puts item into buffer.
Definition ring.h:49
friend void swap(Ring &r1, Ring &r2) noexcept
Definition ring.h:57
Ring(std::initializer_list< T > list)
Definition ring.h:19
T & front()
Definition ring.h:31
const T & front() const
Definition ring.h:32
T & operator[](size_t i)
Definition ring.h:33
Definition arena.h:10