10
10
#include < algorithm>
11
11
#include < assert.h>
12
12
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
+
13
21
/* * A Span is an object that can refer to a contiguous sequence of objects.
14
22
*
15
23
* It implements a subset of C++20's std::span.
@@ -37,7 +45,10 @@ class Span
37
45
* which is hard to implement without std::address_of.
38
46
*/
39
47
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
+ }
41
52
42
53
/* * Implicit conversion of spans between compatible types.
43
54
*
@@ -73,15 +84,42 @@ class Span
73
84
constexpr C* data () const noexcept { return m_data; }
74
85
constexpr C* begin () const noexcept { return m_data; }
75
86
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
+ }
78
97
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
+ }
85
123
86
124
friend constexpr bool operator ==(const Span& a, const Span& b) noexcept { return a.size () == b.size () && std::equal (a.begin (), a.end (), b.begin ()); }
87
125
friend constexpr bool operator !=(const Span& a, const Span& b) noexcept { return !(a == b); }
@@ -106,7 +144,7 @@ template <typename T>
106
144
T& SpanPopBack (Span<T>& span)
107
145
{
108
146
size_t size = span.size ();
109
- assert (size > 0 );
147
+ ASSERT_IF_DEBUG (size > 0 );
110
148
T& back = span[size - 1 ];
111
149
span = Span<T>(span.data (), size - 1 );
112
150
return back;
0 commit comments