#ifndef EDGEFIRST_STDLIB_SPAN_HPP
#define EDGEFIRST_STDLIB_SPAN_HPP
#include <cstddef>
#if __has_include(<version>)
#include <version>
#endif
#if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
# include <span>
namespace edgefirst::stdlib {
template <class T, std::size_t E = std::dynamic_extent>
using span = std::span<T, E>;
using std::dynamic_extent;
}
#else
namespace edgefirst::stdlib {
inline constexpr std::size_t dynamic_extent = static_cast<std::size_t>(-1);
template <class T>
class span {
public:
constexpr span() noexcept = default;
constexpr span(T* p, std::size_t n) noexcept : data_(p), size_(n) {}
constexpr span(T* first, T* last) noexcept
: data_(first), size_(static_cast<std::size_t>(last - first)) {}
constexpr span(span const&) noexcept = default;
constexpr span& operator=(span const&) noexcept = default;
[[nodiscard]] constexpr T* data() const noexcept { return data_; }
[[nodiscard]] constexpr std::size_t size() const noexcept { return size_; }
[[nodiscard]] constexpr std::size_t size_bytes() const noexcept {
return size_ * sizeof(T);
}
[[nodiscard]] constexpr bool empty() const noexcept { return size_ == 0; }
[[nodiscard]] constexpr T& operator[](std::size_t i) const noexcept {
return data_[i];
}
[[nodiscard]] constexpr T* begin() const noexcept { return data_; }
[[nodiscard]] constexpr T* end() const noexcept { return data_ + size_; }
[[nodiscard]] constexpr span<T> subspan(
std::size_t offset,
std::size_t count = dynamic_extent) const noexcept
{
std::size_t n = (count == dynamic_extent) ? (size_ - offset) : count;
return span<T>(data_ + offset, n);
}
private:
T* data_ = nullptr;
std::size_t size_ = 0;
};
}
#endif
#endif