1

Span does runtime checks of bounds (if exist) now

This commit is contained in:
2022-12-08 02:15:03 +01:00
parent f5ee5f6942
commit a0af7fc3a7

View File

@ -6,7 +6,14 @@
namespace Container { namespace Container {
// 0 is unchecked /**
* This class implements a readonly view on a memory region of uniform type.
* The Span can be initialized wihout size checking by supplying 0 as size
* and using the one-argument constructor. Then iterators become invalid.
*
* @tparam T The type of the objects located in the memory region
* @tparam N The size of the memory region
*/
template<typename T, std::size_t N = 0> template<typename T, std::size_t N = 0>
class Span { class Span {
public: public:
@ -17,33 +24,40 @@ namespace Container {
const std::size_t sz = N; const std::size_t sz = N;
public: public:
Span() = default; Span() = delete;
Span(T* first) : ptr(first) {} explicit Span(T *first) : ptr(first) {}
Span(T *first, T *last) : ptr(first), sz(last - first) {} Span(T *first, T *last) : ptr(first), sz(last - first) {}
// TODO: Rest of constructors
iterator begin() { return iterator(ptr); } iterator begin() { return iterator(ptr); }
iterator begin() const { return iterator(ptr); } iterator begin() const { return iterator(ptr); }
// If size is unchecked end() is equal to begin() // If size is unchecked end() is equal to begin()
iterator end() { return iterator(&ptr[N]); } iterator end() { return iterator(&ptr[sz]); }
iterator end() const { return iterator(&ptr[N]); }
// If size is unchecked end() is equal to begin()
iterator end() const { return iterator(&ptr[sz]); }
T *operator[](std::size_t i) { T *operator[](std::size_t i) {
if constexpr (N != 0) { if (sz != 0) {
if (i < 0 || i >= N) { return nullptr; } if (i >= sz) { return nullptr; }
} }
return &ptr[i]; return &ptr[i];
} }
T *operator[](std::size_t i) const { T *operator[](std::size_t i) const {
if constexpr (N != 0) { if (sz != 0) {
if (i < 0 || i >= N) { return nullptr; } if (i >= sz) { return nullptr; }
} }
return &ptr[i]; return &ptr[i];
} }
T *data() { return ptr; } T *data() { return ptr; }
const T *data() const { return ptr; } const T *data() const { return ptr; }
explicit operator T *() { explicit operator T *() {
@ -51,11 +65,11 @@ namespace Container {
} }
// First is inclusive, last exclusive [first, last) // First is inclusive, last exclusive [first, last)
Span& subspan(std::size_t first, std::size_t last = N) { Span &subspan(std::size_t first, std::size_t last) {
return Span(ptr + first, ptr + last - 1); return Span(ptr + first, ptr + last - 1);
} }
std::size_t size() const { [[nodiscard]] std::size_t size() const {
return sz; return sz;
} }
}; };