#pragma once #include #include #include #include // non owning view template struct Span final { const T* ptr {nullptr}; uint64_t size {0}; constexpr Span(const Span&) = default; constexpr Span(Span&&) = default; constexpr Span(void) {} constexpr Span(const T* ptr_, uint64_t size_) : ptr(ptr_), size(size_) {} constexpr Span(T* ptr_, uint64_t size_) : ptr(ptr_), size(size_) {} constexpr explicit Span(const std::vector& vec) : ptr(vec.data()), size(vec.size()) {} constexpr explicit Span(std::vector& vec) : ptr(vec.data()), size(vec.size()) {} template constexpr explicit Span(const std::array& arr) : ptr(arr.data()), size(arr.size()) {} template constexpr explicit Span(std::array& arr) : ptr(arr.data()), size(arr.size()) {} Span& operator=(const Span& other) { ptr = other.ptr; size = other.size; return *this; } explicit operator std::vector() const { return std::vector{ptr, ptr+size}; } constexpr const T& operator[](uint64_t i) const { if (i > size) { throw std::out_of_range("accessed span out of range"); } return ptr[i]; } constexpr bool operator==(const Span& other) const { if (empty() || size != other.size) { return false; } for (uint64_t i = 0; i < size; i++) { if ((*this)[i] != other[i]) { return false; } } return true; } #if 0 constexpr T& operator[](uint64_t i) { if (i > size) { throw std::out_of_range("accessed span out of range"); } return ptr[i]; } #endif constexpr const T* cbegin(void) const { return ptr; } constexpr const T* cend(void) const { return ptr+size; } constexpr const T* begin(void) const { return ptr; } constexpr const T* end(void) const { return ptr+size; } constexpr bool empty(void) const { return ptr == nullptr || size == 0; } }; // useful alias using ByteSpan = Span; using ConstByteSpan = Span; // TODO: make use of?