104 lines
2.1 KiB
C++
104 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include <iterator>
|
|
|
|
namespace psemek::util
|
|
{
|
|
|
|
template <typename T>
|
|
struct span
|
|
{
|
|
using value_type = std::remove_cv_t<T>;
|
|
using size_type = std::size_t;
|
|
using difference_type = std::ptrdiff_t;
|
|
using pointer = T *;
|
|
using const_pointer = const T *;
|
|
using reference = T &;
|
|
using const_reference = const T &;
|
|
using iterator = pointer;
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
|
|
T * p_begin = nullptr;
|
|
T * p_end = nullptr;
|
|
|
|
span() = default;
|
|
span(span const &) = default;
|
|
span(span && other)
|
|
: p_begin{other.p_begin}
|
|
, p_end{other.p_end}
|
|
{
|
|
other.reset();
|
|
}
|
|
|
|
span(T * begin, T * end)
|
|
: p_begin{begin}
|
|
, p_end{end}
|
|
{}
|
|
|
|
template <std::size_t N>
|
|
span(T (&a)[N])
|
|
: p_begin{a}
|
|
, p_end{a + N}
|
|
{}
|
|
|
|
template <typename Container>
|
|
span(Container & a)
|
|
: p_begin{a.data()}
|
|
, p_end{a.data() + a.size()}
|
|
{}
|
|
|
|
span & operator =(span const &) = default;
|
|
span & operator =(span && other)
|
|
{
|
|
if (this == &other)
|
|
return *this;
|
|
|
|
p_begin = other.p_begin;
|
|
p_end = other.p_end;
|
|
other.reset();
|
|
return *this;
|
|
}
|
|
|
|
T * data() const { return p_begin; }
|
|
|
|
T * begin() const { return p_begin; }
|
|
T * end() const { return p_end; }
|
|
|
|
difference_type size() const { return p_end - p_begin; }
|
|
|
|
bool empty() const { return p_begin == p_end; }
|
|
|
|
reverse_iterator rbegin() const { return reverse_iterator(p_end); }
|
|
reverse_iterator rend() const { return reverse_iterator(p_begin); }
|
|
|
|
T & front() const { return *p_begin; }
|
|
T & back() const { return *(p_end - 1); }
|
|
|
|
void reset()
|
|
{
|
|
p_begin = nullptr;
|
|
p_end = nullptr;
|
|
}
|
|
|
|
T & operator[] (size_type i) const { return p_begin[i]; }
|
|
};
|
|
|
|
template <typename T>
|
|
bool operator == (span<T> const & s1, span<T> const & s2)
|
|
{
|
|
return (s1.begin() == s2.begin()) && (s1.end() == s2.end());
|
|
}
|
|
|
|
template <typename T>
|
|
bool operator != (span<T> const & s1, span<T> const & s2)
|
|
{
|
|
return !(s1 == s2);
|
|
}
|
|
|
|
template <typename T, typename H>
|
|
span<T> cast(span<H> const & s)
|
|
{
|
|
return span<T>{reinterpret_cast<T *>(s.begin()), reinterpret_cast<T *>(s.end())};
|
|
}
|
|
|
|
}
|