1010#include < algorithm>
1111#include < assert.h>
1212
13+ #ifdef DEBUG
14+ #define CONSTEXPR_IF_NOT_DEBUG
15+ #define ASSERT_IF_DEBUG (x ) assert ((x))
16+ #else
17+ #define CONSTEXPR_IF_NOT_DEBUG constexpr
18+ #define ASSERT_IF_DEBUG (x )
19+ #endif
20+
1321/* * A Span is an object that can refer to a contiguous sequence of objects.
1422 *
1523 * It implements a subset of C++20's std::span.
@@ -37,7 +45,10 @@ class Span
3745 * which is hard to implement without std::address_of.
3846 */
3947 template <typename T, typename std::enable_if<std::is_convertible<T (*)[], C (*)[]>::value, int >::type = 0 >
40- constexpr Span (T* begin, T* end) noexcept : m_data(begin), m_size(end - begin) {}
48+ CONSTEXPR_IF_NOT_DEBUG Span (T* begin, T* end) noexcept : m_data(begin), m_size(end - begin)
49+ {
50+ ASSERT_IF_DEBUG (end >= begin);
51+ }
4152
4253 /* * Implicit conversion of spans between compatible types.
4354 *
@@ -73,15 +84,42 @@ class Span
7384 constexpr C* data () const noexcept { return m_data; }
7485 constexpr C* begin () const noexcept { return m_data; }
7586 constexpr C* end () const noexcept { return m_data + m_size; }
76- constexpr C& front () const noexcept { return m_data[0 ]; }
77- constexpr C& back () const noexcept { return m_data[m_size - 1 ]; }
87+ CONSTEXPR_IF_NOT_DEBUG C& front () const noexcept
88+ {
89+ ASSERT_IF_DEBUG (size () > 0 );
90+ return m_data[0 ];
91+ }
92+ CONSTEXPR_IF_NOT_DEBUG C& back () const noexcept
93+ {
94+ ASSERT_IF_DEBUG (size () > 0 );
95+ return m_data[m_size - 1 ];
96+ }
7897 constexpr std::size_t size () const noexcept { return m_size; }
79- constexpr C& operator [](std::size_t pos) const noexcept { return m_data[pos]; }
80-
81- constexpr Span<C> subspan (std::size_t offset) const noexcept { return Span<C>(m_data + offset, m_size - offset); }
82- constexpr Span<C> subspan (std::size_t offset, std::size_t count) const noexcept { return Span<C>(m_data + offset, count); }
83- constexpr Span<C> first (std::size_t count) const noexcept { return Span<C>(m_data, count); }
84- constexpr Span<C> last (std::size_t count) const noexcept { return Span<C>(m_data + m_size - count, count); }
98+ CONSTEXPR_IF_NOT_DEBUG C& operator [](std::size_t pos) const noexcept
99+ {
100+ ASSERT_IF_DEBUG (size () > pos);
101+ return m_data[pos];
102+ }
103+ CONSTEXPR_IF_NOT_DEBUG Span<C> subspan (std::size_t offset) const noexcept
104+ {
105+ ASSERT_IF_DEBUG (size () >= offset);
106+ return Span<C>(m_data + offset, m_size - offset);
107+ }
108+ CONSTEXPR_IF_NOT_DEBUG Span<C> subspan (std::size_t offset, std::size_t count) const noexcept
109+ {
110+ ASSERT_IF_DEBUG (size () >= offset + count);
111+ return Span<C>(m_data + offset, count);
112+ }
113+ CONSTEXPR_IF_NOT_DEBUG Span<C> first (std::size_t count) const noexcept
114+ {
115+ ASSERT_IF_DEBUG (size () >= count);
116+ return Span<C>(m_data, count);
117+ }
118+ CONSTEXPR_IF_NOT_DEBUG Span<C> last (std::size_t count) const noexcept
119+ {
120+ ASSERT_IF_DEBUG (size () >= count);
121+ return Span<C>(m_data + m_size - count, count);
122+ }
85123
86124 friend constexpr bool operator ==(const Span& a, const Span& b) noexcept { return a.size () == b.size () && std::equal (a.begin (), a.end (), b.begin ()); }
87125 friend constexpr bool operator !=(const Span& a, const Span& b) noexcept { return !(a == b); }
@@ -106,7 +144,7 @@ template <typename T>
106144T& SpanPopBack (Span<T>& span)
107145{
108146 size_t size = span.size ();
109- assert (size > 0 );
147+ ASSERT_IF_DEBUG (size > 0 );
110148 T& back = span[size - 1 ];
111149 span = Span<T>(span.data (), size - 1 );
112150 return back;
0 commit comments