Zserio C++ runtime library  1.3.0
Built for Zserio 2.18.0
Span.h
Go to the documentation of this file.
1 #ifndef ZSERIO_SPAN_H_INC
2 #define ZSERIO_SPAN_H_INC
3 
4 #include <array>
5 #include <cstddef>
6 #include <iterator>
7 #include <limits>
8 #include <type_traits>
9 #include <vector>
10 
11 #include "zserio/Types.h"
12 
13 namespace zserio
14 {
15 
19 constexpr size_t dynamic_extent = std::numeric_limits<size_t>::max();
20 
21 namespace detail
22 {
23 
24 template <typename T, size_t Extent>
25 struct SpanStorage
26 {
27  SpanStorage() = default;
28 
29  SpanStorage(T* data, size_t) :
30  m_data(data)
31  {}
32 
33  T* m_data = nullptr;
34  static constexpr size_t m_size = Extent;
35 };
36 
37 template <typename T>
38 struct SpanStorage<T, dynamic_extent>
39 {
40  SpanStorage() = default;
41 
42  SpanStorage(T* data, size_t size) :
43  m_data(data),
44  m_size(size)
45  {}
46 
47  T* m_data = nullptr;
48  size_t m_size = 0;
49 };
50 
51 } // namespace detail
52 
59 template <typename T, size_t Extent = dynamic_extent>
60 class Span
61 {
62 public:
63  using element_type = T;
64  using value_type = typename std::remove_cv<T>::type;
65  using size_type = size_t;
66  using difference_type = std::ptrdiff_t;
67  using pointer = T*;
68  using const_pointer = const T*;
69  using reference = T&;
70  using iterator = pointer;
72  using reverse_iterator = std::reverse_iterator<iterator>;
73  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
74 
75  static constexpr size_type extent = Extent;
76 
80  template <size_type ext = Extent,
81  typename std::enable_if<(ext == 0 || ext == dynamic_extent), int>::type = 0>
82  constexpr Span() noexcept
83  {}
84 
92  constexpr Span(pointer first_, size_type count) :
93  m_storage(first_, count)
94  {}
95 
103  constexpr Span(pointer first_, pointer last_) :
104  m_storage(first_, static_cast<size_t>(last_ - first_))
105  {}
106 
112  template <size_type N, size_type ext = Extent,
113  typename std::enable_if<(ext == dynamic_extent || ext == N), int>::type = 0>
114  constexpr Span(element_type (&arr)[N]) noexcept :
115  m_storage(arr, N)
116  {}
117 
123  template <typename U, size_type N, size_type ext = Extent,
124  typename std::enable_if<(ext == dynamic_extent || ext == N) &&
125  std::is_convertible<U (*)[], T (*)[]>::value,
126  int>::type = 0>
127  constexpr Span(std::array<U, N>& arr) noexcept :
128  m_storage(arr.data(), arr.size())
129  {}
130 
136  template <typename U, size_type N, size_type ext = Extent,
137  typename std::enable_if<(ext == dynamic_extent || ext == N) &&
138  std::is_convertible<const U (*)[], T (*)[]>::value,
139  int>::type = 0>
140  constexpr Span(const std::array<U, N>& arr) noexcept :
141  m_storage(arr.data(), arr.size())
142  {}
143 
149  template <typename U, typename ALLOC, size_type ext = Extent,
150  typename std::enable_if<(ext == dynamic_extent) && std::is_convertible<U (*)[], T (*)[]>::value,
151  int>::type = 0>
152  constexpr Span(std::vector<U, ALLOC>& vec) :
153  m_storage(vec.data(), vec.size())
154  {}
155 
161  template <typename U, typename ALLOC, size_type ext = Extent,
162  typename std::enable_if<
163  (ext == dynamic_extent) && std::is_convertible<const U (*)[], T (*)[]>::value, int>::type =
164  0>
165  constexpr Span(const std::vector<U, ALLOC>& vec) :
166  m_storage(vec.data(), vec.size())
167  {}
168 
174  template <typename U, size_type N,
175  typename std::enable_if<(Extent == N || Extent == dynamic_extent) &&
176  std::is_convertible<U (*)[], T (*)[]>::value,
177  int>::type = 0>
178  constexpr Span(const Span<U, N>& span) noexcept :
179  m_storage(span.data(), span.size())
180  {}
181 
186  ~Span() = default;
187 
188  Span(const Span& other) noexcept = default;
189  Span& operator=(const Span& other) noexcept = default;
190 
191  Span(Span&& other) noexcept = default;
192  Span& operator=(Span&& other) noexcept = default;
202  constexpr iterator begin() const noexcept
203  {
204  return data();
205  }
206 
212  constexpr iterator end() const noexcept
213  {
214  return data() + size();
215  }
216 
222  constexpr reverse_iterator rbegin() const noexcept
223  {
224  return reverse_iterator(end());
225  }
226 
232  constexpr reverse_iterator rend() const noexcept
233  {
234  return reverse_iterator(begin());
235  }
236 
242  constexpr reference front() const
243  {
244  return data()[0];
245  }
246 
252  constexpr reference back() const
253  {
254  return data()[size() - 1];
255  }
256 
263  constexpr reference operator[](size_type idx) const
264  {
265  return data()[idx];
266  }
267 
273  constexpr pointer data() const noexcept
274  {
275  return m_storage.m_data;
276  }
277 
283  constexpr size_type size() const noexcept
284  {
285  return m_storage.m_size;
286  }
287 
293  constexpr size_type size_bytes() const noexcept
294  {
295  return size() * sizeof(element_type);
296  }
297 
303  constexpr bool empty() const noexcept
304  {
305  return size() == 0;
306  }
307 
313  template <size_type Count>
315  {
316  static_assert(Count <= Extent, "Requested number of characters out of range.");
317  return Span<element_type, Count>(data(), Count);
318  }
319 
327  {
328  return Span<element_type, dynamic_extent>(data(), Count);
329  }
330 
336  template <size_type Count>
337  constexpr Span<element_type, Count> last() const
338  {
339  static_assert(Count <= Extent, "Requested number of characters out of range.");
340  return Span<element_type, Count>(data() + (size() - Count), Count);
341  }
342 
350  {
351  return Span<element_type, dynamic_extent>(data() + (size() - Count), Count);
352  }
353 
354  template <size_type Offset, size_type Count>
356  Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : dynamic_extent)>;
357 
364  template <size_type Offset, size_type Count = dynamic_extent,
365  typename std::enable_if<Count == dynamic_extent, int>::type = 0>
367  {
368  static_assert((Extent == dynamic_extent) || (Offset <= Extent),
369  "Requested number of characters out of range.");
370  return SubspanReturnType<Offset, Count>(data() + Offset, size() - Offset);
371  }
372 
373  template <size_type Offset, size_type Count,
374  typename std::enable_if<Count != dynamic_extent, int>::type = 0>
376  {
377  static_assert((Extent == dynamic_extent) || (Offset <= Extent && Offset + Count <= Extent),
378  "Requested number of characters out of range.");
379  return SubspanReturnType<Offset, Count>(data() + Offset, Count);
380  }
391  size_type Offset, size_type Count = dynamic_extent) const
392  {
394  data() + Offset, Count == dynamic_extent ? size() - Offset : Count);
395  }
396 
397 private:
398  detail::SpanStorage<T, Extent> m_storage;
399 };
400 
401 } // namespace zserio
402 
403 #endif // ZSERIO_SPAN_H_INC
constexpr Span(pointer first_, size_type count)
Definition: Span.h:92
constexpr bool empty() const noexcept
Definition: Span.h:303
const T * const_pointer
Definition: Span.h:68
pointer iterator
Definition: Span.h:70
Span & operator=(Span &&other) noexcept=default
constexpr reference front() const
Definition: Span.h:242
constexpr Span() noexcept
Definition: Span.h:82
Span(const Span &other) noexcept=default
constexpr size_type size() const noexcept
Definition: Span.h:283
constexpr Span< element_type, dynamic_extent > last(size_type Count) const
Definition: Span.h:349
static constexpr size_type extent
Definition: Span.h:75
constexpr Span(const Span< U, N > &span) noexcept
Definition: Span.h:178
constexpr Span< element_type, Count > last() const
Definition: Span.h:337
constexpr Span(pointer first_, pointer last_)
Definition: Span.h:103
constexpr reverse_iterator rbegin() const noexcept
Definition: Span.h:222
std::ptrdiff_t difference_type
Definition: Span.h:66
T element_type
Definition: Span.h:63
constexpr reverse_iterator rend() const noexcept
Definition: Span.h:232
const_pointer const_iterator
Definition: Span.h:71
~Span()=default
constexpr Span< element_type, dynamic_extent > subspan(size_type Offset, size_type Count=dynamic_extent) const
Definition: Span.h:390
typename std::remove_cv< T >::type value_type
Definition: Span.h:64
constexpr reference back() const
Definition: Span.h:252
constexpr Span(const std::vector< U, ALLOC > &vec)
Definition: Span.h:165
constexpr pointer data() const noexcept
Definition: Span.h:273
T * pointer
Definition: Span.h:67
constexpr SubspanReturnType< Offset, Count > subspan() const
Definition: Span.h:366
std::reverse_iterator< iterator > reverse_iterator
Definition: Span.h:72
T & reference
Definition: Span.h:69
size_t size_type
Definition: Span.h:65
Span(Span &&other) noexcept=default
constexpr size_type size_bytes() const noexcept
Definition: Span.h:293
constexpr Span(const std::array< U, N > &arr) noexcept
Definition: Span.h:140
constexpr reference operator[](size_type idx) const
Definition: Span.h:263
constexpr Span< element_type, Count > first() const
Definition: Span.h:314
constexpr Span< element_type, dynamic_extent > first(size_type Count) const
Definition: Span.h:326
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Span.h:73
constexpr Span(std::array< U, N > &arr) noexcept
Definition: Span.h:127
Span & operator=(const Span &other) noexcept=default
constexpr Span(element_type(&arr)[N]) noexcept
Definition: Span.h:114
constexpr Span(std::vector< U, ALLOC > &vec)
Definition: Span.h:152
constexpr iterator end() const noexcept
Definition: Span.h:212
constexpr iterator begin() const noexcept
Definition: Span.h:202
constexpr size_t dynamic_extent
Definition: Span.h:19