diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2020-06-04 10:46:52 -0700 |
---|---|---|
committer | Pieter Wuille <pieter@wuille.net> | 2020-06-17 15:10:50 -0700 |
commit | 26acc8dd9b512f220c1facdba2c5de7976d3c258 (patch) | |
tree | 4c4d4a8ec5b2260604cbacaecf9d6d92f2f9edf0 /src/span.h | |
parent | 2676aeadfa0e43dcaaccc4720623cdfe0beed528 (diff) |
Add sanity check asserts to span when -DDEBUG
Diffstat (limited to 'src/span.h')
-rw-r--r-- | src/span.h | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/src/span.h b/src/span.h index d5fec462e1..4931507719 100644 --- a/src/span.h +++ b/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; |