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