/* * mptSpan.h * --------- * Purpose: C++20 span. * Notes : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ #pragma once #include "BuildSettings.h" #include "mptBaseTypes.h" #if MPT_CXX_AT_LEAST(20) #include #include #else // !C++20 #include #include #include #endif // C++20 OPENMPT_NAMESPACE_BEGIN namespace mpt { #if MPT_CXX_AT_LEAST(20) using std::span; #else // !C++20 // Simplified version of gsl::span. // Non-owning read-only or read-write view into a contiguous block of T // objects, i.e. equivalent to a (beg,end) or (data,size) tuple. // Can eventually be replaced without further modifications with a full C++20 // std::span. template class span { public: using element_type = T; using value_type = typename std::remove_cv::type; using index_type = std::size_t; 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 difference_type = typename std::iterator_traits::difference_type; private: T * m_beg; T * m_end; public: span() noexcept : m_beg(nullptr), m_end(nullptr) { } span(pointer beg, pointer end) : m_beg(beg), m_end(end) { } span(pointer data, index_type size) : m_beg(data), m_end(data + size) { } template span(element_type (&arr)[N]) : m_beg(arr), m_end(arr + N) { } template span(std::array &arr) : m_beg(arr.data()), m_end(arr.data() + arr.size()) { } template span(const std::array &arr) : m_beg(arr.data()), m_end(arr.data() + arr.size()) { } template span(Cont &cont) : m_beg(std::data(cont)), m_end(std::data(cont) + std::size(cont)) { } span(const span &other) : m_beg(other.begin()), m_end(other.end()) { } template span(const span &other) : m_beg(other.begin()), m_end(other.end()) { } span & operator = (const span & other) noexcept = default; iterator begin() const { return iterator(m_beg); } iterator end() const { return iterator(m_end); } const_iterator cbegin() const { return const_iterator(begin()); } const_iterator cend() const { return const_iterator(end()); } operator bool () const noexcept { return m_beg != nullptr; } reference operator[](index_type index) { return at(index); } const_reference operator[](index_type index) const { return at(index); } bool operator==(span const & other) const noexcept { return size() == other.size() && (m_beg == other.m_beg || std::equal(begin(), end(), other.begin())); } bool operator!=(span const & other) const noexcept { return !(*this == other); } reference at(index_type index) { return m_beg[index]; } const_reference at(index_type index) const { return m_beg[index]; } pointer data() const noexcept { return m_beg; } bool empty() const noexcept { return size() == 0; } index_type size() const noexcept { return static_cast(std::distance(m_beg, m_end)); } index_type length() const noexcept { return size(); } }; // class span #endif // C++20 template inline span as_span(T * beg, T * end) { return span(beg, end); } template inline span as_span(T * data, std::size_t size) { return span(data, size); } template inline span as_span(T (&arr)[N]) { return span(std::begin(arr), std::end(arr)); } template inline span as_span(std::array & cont) { return span(cont); } template inline span as_span(const std::array & cont) { return span(cont); } } // namespace mpt OPENMPT_NAMESPACE_END