File indexing completed on 2026-11-08 10:11:47
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <cstddef>
0010 #include <type_traits>
0011
0012 #include "corecel/Macros.hh"
0013
0014 #include "detail/SpanImpl.hh"
0015
0016 #if !CELER_DEVICE_COMPILE
0017 # include "corecel/io/StreamableContainer.hh"
0018 #endif
0019
0020 namespace celeritas
0021 {
0022
0023
0024 constexpr std::size_t dynamic_extent = detail::dynamic_extent;
0025
0026
0027
0028
0029 template<class T, std::size_t N>
0030 class Array;
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 template<class T, std::size_t Extent = dynamic_extent>
0085 class Span
0086 {
0087 using SpanTraitsT = detail::SpanTraits<T>;
0088 static constexpr bool ndebug = !CELERITAS_DEBUG;
0089 static constexpr bool ndebug_or_dyn = (ndebug || Extent == dynamic_extent);
0090
0091 public:
0092
0093
0094 using element_type = typename SpanTraitsT::element_type;
0095 using value_type = std::remove_cv_t<element_type>;
0096 using size_type = std::size_t;
0097 using pointer = typename SpanTraitsT::pointer;
0098 using const_pointer = typename SpanTraitsT::const_pointer;
0099 using reference = typename SpanTraitsT::reference;
0100 using const_reference = typename SpanTraitsT::const_reference;
0101 using iterator = typename SpanTraitsT::iterator;
0102 using const_iterator = typename SpanTraitsT::const_iterator;
0103
0104
0105
0106 static constexpr std::size_t extent = Extent;
0107
0108 public:
0109
0110
0111
0112 constexpr Span() = default;
0113
0114
0115 CELER_CONSTEXPR_FUNCTION Span(pointer d,
0116 std::size_t s) noexcept(ndebug_or_dyn)
0117 : s_(d, s)
0118 {
0119 }
0120
0121
0122
0123
0124
0125
0126
0127
0128 template<class Iter>
0129 CELER_CONSTEXPR_FUNCTION Span(Iter first, Iter last) noexcept(ndebug_or_dyn)
0130 : s_(first == last ? nullptr : &(*first),
0131 static_cast<std::size_t>(last - first))
0132 {
0133 CELER_EXPECT(last >= first);
0134 }
0135
0136
0137 template<std::size_t N,
0138 std::enable_if_t<N == Extent || Extent == dynamic_extent, bool>
0139 = true>
0140 CELER_CONSTEXPR_FUNCTION Span(element_type (&arr)[N]) noexcept : s_(arr, N)
0141 {
0142 }
0143
0144
0145
0146
0147
0148
0149
0150
0151 template<class U,
0152 std::size_t N,
0153 std::enable_if_t<detail::is_array_convertible_v<U, T>
0154 && (N == Extent || Extent == dynamic_extent),
0155 bool> = true>
0156 CELER_CONSTEXPR_FUNCTION Span(Array<U, N>& arr) noexcept
0157 : s_(arr.data(), N)
0158 {
0159 }
0160
0161
0162
0163
0164
0165
0166
0167
0168 template<class U,
0169 std::size_t N,
0170 std::enable_if_t<detail::is_array_convertible_v<U const, T>
0171 && (N == Extent || Extent == dynamic_extent),
0172 bool> = true>
0173 CELER_CONSTEXPR_FUNCTION Span(Array<U, N> const& arr) noexcept
0174 : s_(arr.data(), N)
0175 {
0176 }
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 template<class U,
0191 std::size_t E2,
0192 std::enable_if_t<detail::is_array_convertible_v<U, T>
0193 && (E2 == Extent || Extent == dynamic_extent),
0194 bool> = true>
0195 CELER_CONSTEXPR_FUNCTION Span(Span<U, E2> other) noexcept(ndebug_or_dyn)
0196 : s_(other.data(), other.size())
0197 {
0198 }
0199
0200
0201
0202
0203
0204
0205 template<class U,
0206 std::size_t E2,
0207 std::enable_if_t<detail::is_array_convertible_v<U, T>
0208 && Extent != dynamic_extent && E2 == dynamic_extent,
0209 bool> = true>
0210 CELER_CONSTEXPR_FUNCTION explicit Span(Span<U, E2> other) noexcept(
0211 ndebug_or_dyn)
0212 : s_(other.data(), other.size())
0213 {
0214 }
0215
0216 CELER_DEFAULT_COPY_MOVE(Span);
0217 ~Span() = default;
0218
0219
0220
0221
0222
0223 CELER_CONSTEXPR_FUNCTION iterator begin() const { return s_.data; }
0224 CELER_CONSTEXPR_FUNCTION iterator end() const { return s_.data + s_.size; }
0225
0226
0227
0228
0229 CELER_CONSTEXPR_FUNCTION reference operator[](std::size_t i) const
0230 {
0231 return s_.data[i];
0232 }
0233 CELER_CONSTEXPR_FUNCTION reference front() const { return s_.data[0]; }
0234 CELER_CONSTEXPR_FUNCTION reference back() const
0235 {
0236 return s_.data[s_.size - 1];
0237 }
0238 CELER_CONSTEXPR_FUNCTION pointer data() const
0239 {
0240 return static_cast<pointer>(s_.data);
0241 }
0242
0243
0244
0245
0246 CELER_CONSTEXPR_FUNCTION bool empty() const { return s_.size == 0; }
0247 CELER_CONSTEXPR_FUNCTION std::size_t size() const { return s_.size; }
0248 CELER_CONSTEXPR_FUNCTION std::size_t size_bytes() const
0249 {
0250 return sizeof(element_type) * s_.size;
0251 }
0252
0253
0254
0255
0256 template<std::size_t Count>
0257 CELER_CONSTEXPR_FUNCTION Span<T, Count> first() const noexcept(ndebug)
0258 {
0259 CELER_EXPECT(Count == 0 || Count <= this->size());
0260 return {this->data(), Count};
0261 }
0262 CELER_CONSTEXPR_FUNCTION Span<T, dynamic_extent> first(
0263 std::size_t count) const noexcept(ndebug)
0264 {
0265 CELER_EXPECT(count <= this->size());
0266 return {this->data(), count};
0267 }
0268
0269 template<std::size_t Offset, std::size_t Count = dynamic_extent>
0270 CELER_CONSTEXPR_FUNCTION
0271 Span<T, detail::subspan_extent(Extent, Offset, Count)>
0272 subspan() const noexcept(ndebug)
0273 {
0274 CELER_EXPECT((Count == dynamic_extent) || (Offset == 0 && Count == 0)
0275 || (Offset + Count <= this->size()));
0276 return {this->data() + Offset,
0277 detail::subspan_size(this->size(), Offset, Count)};
0278 }
0279 CELER_CONSTEXPR_FUNCTION Span<T, dynamic_extent> subspan(
0280 std::size_t offset, std::size_t count = dynamic_extent) const
0281 noexcept(ndebug)
0282 {
0283 CELER_EXPECT(offset + count <= this->size());
0284 return {this->data() + offset,
0285 detail::subspan_size(this->size(), offset, count)};
0286 }
0287
0288 template<std::size_t Count>
0289 CELER_CONSTEXPR_FUNCTION Span<T, Count> last() const noexcept(ndebug)
0290 {
0291 CELER_EXPECT(Count == 0 || Count <= this->size());
0292 return {this->data() + this->size() - Count, Count};
0293 }
0294 CELER_CONSTEXPR_FUNCTION Span<T, dynamic_extent> last(
0295 std::size_t count) const noexcept(ndebug)
0296 {
0297 CELER_EXPECT(count <= this->size());
0298 return {this->data() + this->size() - count, count};
0299 }
0300
0301
0302 private:
0303
0304 detail::SpanImpl<T, Extent> s_;
0305 };
0306
0307
0308
0309
0310
0311
0312 template<class T>
0313 CELER_CTAD_FUNCTION Span(T*, std::size_t) -> Span<T>;
0314
0315
0316 template<class Iter>
0317 CELER_CTAD_FUNCTION Span(Iter, Iter)
0318 -> Span<typename std::iterator_traits<Iter>::value_type>;
0319
0320
0321 template<class T, std::size_t N>
0322 CELER_CTAD_FUNCTION Span(T (&)[N]) -> Span<T, N>;
0323
0324
0325 template<class T, std::size_t N>
0326 CELER_CTAD_FUNCTION Span(Array<T, N>&) -> Span<T, N>;
0327
0328
0329 template<class T, std::size_t N>
0330 CELER_CTAD_FUNCTION Span(Array<T, N> const&) -> Span<T const, N>;
0331
0332
0333
0334
0335
0336 template<class T, std::size_t N>
0337 CELER_CONSTEXPR_FUNCTION Span<T, N> make_span(Array<T, N>& x)
0338 {
0339 return {x.data(), N};
0340 }
0341
0342
0343
0344 template<class T, std::size_t N>
0345 CELER_CONSTEXPR_FUNCTION Span<T const, N> make_span(Array<T, N> const& x)
0346 {
0347 return {x.data(), N};
0348 }
0349
0350
0351
0352 template<class T, std::size_t N>
0353 CELER_CONSTEXPR_FUNCTION Span<T, N> make_span(T (&arr)[N])
0354 {
0355 return {arr, N};
0356 }
0357
0358
0359
0360 template<class T>
0361 CELER_CONSTEXPR_FUNCTION Span<typename T::value_type> make_span(T& cont)
0362 {
0363 return {cont.data(), cont.size()};
0364 }
0365
0366
0367
0368 template<class T>
0369 CELER_CONSTEXPR_FUNCTION Span<typename T::value_type const> make_span(
0370 T const& cont)
0371 {
0372 return {cont.data(), cont.size()};
0373 }
0374
0375 #if !CELER_DEVICE_COMPILE
0376
0377
0378
0379
0380 template<class T, std::size_t N>
0381 CELER_FORCEINLINE std::ostream& operator<<(std::ostream& os,
0382 Span<T, N> const& s)
0383 {
0384 os << StreamableContainer{s.data(), s.size()};
0385 return os;
0386 }
0387 #endif
0388
0389
0390 }