/* Copyright 2019-2023 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_CORE_SPAN_HPP #define BOOST_CORE_SPAN_HPP #include #include #include #include namespace boost { constexpr std::size_t dynamic_extent = static_cast(-1); template class span; namespace detail { template struct span_convertible { static constexpr bool value = std::is_convertible::value; }; template struct span_capacity { static constexpr bool value = E == boost::dynamic_extent || E == N; }; template struct span_compatible { static constexpr bool value = span_capacity::value && span_convertible::value; }; template using span_uncvref = typename std::remove_cv::type>::type; template struct span_is_span { static constexpr bool value = false; }; template struct span_is_span > { static constexpr bool value = true; }; template struct span_is_array { static constexpr bool value = false; }; template struct span_is_array > { static constexpr bool value = true; }; template using span_ptr = decltype(boost::data(std::declval())); template struct span_data { }; template struct span_data >::value>::type> { typedef typename std::remove_pointer >::type type; }; template struct span_has_data { static constexpr bool value = false; }; template struct span_has_data::type, T>::value>::type> { static constexpr bool value = true; }; template struct span_has_size { static constexpr bool value = false; }; template struct span_has_size().size()), std::size_t>::value>::type> { static constexpr bool value = true; }; template struct span_is_range { static constexpr bool value = (std::is_const::value || std::is_lvalue_reference::value) && !span_is_span >::value && !span_is_array >::value && !std::is_array >::value && span_has_data::value && span_has_size::value; }; template struct span_implicit { static constexpr bool value = E == boost::dynamic_extent || N != boost::dynamic_extent; }; template struct span_copyable { static constexpr bool value = (N == boost::dynamic_extent || span_capacity::value) && span_convertible::value; }; template struct span_sub { static constexpr std::size_t value = E == boost::dynamic_extent ? boost::dynamic_extent : E - O; }; template struct span_store { constexpr span_store(T* p_, std::size_t) noexcept : p(p_) { } static constexpr std::size_t n = E; T* p; }; template struct span_store { constexpr span_store(T* p_, std::size_t n_) noexcept : p(p_) , n(n_) { } T* p; std::size_t n; }; template struct span_bytes { static constexpr std::size_t value = sizeof(T) * E; }; template struct span_bytes { static constexpr std::size_t value = boost::dynamic_extent; }; } /* detail */ template class span { public: typedef T element_type; typedef typename std::remove_cv::type value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef T* iterator; typedef const T* const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; static constexpr std::size_t extent = E; template::type = 0> constexpr span() noexcept : s_(0, 0) { } template::value, int>::type = 0> constexpr span(I* f, size_type c) : s_(f, c) { } template::value, int>::type = 0> explicit constexpr span(I* f, size_type c) : s_(f, c) { } template::value, int>::type = 0> constexpr span(I* f, L* l) : s_(f, l - f) { } template::value, int>::type = 0> explicit constexpr span(I* f, L* l) : s_(f, l - f) { } template::value, int>::type = 0> constexpr span(typename std::enable_if::type (&a)[N]) noexcept : s_(a, N) { } template::value, int>::type = 0> constexpr span(std::array& a) noexcept : s_(a.data(), N) { } template::value, int>::type = 0> constexpr span(const std::array& a) noexcept : s_(a.data(), N) { } template::value, int>::type = 0> constexpr span(R&& r) noexcept(noexcept(boost::data(r)) && noexcept(r.size())) : s_(boost::data(r), r.size()) { } template::value, int>::type = 0> explicit constexpr span(R&& r) noexcept(noexcept(boost::data(r)) && noexcept(r.size())) : s_(boost::data(r), r.size()) { } template::value && detail::span_copyable::value, int>::type = 0> constexpr span(const span& s) noexcept : s_(s.data(), s.size()) { } template::value && detail::span_copyable::value, int>::type = 0> explicit constexpr span(const span& s) noexcept : s_(s.data(), s.size()) { } template constexpr span first() const { static_assert(C <= E, "Count <= Extent"); return span(s_.p, C); } template constexpr span last() const { static_assert(C <= E, "Count <= Extent"); return span(s_.p + (s_.n - C), C); } template constexpr typename std::enable_if::value> >::type subspan() const { static_assert(O <= E, "Offset <= Extent"); return span::value>(s_.p + O, s_.n - O); } template constexpr typename std::enable_if >::type subspan() const { static_assert(O <= E && C <= E - O, "Offset <= Extent && Count <= Extent - Offset"); return span(s_.p + O, C); } constexpr span first(size_type c) const { return span(s_.p, c); } constexpr span last(size_type c) const { return span(s_.p + (s_.n - c), c); } constexpr span subspan(size_type o, size_type c = dynamic_extent) const { return span(s_.p + o, c == dynamic_extent ? s_.n - o : c); } constexpr size_type size() const noexcept { return s_.n; } constexpr size_type size_bytes() const noexcept { return s_.n * sizeof(T); } constexpr bool empty() const noexcept { return s_.n == 0; } constexpr reference operator[](size_type i) const { return s_.p[i]; } constexpr reference front() const { return *s_.p; } constexpr reference back() const { return s_.p[s_.n - 1]; } constexpr pointer data() const noexcept { return s_.p; } constexpr iterator begin() const noexcept { return s_.p; } constexpr iterator end() const noexcept { return s_.p + s_.n; } constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(s_.p + s_.n); } constexpr reverse_iterator rend() const noexcept { return reverse_iterator(s_.p); } constexpr const_iterator cbegin() const noexcept { return s_.p; } constexpr const_iterator cend() const noexcept { return s_.p + s_.n; } constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(s_.p + s_.n); } constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(s_.p); } private: detail::span_store s_; }; template constexpr std::size_t span::extent; #ifdef __cpp_deduction_guides template span(I*, L) -> span; template span(T(&)[N]) -> span; template span(std::array&) -> span; template span(const std::array&) -> span; template span(R&&) -> span::type>; template span(span) -> span; #endif #ifdef __cpp_lib_byte template inline span::value> as_bytes(span s) noexcept { return span::value>(reinterpret_cast(s.data()), s.size_bytes()); } template inline typename std::enable_if::value, span::value> >::type as_writable_bytes(span s) noexcept { return span::value>(reinterpret_cast(s.data()), s.size_bytes()); } #endif } /* boost */ #endif