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