HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
span.h
Go to the documentation of this file.
1 //
2 // Copyright 2019 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_TF_SPAN_H
8 #define PXR_BASE_TF_SPAN_H
9 
10 /// \file tf/span.h
11 
12 #include "pxr/pxr.h"
13 #include "pxr/base/tf/api.h"
14 #include "pxr/base/tf/diagnostic.h"
15 
16 #include <cstddef>
17 #include <iterator>
18 #include <type_traits>
19 
20 
22 
23 
24 /// \class TfSpan
25 /// Represents a range of contiguous elements.
26 ///
27 /// This simply pairs a pointer with a size, while adding a common
28 /// array interface.
29 ///
30 /// A span allows ranges of elements to be referenced in a container-neutral
31 /// manner. While it is possible to achieve that effect by simply passing around
32 /// raw pointers, a span has the advantage of carrying around additional size
33 /// information, both enabling use of common array patterns, as well as
34 /// providing sufficient information to perform boundary tests.
35 ///
36 /// A TfSpan is implicitly convertible from common array types,
37 /// as well as from other spans, but preserves const-ness:
38 ///
39 /// \code
40 /// std::vector<int> data;
41 /// TfSpan<int> span(data); // Okay
42 ///
43 /// VtIntArray data;
44 /// TfSpan<int> span = data; // Okay
45 /// TfSpan<const int> cspan = span; // Okay
46 ///
47 /// const std::vector<int> data;
48 /// TfSpan<const int> span = data; // Okay
49 ///
50 /// const std::vector<int> data;
51 /// TfSpan<int> span = data; // Error! Discards cv-qualifier.
52 /// \endcode
53 ///
54 /// Helper methods TfMakeSpan and TfMakeConstSpan are also provided to enable
55 /// auto-typing when constructing spans:
56 /// \code
57 /// VtIntArray data;
58 /// auto readOnlySpan = TfMakeConstSpan(data); // TfSpan<const int>
59 /// auto readWriteSpan = TfMakeSpan(data); // TfSpan<int>
60 /// \endcode
61 ///
62 /// Spans do not own the data they reference. It is up to the user of the span
63 /// to ensure that the underlying data is not destructed while the span is in
64 /// use.
65 ///
66 /// This is modelled after std::span (C++20), but does not currently include
67 /// any specialization for static extents.
68 ///
69 template <typename T>
70 class TfSpan
71 {
72 public:
73  using element_type = T;
75  using pointer = T*;
76  using reference = T&;
77  using index_type = std::size_t;
78  using difference_type = std::ptrdiff_t;
79 
80  using iterator = T*;
81  using const_iterator = const T*;
82  using reverse_iterator = std::reverse_iterator<iterator>;
83  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
84 
85  TfSpan() noexcept = default;
86 
87  /// Construct a span over the range of [ptr, ptr+count).
88  /// In debug builds, a runtime assertion will fail if \p count > 0 and
89  /// \p ptr is null. The behavior is otherwise undefined for invalid ranges.
91  : _data(ptr), _size(count)
92  {
93  TF_DEV_AXIOM(count == 0 || ptr);
94  }
95 
96  /// Construct a span over the range [first, last).
98  : TfSpan(first, index_type(last-first))
99  {
100  TF_DEV_AXIOM(last >= first);
101  }
102 
103  /// Construct a span from a container.
104  /// The resulting span has a range of
105  /// [cont.data(), cont.data()+cont.size())
106  template <class Container>
107  TfSpan(Container& cont,
108  typename std::enable_if<
110  std::is_same<typename Container::value_type, value_type
111  >::value, Container
112  >::type* = 0)
113  : _data(cont.data()), _size(cont.size())
114  {
115  TF_DEV_AXIOM(_size == 0 || _data);
116  }
117 
118  /// Construct a span from a container.
119  /// The resulting span has a range of
120  /// [cont.data(), cont.data()+cont.size())
121  template <class Container>
122  TfSpan(const Container& cont,
123  typename std::enable_if<
124  std::is_same<typename Container::value_type, value_type
125  >::value, Container
126  >::type* = 0)
127  : _data(cont.data()), _size(cont.size())
128  {
129  TF_DEV_AXIOM(_size == 0 || _data);
130  }
131 
132  /// Return a pointer to the first element of the span.
133  pointer data() const noexcept { return _data; }
134 
135  /// Return the total number of elements in the span.
136  index_type size() const noexcept { return _size; }
137 
138  /// Returns true if this span contains no elements, false otherwise.
139  bool empty() const noexcept { return _size == 0; }
140 
141  /// Returns a reference to the \p idx'th element of the span.
142  /// In debug builds, a runtime assertion will fail if \p idx is out of
143  /// range. The behavior is otherwise undefined if \p idx is out of range.
145  TF_DEV_AXIOM(idx < _size);
146  return _data[idx];
147  }
148 
149  /// Return a reference to the first element in the span.
150  reference front() const {
151  TF_DEV_AXIOM(!empty());
152  return *begin();
153  }
154 
155  /// Return a reference to the last element in the span.
156  reference back() const {
157  TF_DEV_AXIOM(!empty());
158  return *(end() - 1);
159  }
160 
161  /// Returns a non-const iterator the start of the span.
162  iterator begin() const noexcept { return _data; }
163 
164  /// Returns a cons iterator to the start of the span.
165  const_iterator cbegin() const noexcept { return _data; }
166 
167  /// Returns a non-const iterator to the end of the span.
168  iterator end() const noexcept { return _data + _size; }
169 
170  /// Returns a const iterator to the end of the span.
171  const_iterator cend() const noexcept { return _data + _size; }
172 
173  /// Returns a non-const reverse iterator the start of the span.
174  reverse_iterator rbegin() const noexcept
175  { return reverse_iterator(end()); }
176 
177  /// Returns a cons reverse iterator to the start of the span.
178  const_reverse_iterator crbegin() const noexcept
179  { return const_reverse_iterator(cend()); }
180 
181  /// Returns a non-const reverse iterator to the end of the span.
182  reverse_iterator rend() const noexcept
183  { return reverse_iterator(begin()); }
184 
185  /// Returns a const reverse iterator to the end of the span.
186  const_reverse_iterator crend() const noexcept
187  { return const_reverse_iterator(cbegin()); }
188 
189  /// Returns a new span referencing a sub-range of this span.
190  /// If \p count == -1 (or std::dynamic_extent in C++20), the new span
191  /// has a range of [data()+offset, data()+size()). Otherwise, the new
192  /// span has range [data()+offset, data()+offset+count).
194  TF_DEV_AXIOM(offset >= 0 && (index_type)offset < _size);
195  if (count == -1) {
196  return TfSpan<T>(_data + offset, _size - offset);
197  } else {
198  TF_DEV_AXIOM(count >= 0);
199  TF_DEV_AXIOM(((index_type)offset+(index_type)count) <= _size);
200  return TfSpan<T>(_data + offset, count);
201  }
202  }
203 
204  /// Return a subspan consisting of the first \p count elements of this span.
205  TfSpan<T> first(size_t count) const {
206  return subspan(0, count);
207  }
208 
209  /// Return a subspan consisting of the last \p count elements of this span.
210  TfSpan<T> last(size_t count) const {
211  TF_DEV_AXIOM(_size >= count);
212  return TfSpan<T>(end() - count, count);
213  }
214 
215 private:
216  pointer _data = nullptr;
217  index_type _size = 0;
218 };
219 
220 
221 /// Helper for constructing a non-const TfSpan from a container.
222 template <typename Container>
224 TfMakeSpan(Container& cont)
225 {
227 }
228 
229 
230 /// Helper for constructing a const TfSpan from a container.
231 template <typename Container>
233 TfMakeConstSpan(const Container& cont)
234 {
236 }
237 
239 
240 #endif // PXR_BASE_TF_SPAN_H
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the end of the span.
Definition: span.h:186
type
Definition: core.h:556
TfSpan() noexcept=default
GLint first
Definition: glcorearb.h:405
const_iterator cend() const noexcept
Returns a const iterator to the end of the span.
Definition: span.h:171
TfSpan(Container &cont, typename std::enable_if< !std::is_const< element_type >::value &&std::is_same< typename Container::value_type, value_type >::value, Container >::type *=0)
Definition: span.h:107
index_type size() const noexcept
Return the total number of elements in the span.
Definition: span.h:136
bool empty() const noexcept
Returns true if this span contains no elements, false otherwise.
Definition: span.h:139
std::ptrdiff_t difference_type
Definition: span.h:78
GLsizei const GLfloat * value
Definition: glcorearb.h:824
reference operator[](index_type idx) const
Definition: span.h:144
const_iterator cbegin() const noexcept
Returns a cons iterator to the start of the span.
Definition: span.h:165
TfSpan(pointer first, pointer last)
Construct a span over the range [first, last).
Definition: span.h:97
uint64 value_type
Definition: GA_PrimCompat.h:29
#define TF_DEV_AXIOM(cond)
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: span.h:83
GLintptr offset
Definition: glcorearb.h:665
const T * const_iterator
Definition: span.h:81
TfSpan(const Container &cont, typename std::enable_if< std::is_same< typename Container::value_type, value_type >::value, Container >::type *=0)
Definition: span.h:122
TfSpan< T > last(size_t count) const
Return a subspan consisting of the last count elements of this span.
Definition: span.h:210
Definition: span.h:70
T & reference
Definition: span.h:76
TfSpan< T > first(size_t count) const
Return a subspan consisting of the first count elements of this span.
Definition: span.h:205
TfSpan< T > subspan(difference_type offset, difference_type count=-1) const
Definition: span.h:193
T * pointer
Definition: span.h:75
typename std::remove_cv< T >::type value_type
Definition: span.h:74
T * iterator
Definition: span.h:80
std::size_t index_type
Definition: span.h:77
std::reverse_iterator< iterator > reverse_iterator
Definition: span.h:82
iterator end() const noexcept
Returns a non-const iterator to the end of the span.
Definition: span.h:168
reverse_iterator rbegin() const noexcept
Returns a non-const reverse iterator the start of the span.
Definition: span.h:174
GLsizeiptr size
Definition: glcorearb.h:664
GLenum void ** pointer
Definition: glcorearb.h:810
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
TfSpan< typename Container::value_type > TfMakeSpan(Container &cont)
Helper for constructing a non-const TfSpan from a container.
Definition: span.h:224
TfSpan< const typename Container::value_type > TfMakeConstSpan(const Container &cont)
Helper for constructing a const TfSpan from a container.
Definition: span.h:233
auto ptr(T p) -> const void *
Definition: format.h:4331
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
T element_type
Definition: span.h:73
pointer data() const noexcept
Return a pointer to the first element of the span.
Definition: span.h:133
iterator begin() const noexcept
Returns a non-const iterator the start of the span.
Definition: span.h:162
reference back() const
Return a reference to the last element in the span.
Definition: span.h:156
reverse_iterator rend() const noexcept
Returns a non-const reverse iterator to the end of the span.
Definition: span.h:182
reference front() const
Return a reference to the first element in the span.
Definition: span.h:150
GLint GLsizei count
Definition: glcorearb.h:405
Definition: format.h:1821
const_reverse_iterator crbegin() const noexcept
Returns a cons reverse iterator to the start of the span.
Definition: span.h:178