HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
span.h
Go to the documentation of this file.
1 // Copyright 2008-present Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/OpenImageIO/oiio
4 
5 // clang-format off
6 
7 #pragma once
8 
9 #include <array>
10 #include <cstddef>
11 #include <initializer_list>
12 #include <iostream>
13 #include <stdexcept>
14 #include <type_traits>
15 #include <vector>
16 
17 #include <OpenImageIO/dassert.h>
19 #include <OpenImageIO/platform.h>
20 
22 
23 // By default, our span::size() is a signed value, because we wrote this at
24 // a time that the draft of std::span said it should be signed. The final
25 // C++20 std::span ended up with an unsigned size, like all the other STL
26 // classes. We will eventually conform by switching, but not until we are at
27 // OIIO 3.0, allowing source code API-breaking incompatibilities. In the
28 // mean time, we allow a back door to experiment with standard conformance
29 // by pre-defining OIIO_SPAN_SIZE_IS_UNSIGNED=1.
30 #if OIIO_VERSION_GREATER_EQUAL(3,0,0)
31 # define OIIO_SPAN_SIZE_IS_UNSIGNED
32 #endif
33 
34 #ifdef OIIO_SPAN_SIZE_IS_UNSIGNED
35 using oiio_span_size_type = size_t;
36 #else
37 using oiio_span_size_type = ptrdiff_t;
38 #endif
39 
40 OIIO_INLINE_CONSTEXPR oiio_span_size_type dynamic_extent = -1;
41 
42 
43 
44 /// span<T> is a non-owning, non-copying, non-allocating reference to a
45 /// contiguous array of T objects known length. A 'span` encapsulates both a
46 /// pointer and a length, and thus is a safer way of passing pointers around
47 /// (because the function called knows how long the array is). A function
48 /// that might ordinarily take a `T*` and a length could instead just take a
49 /// `span<T>`.
50 ///
51 /// `A span<T>` is mutable (the values in the array may be modified). A
52 /// non-mutable (i.e., read-only) reference would be `span<const T>`. Thus,
53 /// a function that might ordinarily take a `const T*` and a length could
54 /// instead take a `span<const T>`.
55 ///
56 /// For convenience, we also define `cspan<T>` as equivalent to
57 /// `span<const T>`.
58 ///
59 /// A `span` may be initialized explicitly from a pointer and length, by
60 /// initializing with a `std::vector<T>`, or by initalizing with a constant
61 /// (treated as an array of length 1). For all of these cases, no extra
62 /// allocations are performed, and no extra copies of the array contents are
63 /// made.
64 ///
65 /// Important caveat: The `span` merely refers to items owned by another
66 /// array, so the `span` should not be used beyond the lifetime of the
67 /// array it refers to. Thus, `span` is great for parameter passing, but
68 /// it's not a good idea to use a `span` to store values in a data
69 /// structure (unless you are really sure you know what you're doing).
70 ///
71 
72 template <typename T, oiio_span_size_type Extent = dynamic_extent>
73 class span {
74  static_assert (std::is_array<T>::value == false, "can't have span of an array");
75 public:
76  using element_type = T;
79  using difference_type = ptrdiff_t;
80 #if OIIO_VERSION < OIIO_MAKE_VERSION(3,0,0)
81  using index_type = size_type; // DEPRECATED(3.0)
82 #endif
86  using const_iterator = const element_type*;
87  using reverse_iterator = std::reverse_iterator<iterator>;
88  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
89  static constexpr size_type extent = Extent;
90 
91  /// Default constructor -- the span points to nothing.
92  constexpr span () noexcept { }
93 
94  /// Copy constructor (copies the span pointer and length, NOT the data).
95  template<class U, oiio_span_size_type N>
96  constexpr span (const span<U,N> &copy) noexcept
97  : m_data(copy.data()), m_size(copy.size()) { }
98  /// Copy constructor (copies the span pointer and length, NOT the data).
99  constexpr span (const span &copy) noexcept = default;
100 
101  /// Construct from T* and length.
102  constexpr span (pointer data, size_type size) noexcept
103  : m_data(data), m_size(size) { }
104 
105  /// Construct from begin and end pointers.
106  constexpr span (pointer b, pointer e) noexcept
107  : m_data(b), m_size(e-b) { }
108 
109  /// Construct from a single T&.
110  constexpr span (T &data) : m_data(&data), m_size(1) { }
111 
112  /// Construct from a fixed-length C array. Template magic automatically
113  /// finds the length from the declared type of the array.
114  template<size_t N>
115  constexpr span (T (&data)[N]) : m_data(data), m_size(N) { }
116 
117  /// Construct from std::vector<T>.
118  template<class Allocator>
119  constexpr span (std::vector<T, Allocator> &v)
120  : m_data(v.size() ? &v[0] : nullptr), m_size(v.size()) {
121  }
122 
123  /// Construct from `const std::vector<T>.` This turns
124  /// `const std::vector<T>` into a `span<const T>` (the span isn't const,
125  /// but the data it points to will be).
126  template<class Allocator>
127  span (const std::vector<value_type, Allocator> &v)
128  : m_data(v.size() ? &v[0] : nullptr), m_size(v.size()) { }
129 
130  /// Construct from mutable element std::array
131  template <size_t N>
132  constexpr span (std::array<value_type, N> &arr)
133  : m_data(arr.data()), m_size(N) {}
134 
135  /// Construct from read-only element std::array
136  template <size_t N>
137  constexpr span (const std::array<value_type, N>& arr)
138  : m_data(arr.data()), m_size(N) {}
139 
140  /// Construct an span from an initializer_list.
141  constexpr span (std::initializer_list<T> il)
142  : span (il.begin(), il.size()) { }
143 
144  /// Assignment copies the pointer and length, not the data.
146  m_data = copy.data();
147  m_size = copy.size();
148  return *this;
149  }
150 
151  /// Subview containing the first Count elements of the span.
152  template<size_type Count>
153  constexpr span<element_type, Count> first () const {
154  return { m_data, Count };
155  }
156  /// Subview containing the last Count elements of the span.
157  template<size_type Count>
158  constexpr span<element_type, Count> last () const {
159  return { m_data + m_size - Count, Count };
160  }
161 
162  template<size_type Offset, size_type Count = dynamic_extent>
163  constexpr span<element_type, Count> subspan () const {
164  return { m_data + Offset, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : m_size - Offset) };
165  }
166 
168  return { m_data, count };
169  }
170 
172  return { m_data + ( m_size - count ), count };
173  }
174 
177  return { m_data + offset, count == dynamic_extent ? m_size - offset : count };
178  }
179 
180  // Note: size() currently returns a signed value. But eventually, we
181  // will conform to std::span<>::size() which returns size_t. In the mean
182  // time, apps may choose to avoid the size() method and instead use
183  // std::size(myspan) and std::ssize(myspan), which already conform to
184  // std's practice of returning size_t and ptrdiff_t, respectively.
185  constexpr size_type size() const noexcept { return m_size; }
186  constexpr size_type size_bytes() const noexcept { return size()*sizeof(T); }
187  constexpr bool empty() const noexcept { return m_size == 0; }
188 
189  constexpr pointer data() const noexcept { return m_data; }
190 
191  constexpr reference operator[] (size_type idx) const { return m_data[idx]; }
192  constexpr reference operator() (size_type idx) const { return m_data[idx]; }
193  reference at (size_type idx) const {
194  if (idx >= size())
195  throw (std::out_of_range ("OpenImageIO::span::at"));
196  return m_data[idx];
197  }
198 
199  constexpr reference front() const noexcept { return m_data[0]; }
200  constexpr reference back() const noexcept { return m_data[size()-1]; }
201 
202  constexpr iterator begin() const noexcept { return m_data; }
203  constexpr iterator end() const noexcept { return m_data + m_size; }
204 
205  constexpr const_iterator cbegin() const noexcept { return m_data; }
206  constexpr const_iterator cend() const noexcept { return m_data + m_size; }
207 
208  constexpr reverse_iterator rbegin() const noexcept { return m_data + m_size - 1; }
209  constexpr reverse_iterator rend() const noexcept { return m_data - 1; }
210 
211  constexpr const_reverse_iterator crbegin() const noexcept { return m_data + m_size - 1; }
212  constexpr const_reverse_iterator crend() const noexcept { return m_data - 1; }
213 
214 private:
215  pointer m_data = nullptr;
216  size_type m_size = 0;
217 };
218 
219 
220 
221 /// cspan<T> is a synonym for a non-mutable span<const T>.
222 template <typename T>
224 
225 
226 
227 /// Compare all elements of two spans for equality
228 template <class T, oiio_span_size_type X, class U, oiio_span_size_type Y>
230 #if OIIO_CPLUSPLUS_VERSION >= 20
231  return std::equal (l.begin(), l.end(), r.begin(), r.end());
232 #else
233  auto lsize = l.size();
234  bool same = (lsize == r.size());
235  for (ptrdiff_t i = 0; same && i < lsize; ++i)
236  same &= (l[i] == r[i]);
237  return same;
238 #endif
239 }
240 
241 /// Compare all elements of two spans for inequality
242 template <class T, oiio_span_size_type X, class U, oiio_span_size_type Y>
244  return !(l == r);
245 }
246 
247 
248 
249 /// span_strided<T> : a non-owning, mutable reference to a contiguous
250 /// array with known length and optionally non-default strides through the
251 /// data. An span_strided<T> is mutable (the values in the array may
252 /// be modified), whereas an span_strided<const T> is not mutable.
253 template <typename T, oiio_span_size_type Extent = dynamic_extent>
255  static_assert (std::is_array<T>::value == false,
256  "can't have span_strided of an array");
257 public:
258  using element_type = T;
261  using difference_type = ptrdiff_t;
262 #if OIIO_VERSION < OIIO_MAKE_VERSION(3,0,0)
263  using index_type = size_type; // DEPRECATED(3.0)
264 #endif
265  using stride_type = ptrdiff_t;
269  using const_iterator = const element_type*;
270  using reverse_iterator = std::reverse_iterator<iterator>;
271  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
272  static constexpr size_type extent = Extent;
273 
274  /// Default ctr -- points to nothing
275  constexpr span_strided () noexcept {}
276 
277  /// Copy constructor
278  constexpr span_strided (const span_strided &copy)
279  : m_data(copy.data()), m_size(copy.size()), m_stride(copy.stride()) {}
280 
281  /// Construct from T* and size, and optionally stride.
283  : m_data(data), m_size(size), m_stride(stride) { }
284 
285  /// Construct from a single T&.
286  constexpr span_strided (T &data) : span_strided(&data,1,1) { }
287 
288  /// Construct from a fixed-length C array. Template magic automatically
289  /// finds the length from the declared type of the array.
290  template<size_t N>
291  constexpr span_strided (T (&data)[N]) : span_strided(data,N,1) {}
292 
293  /// Construct from std::vector<T>.
294  template<class Allocator>
295  OIIO_CONSTEXPR14 span_strided (std::vector<T, Allocator> &v)
296  : span_strided(v.size() ? &v[0] : nullptr, v.size(), 1) {}
297 
298  /// Construct from const std::vector<T>. This turns const std::vector<T>
299  /// into an span_strided<const T> (the span_strided isn't
300  /// const, but the data it points to will be).
301  template<class Allocator>
302  constexpr span_strided (const std::vector<value_type, Allocator> &v)
303  : span_strided(v.size() ? &v[0] : nullptr, v.size(), 1) {}
304 
305  /// Construct an span from an initializer_list.
306  constexpr span_strided (std::initializer_list<T> il)
307  : span_strided (il.begin(), il.size()) { }
308 
309  /// Initialize from an span (stride will be 1).
310  constexpr span_strided (span<T> av)
311  : span_strided(av.data(), av.size(), 1) { }
312 
313  // assignments
315  m_data = copy.data();
316  m_size = copy.size();
317  m_stride = copy.stride();
318  return *this;
319  }
320 
321  constexpr size_type size() const noexcept { return m_size; }
322  constexpr stride_type stride() const noexcept { return m_stride; }
323 
324  constexpr reference operator[] (size_type idx) const {
325  return m_data[m_stride*idx];
326  }
327  constexpr reference operator() (size_type idx) const {
328  return m_data[m_stride*idx];
329  }
330  reference at (size_type idx) const {
331  if (idx >= size())
332  throw (std::out_of_range ("OpenImageIO::span_strided::at"));
333  return m_data[m_stride*idx];
334  }
335  constexpr reference front() const noexcept { return m_data[0]; }
336  constexpr reference back() const noexcept { return (*this)[size()-1]; }
337  constexpr pointer data() const noexcept { return m_data; }
338 
339 private:
340  pointer m_data = nullptr;
341  size_type m_size = 0;
342  stride_type m_stride = 1;
343 };
344 
345 
346 
347 /// cspan_strided<T> is a synonym for a non-mutable span_strided<const T>.
348 template <typename T>
350 
351 
352 
353 /// Compare all elements of two spans for equality
354 template <class T, oiio_span_size_type X, class U, oiio_span_size_type Y>
356  auto lsize = l.size();
357  if (lsize != r.size())
358  return false;
359  for (ptrdiff_t i = 0; i < lsize; ++i)
360  if (l[i] != r[i])
361  return false;
362  return true;
363 }
364 
365 /// Compare all elements of two spans for inequality
366 template <class T, oiio_span_size_type X, class U, oiio_span_size_type Y>
368  return !(l == r);
369 }
370 
371 
373 
374 
375 
376 // Declare std::size and std::ssize for our span.
377 namespace std {
378 
379 template<class T, OIIO::oiio_span_size_type E = OIIO::dynamic_extent>
380 constexpr size_t size(const OIIO::span<T, E>& c) {
381  return static_cast<size_t>(c.size());
382 }
383 
384 template<class T, OIIO::oiio_span_size_type E = OIIO::dynamic_extent>
385 constexpr size_t size(const OIIO::span_strided<T, E>& c) {
386  return static_cast<size_t>(c.size());
387 }
388 
389 
390 #if OIIO_CPLUSPLUS_VERSION < 20
391 // C++20 and beyond already have these declared.
392 template<class T, OIIO::oiio_span_size_type E = OIIO::dynamic_extent>
393 constexpr ptrdiff_t ssize(const OIIO::span<T, E>& c) {
394  return static_cast<ptrdiff_t>(c.size());
395 }
396 
397 template<class T, OIIO::oiio_span_size_type E = OIIO::dynamic_extent>
398 constexpr ptrdiff_t ssize(const OIIO::span_strided<T, E>& c) {
399  return static_cast<ptrdiff_t>(c.size());
400 }
401 #endif
402 
403 // Allow client software to easily know if the std::size/ssize was added for
404 // our span templates.
405 #define OIIO_SPAN_HAS_STD_SIZE 1
406 
407 } // namespace std
#define OIIO_CONSTEXPR14
Definition: platform.h:101
constexpr span(std::array< value_type, N > &arr)
Construct from mutable element std::array.
Definition: span.h:132
constexpr const_iterator cend() const noexcept
Definition: span.h:206
typename std::remove_cv< T >::type value_type
Definition: span.h:259
constexpr iterator end() const noexcept
Definition: span.h:203
constexpr span(std::vector< T, Allocator > &v)
Construct from std::vector<T>.
Definition: span.h:119
constexpr span_strided(const span_strided &copy)
Copy constructor.
Definition: span.h:278
constexpr span< element_type, dynamic_extent > subspan(size_type offset, size_type count=dynamic_extent) const
Definition: span.h:176
ptrdiff_t difference_type
Definition: span.h:261
constexpr span< element_type, Count > first() const
Subview containing the first Count elements of the span.
Definition: span.h:153
span & operator=(const span &copy)
Assignment copies the pointer and length, not the data.
Definition: span.h:145
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
const GLdouble * v
Definition: glcorearb.h:837
GLsizei const GLfloat * value
Definition: glcorearb.h:824
element_type * iterator
Definition: span.h:268
constexpr span_strided(T(&data)[N])
Definition: span.h:291
constexpr span_strided(pointer data, size_type size, stride_type stride=1)
Construct from T* and size, and optionally stride.
Definition: span.h:282
constexpr span< element_type, Count > subspan() const
Definition: span.h:163
typename std::remove_cv< unsigned char >::type value_type
Definition: span.h:77
Definition: span.h:73
IMATH_HOSTDEVICE constexpr bool equal(T1 a, T2 b, T3 t) IMATH_NOEXCEPT
Definition: ImathFun.h:105
T element_type
Definition: span.h:258
constexpr span_strided() noexcept
Default ctr – points to nothing.
Definition: span.h:275
constexpr size_type size() const noexcept
Definition: span.h:321
constexpr span_strided(span< T > av)
Initialize from an span (stride will be 1).
Definition: span.h:310
std::reverse_iterator< iterator > reverse_iterator
Definition: span.h:270
ptrdiff_t oiio_span_size_type
Definition: span.h:37
ptrdiff_t difference_type
Definition: span.h:79
constexpr const_iterator cbegin() const noexcept
Definition: span.h:205
constexpr reference back() const noexcept
Definition: span.h:200
constexpr span(std::initializer_list< T > il)
Construct an span from an initializer_list.
Definition: span.h:141
ptrdiff_t stride_type
Definition: span.h:265
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: span.h:88
OIIO_CONSTEXPR14 bool operator==(span< T, X > l, span< U, Y > r)
Compare all elements of two spans for equality.
Definition: span.h:229
GLintptr offset
Definition: glcorearb.h:665
constexpr reference operator()(size_type idx) const
Definition: span.h:192
OIIO_CONSTEXPR14 bool operator!=(span< T, X > l, span< U, Y > r)
Compare all elements of two spans for inequality.
Definition: span.h:243
OIIO_CONSTEXPR14 span_strided(std::vector< T, Allocator > &v)
Construct from std::vector<T>.
Definition: span.h:295
constexpr iterator begin() const noexcept
Definition: span.h:202
OIIO_INLINE_CONSTEXPR oiio_span_size_type dynamic_extent
Definition: span.h:40
constexpr span< element_type, Count > last() const
Subview containing the last Count elements of the span.
Definition: span.h:158
constexpr pointer data() const noexcept
Definition: span.h:337
element_type * iterator
Definition: span.h:85
const element_type * const_iterator
Definition: span.h:269
constexpr const_reverse_iterator crend() const noexcept
Definition: span.h:212
constexpr reference operator[](size_type idx) const
Definition: span.h:191
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:872
constexpr span_strided(const std::vector< value_type, Allocator > &v)
Definition: span.h:302
element_type & reference
Definition: span.h:84
const element_type * const_iterator
Definition: span.h:86
constexpr span(T &data)
Construct from a single T&.
Definition: span.h:110
constexpr size_type size() const noexcept
Definition: span.h:185
constexpr reverse_iterator rbegin() const noexcept
Definition: span.h:208
constexpr span< element_type, dynamic_extent > last(size_type count) const
Definition: span.h:171
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
constexpr span_strided(std::initializer_list< T > il)
Construct an span from an initializer_list.
Definition: span.h:306
constexpr span(const std::array< value_type, N > &arr)
Construct from read-only element std::array.
Definition: span.h:137
static constexpr size_type extent
Definition: span.h:89
unsigned char element_type
Definition: span.h:76
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: span.h:271
oiio_span_size_type size_type
Definition: span.h:260
GLsizeiptr size
Definition: glcorearb.h:664
constexpr ptrdiff_t ssize(const OIIO::span_strided< T, E > &c)
Definition: span.h:398
GLenum void ** pointer
Definition: glcorearb.h:810
reference at(size_type idx) const
Definition: span.h:330
constexpr span(const span< U, N > &copy) noexcept
Copy constructor (copies the span pointer and length, NOT the data).
Definition: span.h:96
constexpr reference back() const noexcept
Definition: span.h:336
constexpr span(T(&data)[N])
Definition: span.h:115
reference at(size_type idx) const
Definition: span.h:193
constexpr span(pointer data, size_type size) noexcept
Construct from T* and length.
Definition: span.h:102
oiio_span_size_type size_type
Definition: span.h:78
constexpr size_type size_bytes() const noexcept
Definition: span.h:186
constexpr reference front() const noexcept
Definition: span.h:199
constexpr span_strided(T &data)
Construct from a single T&.
Definition: span.h:286
GA_API const UT_StringHolder N
constexpr span< element_type, dynamic_extent > first(size_type count) const
Definition: span.h:167
span(const std::vector< value_type, Allocator > &v)
Definition: span.h:127
constexpr bool empty() const noexcept
Definition: span.h:187
constexpr span(pointer b, pointer e) noexcept
Construct from begin and end pointers.
Definition: span.h:106
element_type * pointer
Definition: span.h:266
element_type * pointer
Definition: span.h:83
constexpr reference front() const noexcept
Definition: span.h:335
GLboolean r
Definition: glcorearb.h:1222
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:94
element_type & reference
Definition: span.h:267
constexpr span() noexcept
Default constructor – the span points to nothing.
Definition: span.h:92
constexpr reverse_iterator rend() const noexcept
Definition: span.h:209
type
Definition: core.h:1059
constexpr pointer data() const noexcept
Definition: span.h:189
constexpr const_reverse_iterator crbegin() const noexcept
Definition: span.h:211
GLint GLsizei count
Definition: glcorearb.h:405
Definition: format.h:895
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:93
constexpr stride_type stride() const noexcept
Definition: span.h:322
std::reverse_iterator< iterator > reverse_iterator
Definition: span.h:87