Add sanity check asserts to span when -DDEBUG
This commit is contained in:
parent
2676aeadfa
commit
26acc8dd9b
1 changed files with 48 additions and 10 deletions
58
src/span.h
58
src/span.h
|
@ -10,6 +10,14 @@
|
|||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define CONSTEXPR_IF_NOT_DEBUG
|
||||
#define ASSERT_IF_DEBUG(x) assert((x))
|
||||
#else
|
||||
#define CONSTEXPR_IF_NOT_DEBUG constexpr
|
||||
#define ASSERT_IF_DEBUG(x)
|
||||
#endif
|
||||
|
||||
/** A Span is an object that can refer to a contiguous sequence of objects.
|
||||
*
|
||||
* It implements a subset of C++20's std::span.
|
||||
|
@ -37,7 +45,10 @@ public:
|
|||
* which is hard to implement without std::address_of.
|
||||
*/
|
||||
template <typename T, typename std::enable_if<std::is_convertible<T (*)[], C (*)[]>::value, int>::type = 0>
|
||||
constexpr Span(T* begin, T* end) noexcept : m_data(begin), m_size(end - begin) {}
|
||||
CONSTEXPR_IF_NOT_DEBUG Span(T* begin, T* end) noexcept : m_data(begin), m_size(end - begin)
|
||||
{
|
||||
ASSERT_IF_DEBUG(end >= begin);
|
||||
}
|
||||
|
||||
/** Implicit conversion of spans between compatible types.
|
||||
*
|
||||
|
@ -73,15 +84,42 @@ public:
|
|||
constexpr C* data() const noexcept { return m_data; }
|
||||
constexpr C* begin() const noexcept { return m_data; }
|
||||
constexpr C* end() const noexcept { return m_data + m_size; }
|
||||
constexpr C& front() const noexcept { return m_data[0]; }
|
||||
constexpr C& back() const noexcept { return m_data[m_size - 1]; }
|
||||
CONSTEXPR_IF_NOT_DEBUG C& front() const noexcept
|
||||
{
|
||||
ASSERT_IF_DEBUG(size() > 0);
|
||||
return m_data[0];
|
||||
}
|
||||
CONSTEXPR_IF_NOT_DEBUG C& back() const noexcept
|
||||
{
|
||||
ASSERT_IF_DEBUG(size() > 0);
|
||||
return m_data[m_size - 1];
|
||||
}
|
||||
constexpr std::size_t size() const noexcept { return m_size; }
|
||||
constexpr C& operator[](std::size_t pos) const noexcept { return m_data[pos]; }
|
||||
|
||||
constexpr Span<C> subspan(std::size_t offset) const noexcept { return Span<C>(m_data + offset, m_size - offset); }
|
||||
constexpr Span<C> subspan(std::size_t offset, std::size_t count) const noexcept { return Span<C>(m_data + offset, count); }
|
||||
constexpr Span<C> first(std::size_t count) const noexcept { return Span<C>(m_data, count); }
|
||||
constexpr Span<C> last(std::size_t count) const noexcept { return Span<C>(m_data + m_size - count, count); }
|
||||
CONSTEXPR_IF_NOT_DEBUG C& operator[](std::size_t pos) const noexcept
|
||||
{
|
||||
ASSERT_IF_DEBUG(size() > pos);
|
||||
return m_data[pos];
|
||||
}
|
||||
CONSTEXPR_IF_NOT_DEBUG Span<C> subspan(std::size_t offset) const noexcept
|
||||
{
|
||||
ASSERT_IF_DEBUG(size() >= offset);
|
||||
return Span<C>(m_data + offset, m_size - offset);
|
||||
}
|
||||
CONSTEXPR_IF_NOT_DEBUG Span<C> subspan(std::size_t offset, std::size_t count) const noexcept
|
||||
{
|
||||
ASSERT_IF_DEBUG(size() >= offset + count);
|
||||
return Span<C>(m_data + offset, count);
|
||||
}
|
||||
CONSTEXPR_IF_NOT_DEBUG Span<C> first(std::size_t count) const noexcept
|
||||
{
|
||||
ASSERT_IF_DEBUG(size() >= count);
|
||||
return Span<C>(m_data, count);
|
||||
}
|
||||
CONSTEXPR_IF_NOT_DEBUG Span<C> last(std::size_t count) const noexcept
|
||||
{
|
||||
ASSERT_IF_DEBUG(size() >= count);
|
||||
return Span<C>(m_data + m_size - count, count);
|
||||
}
|
||||
|
||||
friend constexpr bool operator==(const Span& a, const Span& b) noexcept { return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); }
|
||||
friend constexpr bool operator!=(const Span& a, const Span& b) noexcept { return !(a == b); }
|
||||
|
@ -106,7 +144,7 @@ template <typename T>
|
|||
T& SpanPopBack(Span<T>& span)
|
||||
{
|
||||
size_t size = span.size();
|
||||
assert(size > 0);
|
||||
ASSERT_IF_DEBUG(size > 0);
|
||||
T& back = span[size - 1];
|
||||
span = Span<T>(span.data(), size - 1);
|
||||
return back;
|
||||
|
|
Loading…
Reference in a new issue