#pragma once #include #include #include #include "utility.h" namespace vlc { static constexpr const std::size_t dynamic_extent = ~0u; namespace detail { template using void_t = void; template using bool_constant = std::integral_constant; template struct is_array_convertible : std::false_type {}; template struct is_array_convertible()))>::type>::value>::type > : std::is_convertible()))>::type(*)[], ElementType(*)[]>::type {}; } template class span { public: static const std::size_t extent = Extent; using element_type = T; using value_type = typename std::remove_cv::type; using pointer = T * ; using const_pointer = const T*; using reference = T & ; using const_reference = const T&; using iterator = pointer; using const_iterator = const_pointer; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using index_type = std::size_t; using difference_type = std::ptrdiff_t; template< std::size_t E = Extent, class = typename std::enable_if<(E == dynamic_extent) || (E == 0)>::type > span() noexcept {} span(pointer ptr, index_type count) : m_ptr(ptr), m_size(count) { assert(extent == dynamic_extent || count == extent); } span(pointer first, pointer last) : span(first, last - first) {} template ::value >::type > span(element_type(&arr)[N]) noexcept : span(arr, N) {} template &, element_type>::value >::type > span(std::array& arr) noexcept : span(vlc::data(arr), N) {} template &, element_type>::value >::type > span(const std::array& arr) noexcept : span(vlc::data(arr), N) {} template>::value && !std::is_array::value && detail::is_array_convertible::value >::type > span(Container& c) : span(vlc::data(c), vlc::size(c)) {} template>::value && !std::is_array::value && detail::is_array_convertible::value >::type > span(const Container& c) : span(vlc::data(c), vlc::size(c)) {} template::value >::type > span(const span& other) noexcept : m_ptr(other.data()), m_size(other.size()) {} span(const span& other) noexcept = default; span& operator = (const span& other) noexcept = default; pointer data() const noexcept { return m_ptr; } index_type size() const noexcept { return m_size; } index_type size_bytes() const noexcept { return size() * sizeof(element_type); } bool empty() const noexcept { return !size(); } iterator begin() const noexcept { return data(); } const_iterator cbegin() const noexcept { return data(); } iterator end() const noexcept { return data() + size(); } const_iterator cend() const noexcept { return data() + size(); } reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } friend iterator begin(span s) noexcept { return s.begin(); } friend iterator end(span s) noexcept { return s.end(); } reference front() const { return *begin(); } reference back() const { return *(end() - 1); } reference operator[](index_type idx) const { assert(idx < size()); return *(begin() + idx); } template span first() const { assert(Count <= size()); return { data(), Count }; } template span last() const { assert(Count <= size()); return { data() + (size() - Count), Count }; } template > auto subspan() const -> return_t { assert(Offset < size()); assert(Count == dynamic_extent || (Offset + Count <= size())); return { data() + Offset, Count != dynamic_extent ? Count : size() - Offset }; } span first(std::size_t count) const { assert(count <= size()); return { data(), count }; } span last(std::size_t count) const { assert(count <= size()); return { data() + (size() - count), count }; } auto subspan(std::size_t offset, std::size_t count = dynamic_extent) const -> span { assert(offset < size()); assert(count == dynamic_extent || (offset + count <= size())); return { data() + offset, count != dynamic_extent ? count : size() - offset }; } private: T* m_ptr = nullptr; index_type m_size = 0; }; template span make_span(span s) noexcept { return s; } template span make_span(T(&arr)[N]) noexcept { return { arr }; } template span make_span(std::array& arr) noexcept { return { arr }; } template span make_span(const std::array& arr) noexcept { return { arr }; } template span make_span(Container& cont) { return { cont }; } template span make_span(const Container& cont) { return { cont }; } }