File indexing completed on 2025-12-16 09:45:07
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_CORE_SPAN_HPP
0009 #define BOOST_CORE_SPAN_HPP
0010
0011 #include <boost/core/detail/assert.hpp>
0012 #include <boost/core/data.hpp>
0013 #include <array>
0014 #include <iterator>
0015 #include <type_traits>
0016
0017 namespace boost {
0018
0019 constexpr std::size_t dynamic_extent = static_cast<std::size_t>(-1);
0020
0021 template<class T, std::size_t E = dynamic_extent>
0022 class span;
0023
0024 namespace detail {
0025
0026 template<class U, class T>
0027 struct span_convertible {
0028 static constexpr bool value = std::is_convertible<U(*)[], T(*)[]>::value;
0029 };
0030
0031 template<std::size_t E, std::size_t N>
0032 struct span_capacity {
0033 static constexpr bool value = E == boost::dynamic_extent || E == N;
0034 };
0035
0036 template<class T, std::size_t E, class U, std::size_t N>
0037 struct span_compatible {
0038 static constexpr bool value = span_capacity<E, N>::value &&
0039 span_convertible<U, T>::value;
0040 };
0041
0042 template<class T>
0043 using span_uncvref = typename std::remove_cv<typename
0044 std::remove_reference<T>::type>::type;
0045
0046 template<class>
0047 struct span_is_span {
0048 static constexpr bool value = false;
0049 };
0050
0051 template<class T, std::size_t E>
0052 struct span_is_span<boost::span<T, E> > {
0053 static constexpr bool value = true;
0054 };
0055
0056 template<class T>
0057 struct span_is_array {
0058 static constexpr bool value = false;
0059 };
0060
0061 template<class T, std::size_t N>
0062 struct span_is_array<std::array<T, N> > {
0063 static constexpr bool value = true;
0064 };
0065
0066 template<class T>
0067 using span_ptr = decltype(boost::data(std::declval<T&>()));
0068
0069 template<class, class = void>
0070 struct span_data { };
0071
0072 template<class T>
0073 struct span_data<T,
0074 typename std::enable_if<std::is_pointer<span_ptr<T> >::value>::type> {
0075 typedef typename std::remove_pointer<span_ptr<T> >::type type;
0076 };
0077
0078 template<class, class, class = void>
0079 struct span_has_data {
0080 static constexpr bool value = false;
0081 };
0082
0083 template<class R, class T>
0084 struct span_has_data<R, T, typename std::enable_if<span_convertible<typename
0085 span_data<R>::type, T>::value>::type> {
0086 static constexpr bool value = true;
0087 };
0088
0089 template<class, class = void>
0090 struct span_has_size {
0091 static constexpr bool value = false;
0092 };
0093
0094 template<class R>
0095 struct span_has_size<R, typename
0096 std::enable_if<std::is_convertible<decltype(std::declval<R&>().size()),
0097 std::size_t>::value>::type> {
0098 static constexpr bool value = true;
0099 };
0100
0101 template<class R, class T>
0102 struct span_is_range {
0103 static constexpr bool value = (std::is_const<T>::value ||
0104 std::is_lvalue_reference<R>::value) &&
0105 !span_is_span<span_uncvref<R> >::value &&
0106 !span_is_array<span_uncvref<R> >::value &&
0107 !std::is_array<span_uncvref<R> >::value &&
0108 span_has_data<R, T>::value &&
0109 span_has_size<R>::value;
0110 };
0111
0112 template<std::size_t E, std::size_t N>
0113 struct span_implicit {
0114 static constexpr bool value = E == boost::dynamic_extent ||
0115 N != boost::dynamic_extent;
0116 };
0117
0118 template<class T, std::size_t E, class U, std::size_t N>
0119 struct span_copyable {
0120 static constexpr bool value = (N == boost::dynamic_extent ||
0121 span_capacity<E, N>::value) && span_convertible<U, T>::value;
0122 };
0123
0124 template<std::size_t E, std::size_t O>
0125 struct span_sub {
0126 static constexpr std::size_t value = E == boost::dynamic_extent ?
0127 boost::dynamic_extent : E - O;
0128 };
0129
0130 template<class T, std::size_t E>
0131 struct span_store {
0132 constexpr span_store(T* p_, std::size_t) noexcept
0133 : p(p_) { }
0134 static constexpr std::size_t n = E;
0135 T* p;
0136 };
0137
0138 template<class T>
0139 struct span_store<T, boost::dynamic_extent> {
0140 constexpr span_store(T* p_, std::size_t n_) noexcept
0141 : p(p_)
0142 , n(n_) { }
0143 T* p;
0144 std::size_t n;
0145 };
0146
0147 template<class T, std::size_t E>
0148 struct span_bytes {
0149 static constexpr std::size_t value = sizeof(T) * E;
0150 };
0151
0152 template<class T>
0153 struct span_bytes<T, boost::dynamic_extent> {
0154 static constexpr std::size_t value = boost::dynamic_extent;
0155 };
0156
0157 }
0158
0159 template<class T, std::size_t E>
0160 class span {
0161 public:
0162 typedef T element_type;
0163 typedef typename std::remove_cv<T>::type value_type;
0164 typedef std::size_t size_type;
0165 typedef std::ptrdiff_t difference_type;
0166 typedef T* pointer;
0167 typedef const T* const_pointer;
0168 typedef T& reference;
0169 typedef const T& const_reference;
0170 typedef T* iterator;
0171 typedef const T* const_iterator;
0172 typedef std::reverse_iterator<T*> reverse_iterator;
0173 typedef std::reverse_iterator<const T*> const_reverse_iterator;
0174
0175 static constexpr std::size_t extent = E;
0176
0177 template<std::size_t N = E,
0178 typename std::enable_if<N == dynamic_extent || N == 0, int>::type = 0>
0179 constexpr span() noexcept
0180 : s_(0, 0) { }
0181
0182 template<class I,
0183 typename std::enable_if<E == dynamic_extent &&
0184 detail::span_convertible<I, T>::value, int>::type = 0>
0185 constexpr span(I* f, size_type c)
0186 : s_(f, c) { }
0187
0188 template<class I,
0189 typename std::enable_if<E != dynamic_extent &&
0190 detail::span_convertible<I, T>::value, int>::type = 0>
0191 explicit constexpr span(I* f, size_type c)
0192 : s_(f, c) { }
0193
0194 template<class I, class L,
0195 typename std::enable_if<E == dynamic_extent &&
0196 detail::span_convertible<I, T>::value, int>::type = 0>
0197 constexpr span(I* f, L* l)
0198 : s_(f, l - f) { }
0199
0200 template<class I, class L,
0201 typename std::enable_if<E != dynamic_extent &&
0202 detail::span_convertible<I, T>::value, int>::type = 0>
0203 explicit constexpr span(I* f, L* l)
0204 : s_(f, l - f) { }
0205
0206 template<std::size_t N,
0207 typename std::enable_if<detail::span_capacity<E, N>::value,
0208 int>::type = 0>
0209 constexpr span(typename std::enable_if<true, T>::type (&a)[N]) noexcept
0210 : s_(a, N) { }
0211
0212 template<class U, std::size_t N,
0213 typename std::enable_if<detail::span_compatible<T, E, U, N>::value,
0214 int>::type = 0>
0215 constexpr span(std::array<U, N>& a) noexcept
0216 : s_(a.data(), N) { }
0217
0218 template<class U, std::size_t N,
0219 typename std::enable_if<detail::span_compatible<T, E, const U,
0220 N>::value, int>::type = 0>
0221 constexpr span(const std::array<U, N>& a) noexcept
0222 : s_(a.data(), N) { }
0223
0224 template<class R,
0225 typename std::enable_if<E == dynamic_extent &&
0226 detail::span_is_range<R, T>::value, int>::type = 0>
0227 constexpr span(R&& r) noexcept(noexcept(boost::data(r)) &&
0228 noexcept(r.size()))
0229 : s_(boost::data(r), r.size()) { }
0230
0231 template<class R,
0232 typename std::enable_if<E != dynamic_extent &&
0233 detail::span_is_range<R, T>::value, int>::type = 0>
0234 explicit constexpr span(R&& r) noexcept(noexcept(boost::data(r)) &&
0235 noexcept(r.size()))
0236 : s_(boost::data(r), r.size()) { }
0237
0238 template<class U, std::size_t N,
0239 typename std::enable_if<detail::span_implicit<E, N>::value &&
0240 detail::span_copyable<T, E, U, N>::value, int>::type = 0>
0241 constexpr span(const span<U, N>& s) noexcept
0242 : s_(s.data(), s.size()) { }
0243
0244 template<class U, std::size_t N,
0245 typename std::enable_if<!detail::span_implicit<E, N>::value &&
0246 detail::span_copyable<T, E, U, N>::value, int>::type = 0>
0247 explicit constexpr span(const span<U, N>& s) noexcept
0248 : s_(s.data(), s.size()) { }
0249
0250 template<std::size_t C>
0251 constexpr span<T, C> first() const {
0252 static_assert(C <= E, "Count <= Extent");
0253 return span<T, C>(s_.p, C);
0254 }
0255
0256 template<std::size_t C>
0257 constexpr span<T, C> last() const {
0258 static_assert(C <= E, "Count <= Extent");
0259 return span<T, C>(s_.p + (s_.n - C), C);
0260 }
0261
0262 template<std::size_t O, std::size_t C = dynamic_extent>
0263 constexpr typename std::enable_if<C == dynamic_extent,
0264 span<T, detail::span_sub<E, O>::value> >::type subspan() const {
0265 static_assert(O <= E, "Offset <= Extent");
0266 return span<T, detail::span_sub<E, O>::value>(s_.p + O, s_.n - O);
0267 }
0268
0269 template<std::size_t O, std::size_t C = dynamic_extent>
0270 constexpr typename std::enable_if<C != dynamic_extent,
0271 span<T, C> >::type subspan() const {
0272 static_assert(O <= E && C <= E - O,
0273 "Offset <= Extent && Count <= Extent - Offset");
0274 return span<T, C>(s_.p + O, C);
0275 }
0276
0277 constexpr span<T, dynamic_extent> first(size_type c) const {
0278 return BOOST_CORE_DETAIL_ASSERT(c <= size()),
0279 span<T, dynamic_extent>(s_.p, c);
0280 }
0281
0282 constexpr span<T, dynamic_extent> last(size_type c) const {
0283 return BOOST_CORE_DETAIL_ASSERT(c <= size()),
0284 span<T, dynamic_extent>(s_.p + (s_.n - c), c);
0285 }
0286
0287 constexpr span<T, dynamic_extent> subspan(size_type o,
0288 size_type c = dynamic_extent) const {
0289 return BOOST_CORE_DETAIL_ASSERT(o <= size() &&
0290 (c == dynamic_extent || c + o <= size())),
0291 span<T, dynamic_extent>(s_.p + o,
0292 c == dynamic_extent ? s_.n - o : c);
0293 }
0294
0295 constexpr size_type size() const noexcept {
0296 return s_.n;
0297 }
0298
0299 constexpr size_type size_bytes() const noexcept {
0300 return s_.n * sizeof(T);
0301 }
0302
0303 constexpr bool empty() const noexcept {
0304 return s_.n == 0;
0305 }
0306
0307 constexpr reference operator[](size_type i) const {
0308 return BOOST_CORE_DETAIL_ASSERT(i < size()), s_.p[i];
0309 }
0310
0311 constexpr reference front() const {
0312 return BOOST_CORE_DETAIL_ASSERT(!empty()), *s_.p;
0313 }
0314
0315 constexpr reference back() const {
0316 return BOOST_CORE_DETAIL_ASSERT(!empty()), s_.p[s_.n - 1];
0317 }
0318
0319 constexpr pointer data() const noexcept {
0320 return s_.p;
0321 }
0322
0323 constexpr iterator begin() const noexcept {
0324 return s_.p;
0325 }
0326
0327 constexpr iterator end() const noexcept {
0328 return s_.p + s_.n;
0329 }
0330
0331 constexpr reverse_iterator rbegin() const noexcept {
0332 return reverse_iterator(s_.p + s_.n);
0333 }
0334
0335 constexpr reverse_iterator rend() const noexcept {
0336 return reverse_iterator(s_.p);
0337 }
0338
0339 constexpr const_iterator cbegin() const noexcept {
0340 return s_.p;
0341 }
0342
0343 constexpr const_iterator cend() const noexcept {
0344 return s_.p + s_.n;
0345 }
0346
0347 constexpr const_reverse_iterator crbegin() const noexcept {
0348 return const_reverse_iterator(s_.p + s_.n);
0349 }
0350
0351 constexpr const_reverse_iterator crend() const noexcept {
0352 return const_reverse_iterator(s_.p);
0353 }
0354
0355 private:
0356 detail::span_store<T, E> s_;
0357 };
0358
0359 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
0360 template<class T, std::size_t E>
0361 constexpr std::size_t span<T, E>::extent;
0362 #endif
0363
0364 #ifdef __cpp_deduction_guides
0365 template<class I, class L>
0366 span(I*, L) -> span<I>;
0367
0368 template<class T, std::size_t N>
0369 span(T(&)[N]) -> span<T, N>;
0370
0371 template<class T, std::size_t N>
0372 span(std::array<T, N>&) -> span<T, N>;
0373
0374 template<class T, std::size_t N>
0375 span(const std::array<T, N>&) -> span<const T, N>;
0376
0377 template<class R>
0378 span(R&&) -> span<typename detail::span_data<R>::type>;
0379
0380 template<class T, std::size_t E>
0381 span(span<T, E>) -> span<T, E>;
0382 #endif
0383
0384 #ifdef __cpp_lib_byte
0385 template<class T, std::size_t E>
0386 inline span<const std::byte, detail::span_bytes<T, E>::value>
0387 as_bytes(span<T, E> s) noexcept
0388 {
0389 return span<const std::byte, detail::span_bytes<T,
0390 E>::value>(reinterpret_cast<const std::byte*>(s.data()),
0391 s.size_bytes());
0392 }
0393
0394 template<class T, std::size_t E>
0395 inline typename std::enable_if<!std::is_const<T>::value,
0396 span<std::byte, detail::span_bytes<T, E>::value> >::type
0397 as_writable_bytes(span<T, E> s) noexcept
0398 {
0399 return span<std::byte, detail::span_bytes<T,
0400 E>::value>(reinterpret_cast<std::byte*>(s.data()), s.size_bytes());
0401 }
0402 #endif
0403
0404 }
0405
0406 #endif