My Project
floating_array.h
1 #ifndef FLOATING_ARRAY_H_INCLUDED_
2 #define FLOATING_ARRAY_H_INCLUDED_
3 
4 #include <cstddef>
5 #include <deque>
6 #include <iterator>
7 
8 struct origin_tag {
9  std::ptrdiff_t value = 0;
10  explicit operator ptrdiff_t() const { return value; }
11 };
12 
13 template <typename I>
14 using is_input_iterator =
15  std::is_convertible<std::input_iterator_tag,
16  typename std::iterator_traits<I>::iterator_category>;
17 template <typename I>
18 constexpr bool is_input_iterator_v = is_input_iterator<I>::value;
19 
20 template <typename T, typename Allocator = std::allocator<T>>
21 class floating_array : private std::deque<T, Allocator> {
22  private:
23  using BC = std::deque<T, Allocator>;
24 
25  public:
26  /* Boilerplate stuff */
27  using value_type = typename BC::value_type;
28  using allocator_type = typename BC::allocator_type;
29  using size_type = typename BC::size_type;
30  using index_type = std::ptrdiff_t;
31  using difference_type = typename BC::difference_type;
32  using reference = typename BC::reference;
33  using const_reference = typename BC::const_reference;
34  using pointer = typename BC::pointer;
35  using const_pointer = typename BC::const_pointer;
36  using iterator = typename BC::iterator;
37  using const_iterator = typename BC::const_iterator;
38  using reverse_iterator = typename BC::reverse_iterator;
39  using const_reverse_iterator = typename BC::const_reverse_iterator;
40 
41  floating_array() = default;
42  explicit floating_array(const Allocator& alloc) : BC(alloc) {}
43  floating_array(size_type count, const T& value = T(),
44  const Allocator& alloc = Allocator())
45  : BC(count, value, alloc) {}
46  explicit floating_array(size_type count,
47  const Allocator& alloc = Allocator())
48  : BC(count, alloc) {}
49  template <typename InputIt,
50  typename = std::enable_if_t<is_input_iterator_v<InputIt>>>
51  floating_array(InputIt first, InputIt last,
52  const Allocator& alloc = Allocator())
53  : BC(first, last, alloc) {}
54  floating_array(const floating_array& other) = default;
55  floating_array(const floating_array& other, const Allocator& alloc)
56  : BC(static_cast<const BC&>(other), alloc), offset(other.offset) {}
57  floating_array(floating_array&& other) noexcept = default;
58  floating_array(floating_array&& other, const Allocator& alloc) noexcept(
59  noexcept(BC(static_cast<BC&&>(other), alloc)))
60  : BC(static_cast<BC&&>(other), alloc), offset(other.offset) {}
61  floating_array(std::initializer_list<T> init,
62  const Allocator& alloc = Allocator())
63  : BC(init, alloc) {}
64 
65  explicit floating_array(origin_tag o, const Allocator& alloc = Allocator())
66  : BC(alloc), offset(o) {}
67  floating_array(origin_tag o, size_type count, const T& value = T(),
68  const Allocator& alloc = Allocator())
69  : BC(count, value, alloc), offset(o) {}
70  template <typename InputIt,
71  typename = std::enable_if_t<is_input_iterator_v<InputIt>>>
72  floating_array(origin_tag o, InputIt first, InputIt last,
73  const Allocator& alloc = Allocator())
74  : BC(first, last, alloc), offset(o) {}
75  floating_array(origin_tag o, std::initializer_list<T> init,
76  const Allocator& alloc = Allocator())
77  : BC(init, alloc), offset(o) {}
78 
79  floating_array& operator=(const floating_array& other) = default;
80  floating_array& operator=(floating_array&& other) noexcept(
81  std::allocator_traits<Allocator>::is_always_equal::value) = default;
82  floating_array& operator=(std::initializer_list<T> ilist) {
83  BC::operator=(ilist);
84  offset = 0;
85  return *this;
86  }
87 
88  void assign(size_type count, const T& value) {
89  BC::assign(count, value);
90  offset = 0;
91  }
92  template <typename InputIt,
93  typename = std::enable_if_t<is_input_iterator_v<InputIt>>>
94  void assign(InputIt first, InputIt last) {
95  BC::assign(first, last);
96  offset = 0;
97  }
98  void assign(std::initializer_list<T> ilist) {
99  BC::assign(ilist);
100  offset = 0;
101  return *this;
102  }
103 
104  void assign(origin_tag o, size_type count, const T& value) {
105  BC::assign(count, value);
106  offset = o.value;
107  }
108  template <typename InputIt,
109  typename = std::enable_if_t<is_input_iterator_v<InputIt>>>
110  void assign(origin_tag o, InputIt first, InputIt last) {
111  BC::assign(first, last);
112  offset = o.value;
113  }
114  void assign(origin_tag o, std::initializer_list<T> ilist) {
115  BC::assign(ilist);
116  offset = o.value;
117  return *this;
118  }
119 
120  using BC::get_allocator;
121 
122  reference at(index_type i) { return BC::at(i - offset); }
123  const_reference at(index_type i) const { return BC::at(i - offset); }
124  reference operator[](index_type i) { return BC::operator[](i - offset); }
125  const_reference operator[](index_type i) const {
126  return BC::operator[](i - offset);
127  }
128 
129  using BC::back;
130  using BC::front;
131 
132  using BC::begin;
133  using BC::cbegin;
134  using BC::cend;
135  using BC::crbegin;
136  using BC::crend;
137  using BC::end;
138  using BC::rbegin;
139  using BC::rend;
140 
141  // If the range spans zero, returns an iterator to [0].
142  // Otherwise, returns end()
143  iterator zero() {
144  if (low() < 0 && high() > 0) {
145  return begin() - low();
146  }
147  return end();
148  }
149  const_iterator zero() const {
150  if (low() < 0 && high() > 0) {
151  return begin() - low();
152  }
153  return end();
154  }
155 
156  const_iterator czero() const { return zero(); }
157  reverse_iterator rzero() { return reverse_iterator(zero()); }
158  const_reverse_iterator rzero() const {
159  return const_reverse_iterator(zero());
160  }
161  const_reverse_iterator crzero() const { return rzero(); }
162 
163  using BC::empty;
164  using BC::max_size;
165  using BC::shrink_to_fit;
166  using BC::size;
167 
168  index_type high() const { return size() + offset; }
169  index_type low() const { return offset; }
170 
171  void clear() noexcept {
172  BC::clear();
173  offset = 0;
174  }
175 
176  // no insert, emplace, or erase
177 
178  using BC::emplace_back;
179  using BC::pop_back;
180  using BC::push_back;
181 
182  void push_front(const T& value) {
183  BC::push_front(value);
184  --offset;
185  }
186  void push_front(T&& value) {
187  BC::push_front(value);
188  --offset;
189  }
190 
191  template <typename... Args>
192  reference emplace_front(Args&&... args) {
193  BC::emplace_front(std::forward<Args>(args)...);
194  --offset;
195  }
196 
197  void pop_front() {
198  BC::pop_front();
199  ++offset;
200  }
201 
202  void swap(floating_array& other) noexcept(
203  std::allocator_traits<Allocator>::is_always_equal::value) {
204  using std::swap;
205  swap(static_cast<BC&>(*this), static_cast<BC&>(other));
206  swap(offset, other.offset);
207  }
208 
209  friend bool operator==(const floating_array&, const floating_array&);
210 
211  ~floating_array() = default;
212 
213  private:
214  difference_type offset{0};
215 };
216 
217 template <typename T, typename Alloc>
218 bool operator==(const floating_array<T, Alloc>& lhs,
219  const floating_array<T, Alloc>& rhs) {
220  return (lhs.low() == rhs.low()) &&
221  (static_cast<std::deque<T, Alloc>&>(lhs) ==
222  static_cast<std::deque<T, Alloc>&>(rhs));
223 }
224 
225 template <typename T, typename Alloc>
226 bool operator!=(const floating_array<T, Alloc>& lhs,
227  const floating_array<T, Alloc>& rhs) {
228  return !(lhs == rhs);
229 }
230 
231 template <typename T, typename Alloc>
232 bool operator<(const floating_array<T, Alloc>& lhs,
233  const floating_array<T, Alloc>& rhs) {
234  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
235  rhs.end());
236 }
237 
238 template <typename T, typename Alloc>
239 bool operator<=(const floating_array<T, Alloc>& lhs,
240  const floating_array<T, Alloc>& rhs) {
241  return (lhs == rhs) || std::lexicographical_compare(lhs.begin(), lhs.end(),
242  rhs.begin(), rhs.end());
243 }
244 
245 template <typename T, typename Alloc>
246 bool operator>(const floating_array<T, Alloc>& lhs,
247  const floating_array<T, Alloc>& rhs) {
248  return std::lexicographical_compare(rhs.begin(), rhs.end(), lhs.begin(),
249  lhs.end());
250 }
251 
252 template <typename T, typename Alloc>
253 bool operator>=(const floating_array<T, Alloc>& lhs,
254  const floating_array<T, Alloc>& rhs) {
255  return (lhs == rhs) || std::lexicographical_compare(rhs.begin(), rhs.end(),
256  lhs.begin(), lhs.end());
257 }
258 
259 template <typename T, typename Alloc>
261  lhs.swap(rhs);
262 }
263 
264 #endif // FLOATING_ARRAY_H_INCLUDED_
Definition: floating_array.h:8
Definition: floating_array.h:21