Zserio C++ runtime library  1.0.0
Built for Zserio 2.13.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 <limits>
7 #include <iterator>
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), m_size(size)
42  {}
43 
44  T* m_data = nullptr;
45  std::size_t m_size = 0;
46 };
47 
48 } // namespace detail
49 
56 template <typename T, std::size_t Extent = dynamic_extent>
57 class Span
58 {
59 public:
60  using element_type = T;
61  using value_type = typename std::remove_cv<T>::type;
62  using size_type = std::size_t;
63  using difference_type = std::ptrdiff_t;
64  using pointer = T*;
65  using const_pointer = const T*;
66  using reference = T&;
67  using iterator = pointer;
69  using reverse_iterator = std::reverse_iterator<iterator>;
70  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
71 
72  static constexpr size_type extent = Extent;
73 
77  template <size_type ext = Extent,
78  typename std::enable_if<(ext == 0 || ext == dynamic_extent), int>::type = 0>
79  constexpr Span() noexcept
80  {}
81 
89  constexpr Span(pointer first, size_type count) :
90  m_storage(first, count)
91  {}
92 
100  constexpr Span(pointer first, pointer last) :
101  m_storage(first, static_cast<size_t>(last - first))
102  {}
103 
109  template <size_type N, size_type ext = Extent,
110  typename std::enable_if<(ext == dynamic_extent || ext == N), int>::type = 0>
111  constexpr Span(element_type(&arr)[N]) noexcept :
112  m_storage(arr, N)
113  {}
114 
120  template <typename U, size_type N, size_type ext = Extent,
121  typename std::enable_if<(ext == dynamic_extent || ext == N) &&
122  std::is_convertible<U(*)[], T(*)[]>::value, int>::type = 0>
123  constexpr Span(std::array<U, N>& arr) noexcept :
124  m_storage(arr.data(), arr.size())
125  {}
126 
132  template <typename U, size_type N, size_type ext = Extent,
133  typename std::enable_if<(ext == dynamic_extent || ext == N) &&
134  std::is_convertible<const U(*)[], T(*)[]>::value, int>::type = 0>
135  constexpr Span(const std::array<U, N>& arr) noexcept :
136  m_storage(arr.data(), arr.size())
137  {}
138 
144  template <typename U, typename ALLOC, size_type ext = Extent,
145  typename std::enable_if<(ext == dynamic_extent) &&
146  std::is_convertible<U(*)[], T(*)[]>::value, int>::type = 0>
147  constexpr Span(std::vector<U, ALLOC>& vec) :
148  m_storage(vec.data(), vec.size())
149  {}
150 
156  template <typename U, typename ALLOC, size_type ext = Extent,
157  typename std::enable_if<(ext == dynamic_extent) &&
158  std::is_convertible<const U(*)[], T(*)[]>::value, int>::type = 0>
159  constexpr Span(const std::vector<U, ALLOC>& vec) :
160  m_storage(vec.data(), vec.size())
161  {}
162 
168  template <typename U, size_type N,
169  typename std::enable_if<(Extent == N || Extent == dynamic_extent) &&
170  std::is_convertible<U(*)[], T(*)[]>::value, int>::type = 0>
171  constexpr Span(const Span<U, N>& s) noexcept :
172  m_storage(s.data(), s.size())
173  {}
174 
179  ~Span() = default;
180 
181  Span(const Span& other) noexcept = default;
182  Span& operator=(const Span& other) noexcept = default;
183 
184  Span(Span&& other) noexcept = default;
185  Span& operator=(Span&& other) noexcept = default;
195  constexpr iterator begin() const noexcept
196  {
197  return data();
198  }
199 
205  constexpr iterator end() const noexcept
206  {
207  return data() + size();
208  }
209 
215  constexpr reverse_iterator rbegin() const noexcept
216  {
217  return reverse_iterator(end());
218  }
219 
225  constexpr reverse_iterator rend() const noexcept
226  {
227  return reverse_iterator(begin());
228  }
229 
235  constexpr reference front() const
236  {
237  return data()[0];
238  }
239 
245  constexpr reference back() const
246  {
247  return data()[size() - 1];
248  }
249 
256  constexpr reference operator[](size_type idx) const
257  {
258  return data()[idx];
259  }
260 
266  constexpr pointer data() const noexcept
267  {
268  return m_storage.m_data;
269  }
270 
276  constexpr size_type size() const noexcept
277  {
278  return m_storage.m_size;
279  }
280 
286  constexpr size_type size_bytes() const noexcept
287  {
288  return size() * sizeof(element_type);
289  }
290 
296  constexpr bool empty() const noexcept
297  {
298  return size() == 0;
299  }
300 
306  template <size_type Count>
308  {
309  static_assert(Count <= Extent, "Requested number of characters out of range.");
310  return Span<element_type, Count>(data(), Count);
311  }
312 
319  constexpr Span<element_type, dynamic_extent> first(size_type Count) const
320  {
321  return Span<element_type, dynamic_extent>(data(), Count);
322  }
323 
329  template <size_type Count>
330  constexpr Span<element_type, Count> last() const
331  {
332  static_assert(Count <= Extent, "Requested number of characters out of range.");
333  return Span<element_type, Count>(data() + (size() - Count), Count);
334  }
335 
342  constexpr Span<element_type, dynamic_extent> last(size_type Count) const
343  {
344  return Span<element_type, dynamic_extent>(data() + (size() - Count), Count);
345  }
346 
347  template <size_type Offset, size_type Count>
348  using SubspanReturnType =
349  Span<T, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset
351 
358  template <size_type Offset, size_type Count = dynamic_extent,
359  typename std::enable_if<Count == dynamic_extent, int>::type = 0>
361  {
362  static_assert((Extent == dynamic_extent) || (Offset <= Extent),
363  "Requested number of characters out of range.");
364  return SubspanReturnType<Offset, Count>(data() + Offset, size() - Offset);
365  }
366 
367  template <size_type Offset, size_type Count,
368  typename std::enable_if<Count != dynamic_extent, int>::type = 0>
370  {
371  static_assert((Extent == dynamic_extent) || (Offset <= Extent && Offset + Count <= Extent),
372  "Requested number of characters out of range.");
373  return SubspanReturnType<Offset, Count>(data() + Offset, Count);
374  }
384  constexpr Span<element_type, dynamic_extent> subspan(size_type Offset,
385  size_type Count = dynamic_extent) const
386  {
387  return Span<element_type, dynamic_extent>(data() + Offset,
388  Count == dynamic_extent ? size() - Offset : Count );
389  }
390 
391 private:
392  detail::SpanStorage<T, Extent> m_storage;
393 };
394 
395 } // namespace zserio
396 
397 #endif // ZSERIO_SPAN_H_INC
constexpr std::size_t dynamic_extent
Definition: Span.h:17
constexpr Span< element_type, dynamic_extent > subspan(size_type Offset, size_type Count=dynamic_extent) const
Definition: Span.h:384
const const zserio::BasicStringView * const_pointer
Definition: Span.h:65
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Span.h:70
constexpr reference front() const
Definition: Span.h:235
typename std::remove_cv< const zserio::BasicStringView >::type value_type
Definition: Span.h:61
constexpr Span(pointer first, size_type count)
Definition: Span.h:89
constexpr Span(std::array< U, N > &arr) noexcept
Definition: Span.h:123
constexpr Span< element_type, Count > last() const
Definition: Span.h:330
constexpr Span(const Span< U, N > &s) noexcept
Definition: Span.h:171
constexpr reference back() const
Definition: Span.h:245
constexpr Span(const std::array< U, N > &arr) noexcept
Definition: Span.h:135
constexpr bool empty() const noexcept
Definition: Span.h:296
std::reverse_iterator< iterator > reverse_iterator
Definition: Span.h:69
constexpr Span(const std::vector< U, ALLOC > &vec)
Definition: Span.h:159
constexpr reverse_iterator rend() const noexcept
Definition: Span.h:225
constexpr size_type size() const noexcept
Definition: Span.h:276
constexpr Span(pointer first, pointer last)
Definition: Span.h:100
constexpr Span() noexcept
Definition: Span.h:79
constexpr reference operator[](size_type idx) const
Definition: Span.h:256
constexpr SubspanReturnType< Offset, Count > subspan() const
Definition: Span.h:360
constexpr Span< element_type, dynamic_extent > first(size_type Count) const
Definition: Span.h:319
constexpr pointer data() const noexcept
Definition: Span.h:266
constexpr Span< element_type, Count > first() const
Definition: Span.h:307
constexpr iterator begin() const noexcept
Definition: Span.h:195
constexpr size_type size_bytes() const noexcept
Definition: Span.h:286
constexpr reverse_iterator rbegin() const noexcept
Definition: Span.h:215
constexpr Span(std::vector< U, ALLOC > &vec)
Definition: Span.h:147
constexpr Span< element_type, dynamic_extent > last(size_type Count) const
Definition: Span.h:342
constexpr iterator end() const noexcept
Definition: Span.h:205
constexpr Span(element_type(&arr)[N]) noexcept
Definition: Span.h:111