Zserio C++ runtime library  1.1.0
Built for Zserio 2.15.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 namespace zserio
12 {
13 
17 constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
18 
19 namespace detail
20 {
21 
22 template <typename T, std::size_t Extent>
23 struct SpanStorage
24 {
25  SpanStorage() = default;
26 
27  SpanStorage(T* data, std::size_t) :
28  m_data(data)
29  {}
30 
31  T* m_data = nullptr;
32  static constexpr std::size_t m_size = Extent;
33 };
34 
35 template <typename T>
36 struct SpanStorage<T, dynamic_extent>
37 {
38  SpanStorage() = default;
39 
40  SpanStorage(T* data, std::size_t size) :
41  m_data(data),
42  m_size(size)
43  {}
44 
45  T* m_data = nullptr;
46  std::size_t m_size = 0;
47 };
48 
49 } // namespace detail
50 
57 template <typename T, std::size_t Extent = dynamic_extent>
58 class Span
59 {
60 public:
61  using element_type = T;
62  using value_type = typename std::remove_cv<T>::type;
63  using size_type = std::size_t;
64  using difference_type = std::ptrdiff_t;
65  using pointer = T*;
66  using const_pointer = const T*;
67  using reference = T&;
68  using iterator = pointer;
70  using reverse_iterator = std::reverse_iterator<iterator>;
71  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
72 
73  static constexpr size_type extent = Extent;
74 
78  template <size_type ext = Extent,
79  typename std::enable_if<(ext == 0 || ext == dynamic_extent), int>::type = 0>
80  constexpr Span() noexcept
81  {}
82 
90  constexpr Span(pointer first_, size_type count) :
91  m_storage(first_, count)
92  {}
93 
101  constexpr Span(pointer first_, pointer last_) :
102  m_storage(first_, static_cast<size_t>(last_ - first_))
103  {}
104 
110  template <size_type N, size_type ext = Extent,
111  typename std::enable_if<(ext == dynamic_extent || ext == N), int>::type = 0>
112  constexpr Span(element_type (&arr)[N]) noexcept :
113  m_storage(arr, N)
114  {}
115 
121  template <typename U, size_type N, size_type ext = Extent,
122  typename std::enable_if<(ext == dynamic_extent || ext == N) &&
123  std::is_convertible<U (*)[], T (*)[]>::value,
124  int>::type = 0>
125  constexpr Span(std::array<U, N>& arr) noexcept :
126  m_storage(arr.data(), arr.size())
127  {}
128 
134  template <typename U, size_type N, size_type ext = Extent,
135  typename std::enable_if<(ext == dynamic_extent || ext == N) &&
136  std::is_convertible<const U (*)[], T (*)[]>::value,
137  int>::type = 0>
138  constexpr Span(const std::array<U, N>& arr) noexcept :
139  m_storage(arr.data(), arr.size())
140  {}
141 
147  template <typename U, typename ALLOC, size_type ext = Extent,
148  typename std::enable_if<(ext == dynamic_extent) && std::is_convertible<U (*)[], T (*)[]>::value,
149  int>::type = 0>
150  constexpr Span(std::vector<U, ALLOC>& vec) :
151  m_storage(vec.data(), vec.size())
152  {}
153 
159  template <typename U, typename ALLOC, size_type ext = Extent,
160  typename std::enable_if<
161  (ext == dynamic_extent) && std::is_convertible<const U (*)[], T (*)[]>::value, int>::type =
162  0>
163  constexpr Span(const std::vector<U, ALLOC>& vec) :
164  m_storage(vec.data(), vec.size())
165  {}
166 
172  template <typename U, size_type N,
173  typename std::enable_if<(Extent == N || Extent == dynamic_extent) &&
174  std::is_convertible<U (*)[], T (*)[]>::value,
175  int>::type = 0>
176  constexpr Span(const Span<U, N>& span) noexcept :
177  m_storage(span.data(), span.size())
178  {}
179 
184  ~Span() = default;
185 
186  Span(const Span& other) noexcept = default;
187  Span& operator=(const Span& other) noexcept = default;
188 
189  Span(Span&& other) noexcept = default;
190  Span& operator=(Span&& other) noexcept = default;
200  constexpr iterator begin() const noexcept
201  {
202  return data();
203  }
204 
210  constexpr iterator end() const noexcept
211  {
212  return data() + size();
213  }
214 
220  constexpr reverse_iterator rbegin() const noexcept
221  {
222  return reverse_iterator(end());
223  }
224 
230  constexpr reverse_iterator rend() const noexcept
231  {
232  return reverse_iterator(begin());
233  }
234 
240  constexpr reference front() const
241  {
242  return data()[0];
243  }
244 
250  constexpr reference back() const
251  {
252  return data()[size() - 1];
253  }
254 
261  constexpr reference operator[](size_type idx) const
262  {
263  return data()[idx];
264  }
265 
271  constexpr pointer data() const noexcept
272  {
273  return m_storage.m_data;
274  }
275 
281  constexpr size_type size() const noexcept
282  {
283  return m_storage.m_size;
284  }
285 
291  constexpr size_type size_bytes() const noexcept
292  {
293  return size() * sizeof(element_type);
294  }
295 
301  constexpr bool empty() const noexcept
302  {
303  return size() == 0;
304  }
305 
311  template <size_type Count>
313  {
314  static_assert(Count <= Extent, "Requested number of characters out of range.");
315  return Span<element_type, Count>(data(), Count);
316  }
317 
325  {
326  return Span<element_type, dynamic_extent>(data(), Count);
327  }
328 
334  template <size_type Count>
335  constexpr Span<element_type, Count> last() const
336  {
337  static_assert(Count <= Extent, "Requested number of characters out of range.");
338  return Span<element_type, Count>(data() + (size() - Count), Count);
339  }
340 
348  {
349  return Span<element_type, dynamic_extent>(data() + (size() - Count), Count);
350  }
351 
352  template <size_type Offset, size_type Count>
354  Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : dynamic_extent)>;
355 
362  template <size_type Offset, size_type Count = dynamic_extent,
363  typename std::enable_if<Count == dynamic_extent, int>::type = 0>
365  {
366  static_assert((Extent == dynamic_extent) || (Offset <= Extent),
367  "Requested number of characters out of range.");
368  return SubspanReturnType<Offset, Count>(data() + Offset, size() - Offset);
369  }
370 
371  template <size_type Offset, size_type Count,
372  typename std::enable_if<Count != dynamic_extent, int>::type = 0>
374  {
375  static_assert((Extent == dynamic_extent) || (Offset <= Extent && Offset + Count <= Extent),
376  "Requested number of characters out of range.");
377  return SubspanReturnType<Offset, Count>(data() + Offset, Count);
378  }
389  size_type Offset, size_type Count = dynamic_extent) const
390  {
392  data() + Offset, Count == dynamic_extent ? size() - Offset : Count);
393  }
394 
395 private:
396  detail::SpanStorage<T, Extent> m_storage;
397 };
398 
399 } // namespace zserio
400 
401 #endif // ZSERIO_SPAN_H_INC
std::size_t size_type
Definition: Span.h:63
constexpr Span(pointer first_, size_type count)
Definition: Span.h:90
constexpr bool empty() const noexcept
Definition: Span.h:301
const T * const_pointer
Definition: Span.h:66
pointer iterator
Definition: Span.h:68
Span & operator=(Span &&other) noexcept=default
constexpr reference front() const
Definition: Span.h:240
constexpr Span() noexcept
Definition: Span.h:80
Span(const Span &other) noexcept=default
constexpr size_type size() const noexcept
Definition: Span.h:281
constexpr Span< element_type, dynamic_extent > last(size_type Count) const
Definition: Span.h:347
static constexpr size_type extent
Definition: Span.h:73
constexpr Span(const Span< U, N > &span) noexcept
Definition: Span.h:176
constexpr Span< element_type, Count > last() const
Definition: Span.h:335
constexpr Span(pointer first_, pointer last_)
Definition: Span.h:101
constexpr reverse_iterator rbegin() const noexcept
Definition: Span.h:220
std::ptrdiff_t difference_type
Definition: Span.h:64
T element_type
Definition: Span.h:61
constexpr reverse_iterator rend() const noexcept
Definition: Span.h:230
const_pointer const_iterator
Definition: Span.h:69
~Span()=default
constexpr Span< element_type, dynamic_extent > subspan(size_type Offset, size_type Count=dynamic_extent) const
Definition: Span.h:388
typename std::remove_cv< T >::type value_type
Definition: Span.h:62
constexpr reference back() const
Definition: Span.h:250
constexpr Span(const std::vector< U, ALLOC > &vec)
Definition: Span.h:163
constexpr pointer data() const noexcept
Definition: Span.h:271
T * pointer
Definition: Span.h:65
constexpr SubspanReturnType< Offset, Count > subspan() const
Definition: Span.h:364
std::reverse_iterator< iterator > reverse_iterator
Definition: Span.h:70
T & reference
Definition: Span.h:67
Span(Span &&other) noexcept=default
constexpr size_type size_bytes() const noexcept
Definition: Span.h:291
constexpr Span(const std::array< U, N > &arr) noexcept
Definition: Span.h:138
constexpr reference operator[](size_type idx) const
Definition: Span.h:261
constexpr Span< element_type, Count > first() const
Definition: Span.h:312
constexpr Span< element_type, dynamic_extent > first(size_type Count) const
Definition: Span.h:324
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Span.h:71
constexpr Span(std::array< U, N > &arr) noexcept
Definition: Span.h:125
Span & operator=(const Span &other) noexcept=default
constexpr Span(element_type(&arr)[N]) noexcept
Definition: Span.h:112
constexpr Span(std::vector< U, ALLOC > &vec)
Definition: Span.h:150
constexpr iterator end() const noexcept
Definition: Span.h:210
constexpr iterator begin() const noexcept
Definition: Span.h:200
constexpr std::size_t dynamic_extent
Definition: Span.h:17