#pragma once #include #include #include namespace BAN { template class Span { public: using value_type = T; using size_type = size_t; using iterator = IteratorSimple; using const_iterator = ConstIteratorSimple; private: template static inline constexpr bool can_init_from_v = is_same_v || is_same_v; public: Span() = default; Span(value_type* data, size_type size) : m_data(data) , m_size(size) { } template Span(const Span& other) requires can_init_from_v : m_data(other.m_data) , m_size(other.m_size) { } template Span(Span&& other) requires can_init_from_v : m_data(other.m_data) , m_size(other.m_size) { other.clear(); } template Span& operator=(const Span& other) requires can_init_from_v { m_data = other.m_data; m_size = other.m_size; return *this; } template Span& operator=(Span&& other) requires can_init_from_v { m_data = other.m_data; m_size = other.m_size; return *this; } iterator begin() { return iterator(m_data); } iterator end() { return iterator(m_data + m_size); } const_iterator begin() const { return const_iterator(m_data); } const_iterator end() const { return const_iterator(m_data + m_size); } value_type& operator[](size_type index) const { ASSERT(index < m_size); return m_data[index]; } value_type* data() const { ASSERT(m_data); return m_data; } bool empty() const { return m_size == 0; } size_type size() const { return m_size; } void clear() { m_data = nullptr; m_size = 0; } Span slice(size_type start, size_type length = ~size_type(0)) const { ASSERT(m_data); ASSERT(start <= m_size); if (length == ~size_type(0)) length = m_size - start; ASSERT(m_size - start >= length); return Span(m_data + start, length); } Span as_const() const { return *this; } private: value_type* m_data = nullptr; size_type m_size = 0; friend class Span; }; }