ATLAS Offline Software
span.icc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
3  */
4 /**
5  * @file CxxUtils/span.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Jan, 2022
8  * @brief Simplified version of the C++20 std::span.
9  */
10 
11 
12 namespace CxxUtils {
13 
14 
15 /*
16  * @brief Default constructor.
17  * Makes an empty span.
18  */
19 template <class T>
20 inline
21 span<T>::span()
22  : m_ptr(nullptr),
23  m_size(0)
24 {
25 }
26 
27 
28 /**
29  * @brief Constructor from start and length.
30  * @param ptr Start of the span.
31  * @param sz Length of the span.
32  */
33 template <class T>
34 #if HAVE_CONCEPTS
35 template <class U>
36 requires (valid_span_type_v<T, U>)
37 #else
38 template <class U, typename>
39 #endif
40 inline
41 span<T>::span (U* ptr, size_type sz)
42  : m_ptr (ptr),
43  m_size (sz)
44 {
45  // cppcheck-suppress missingReturn; false positive
46 }
47 
48 
49 /**
50  * @brief Constructor from start and end.
51  * @param beg Start of the span.
52  * @param end One past the end of the span.
53  */
54 template <class T>
55 #if HAVE_CONCEPTS
56 template <class U>
57 requires (valid_span_type_v<T, U>)
58 #else
59 template <class U, typename>
60 #endif
61 inline
62 span<T>::span (U* beg, U* end)
63  : m_ptr (beg),
64  m_size (end-beg)
65 {
66  // cppcheck-suppress missingReturn; false positive
67 }
68 
69 
70 /**
71  * @brief Constructor from another span.
72  * @param other Span to copy from.
73  */
74 template <class T>
75 #if HAVE_CONCEPTS
76 template <class U>
77 requires (valid_span_type_v<T, U>)
78 #else
79 template <class U, typename>
80 #endif
81 inline
82 span<T>::span (const span<U>& other)
83  : m_ptr (other.begin()),
84  m_size (other.size())
85 {
86 }
87 
88 
89 /**
90  * @brief Return the size of the span.
91  */
92 template <class T>
93 inline
94 constexpr typename span<T>::size_type
95 span<T>::size() const noexcept
96 {
97  return m_size;
98 }
99 
100 
101 /**
102  * @brief Return the size of contents of the span, in bytes.
103  */
104 template <class T>
105 inline
106 constexpr typename span<T>::size_type
107 span<T>::size_bytes() const noexcept
108 {
109  return m_size * sizeof(element_type);
110 }
111 
112 
113 /**
114  * @brief Test if the span is empty.
115  */
116 template <class T>
117 inline
118 constexpr bool
119 span<T>::empty() const noexcept
120 {
121  return m_size == 0;
122 }
123 
124 
125 /**
126  * @brief Return a reference to the first element in the span.
127  */
128 template <class T>
129 inline
130 constexpr typename span<T>::reference
131 span<T>::front() noexcept
132 {
133  assert (m_ptr != nullptr);
134  return *m_ptr;
135 }
136 
137 
138 /**
139  * @brief Return a reference to the first element in the span.
140  */
141 template <class T>
142 inline
143 constexpr typename span<T>::const_reference
144 span<T>::front() const noexcept
145 {
146  assert (m_ptr != nullptr);
147  return *m_ptr;
148 }
149 
150 
151 /**
152  * @brief Return a reference to the last element in the span.
153  */
154 template <class T>
155 inline
156 constexpr typename span<T>::reference
157 span<T>::back() noexcept
158 {
159  assert (m_ptr != nullptr);
160  return *(m_ptr + m_size-1);
161 }
162 
163 
164 /**
165  * @brief Return a reference to the last element in the span.
166  */
167 template <class T>
168 inline
169 constexpr typename span<T>::const_reference
170 span<T>::back() const noexcept
171 {
172  assert (m_ptr != nullptr);
173  return *(m_ptr + m_size-1);
174 }
175 
176 
177 /**
178  * @brief Return a reference to the i-th element in the span.
179  * @param i Index of the element to return.
180  */
181 template <class T>
182 inline
183 constexpr typename span<T>::reference
184 span<T>::operator[] (size_type i) noexcept
185 {
186  assert (i < m_size);
187  return m_ptr[i];
188 }
189 
190 
191 /**
192  * @brief Return a reference to the i-th element in the span.
193  * @param i Index of the element to return.
194  */
195 template <class T>
196 inline
197 constexpr typename span<T>::const_reference
198 span<T>::operator[] (size_type i) const noexcept
199 {
200  assert (i < m_size);
201  return m_ptr[i];
202 }
203 
204 
205 /**
206  * @brief Return a reference to the i-th element in the span (bounds-checked).
207  * @param i Index of the element to return.
208  */
209 template <class T>
210 inline
211 constexpr typename span<T>::reference
212 span<T>::at (size_type i)
213 {
214  if (i >= m_size) throw std::out_of_range ("CxxUtils::span::at");
215  return m_ptr[i];
216 }
217 
218 
219 /**
220  * @brief Return a reference to the i-th element in the span (bounds-checked).
221  * @param i Index of the element to return.
222  */
223 template <class T>
224 inline
225 constexpr typename span<T>::const_reference
226 span<T>::at (size_type i) const
227 {
228  if (i >= m_size) throw std::out_of_range ("CxxUtils::span::at");
229  return m_ptr[i];
230 }
231 
232 
233 /**
234  * @brief Return a pointer to the start of the span.
235  */
236 template <class T>
237 inline
238 constexpr typename span<T>::pointer
239 span<T>::data() noexcept
240 {
241  return m_ptr;
242 }
243 
244 
245 /**
246  * @brief Return a pointer to the start of the span.
247  */
248 template <class T>
249 inline
250 constexpr typename span<T>::const_pointer
251 span<T>::data() const noexcept
252 {
253  return m_ptr;
254 }
255 
256 
257 /**
258  * @brief Return a begin iterator.
259  */
260 template <class T>
261 inline
262 constexpr typename span<T>::iterator
263 span<T>::begin() noexcept
264 {
265  return m_ptr;
266 }
267 
268 
269 /**
270  * @brief Return a begin iterator.
271  */
272 template <class T>
273 inline
274 constexpr typename span<T>::const_iterator
275 span<T>::begin() const noexcept
276 {
277  return m_ptr;
278 }
279 
280 
281 /**
282  * @brief Return an end iterator.
283  */
284 template <class T>
285 inline
286 constexpr typename span<T>::iterator
287 span<T>::end() noexcept
288 {
289  return m_ptr + m_size;
290 }
291 
292 
293 /**
294  * @brief Return an end iterator.
295  */
296 template <class T>
297 inline
298 constexpr typename span<T>::const_iterator
299 span<T>::end() const noexcept
300 {
301  return m_ptr + m_size;
302 }
303 
304 
305 /**
306  * @brief Return a begin reverse iterator.
307  */
308 template <class T>
309 inline
310 constexpr typename span<T>::reverse_iterator
311 span<T>::rbegin() noexcept
312 {
313  return reverse_iterator (end());
314 }
315 
316 
317 /**
318  * @brief Return a begin reverse iterator.
319  */
320 template <class T>
321 inline
322 constexpr typename span<T>::const_reverse_iterator
323 span<T>::rbegin() const noexcept
324 {
325  return const_reverse_iterator (end());
326 }
327 
328 
329 /**
330  * @brief Return an end reverse iterator.
331  */
332 template <class T>
333 inline
334 constexpr typename span<T>::reverse_iterator
335 span<T>::rend() noexcept
336 {
337  return reverse_iterator (begin());
338 }
339 
340 
341 /**
342  * @brief Return an end reverse iterator.
343  */
344 template <class T>
345 inline
346 constexpr typename span<T>::const_reverse_iterator
347 span<T>::rend() const noexcept
348 {
349  return const_reverse_iterator (begin());
350 }
351 
352 
353 /**
354  * @brief Return a subspan from the start.
355  * @param n Number of elements in the subspan.
356  */
357 template <class T>
358 inline
359 constexpr span<T>
360 span<T>::first (size_type n) noexcept
361 {
362  assert (n <= size());
363  return span (m_ptr, n);
364 }
365 
366 
367 /**
368  * @brief Return a subspan from the start.
369  * @param n Number of elements in the subspan.
370  */
371 template <class T>
372 inline
373 constexpr span<const T>
374 span<T>::first (size_type n) const noexcept
375 {
376  assert (n <= size());
377  const T* ptr = m_ptr;
378  return span<const T> (ptr, n);
379 }
380 
381 
382 /**
383  * @brief Return a subspan from the end.
384  * @param n Number of elements in the subspan.
385  */
386 template <class T>
387 inline
388 constexpr span<T>
389 span<T>::last (size_type n) noexcept
390 {
391  assert (n <= size());
392  return span (m_ptr + (size() - n), n);
393 }
394 
395 
396 /**
397  * @brief Return a subspan from the end.
398  * @param n Number of elements in the subspan.
399  */
400 template <class T>
401 inline
402 constexpr span<const T>
403 span<T>::last (size_type n) const noexcept
404 {
405  assert (n <= size());
406  const T* ptr = m_ptr;
407  return span<const T> (ptr + (size() - n), n);
408 }
409 
410 
411 /**
412  * @brief Return a subspan.
413  * @param offs Starting element of the subspan.
414  * @param n Number of elements in the subspan.
415  * If defaulted, take all remaining elements.
416  */
417 template <class T>
418 inline
419 constexpr span<T>
420 span<T>::subspan (size_type offs, size_type n /*= dynamic_extent*/) noexcept
421 {
422  assert (offs <= size());
423  if (n == dynamic_extent)
424  n = size() - offs;
425  else {
426  assert (n <= size());
427  assert (offs + n <= size());
428  }
429  return span (m_ptr + offs, n);
430 }
431 
432 
433 /**
434  * @brief Return a subspan.
435  * @param offs Starting element of the subspan.
436  * @param n Number of elements in the subspan.
437  * If defaulted, take all remaining elements.
438  */
439 template <class T>
440 inline
441 constexpr span<const T>
442 span<T>::subspan (size_type offs, size_type n /*= dynamic_extent*/) const noexcept
443 {
444  assert (offs <= size());
445  if (n == dynamic_extent)
446  n = size() - offs;
447  else {
448  assert (n <= size());
449  assert (offs + n <= size());
450  }
451  const T* ptr = m_ptr;
452  return span<const T> (ptr + offs, n);
453 }
454 
455 
456 } // namespace CxxUtils