From 2da6776451bad9d082919b418a03cea4596b3e0e Mon Sep 17 00:00:00 2001 From: Bananymous Date: Thu, 10 Oct 2024 21:53:23 +0300 Subject: [PATCH] BAN: Update {Byte}Span API with better constness const BAN::Span is now allowed to modify its underlying data, but the container itself is const. BAN::Span can be used for spans over constant data. --- BAN/include/BAN/ByteSpan.h | 107 ++++++++---------------- BAN/include/BAN/Span.h | 164 +++++++++++++++---------------------- 2 files changed, 103 insertions(+), 168 deletions(-) diff --git a/BAN/include/BAN/ByteSpan.h b/BAN/include/BAN/ByteSpan.h index 944262409c..40eacdfa39 100644 --- a/BAN/include/BAN/ByteSpan.h +++ b/BAN/include/BAN/ByteSpan.h @@ -21,75 +21,56 @@ namespace BAN , m_size(size) { } - ByteSpanGeneral(ByteSpanGeneral& other) + template + ByteSpanGeneral(const ByteSpanGeneral& other) requires(CONST || !SRC_CONST) : m_data(other.data()) , m_size(other.size()) { } - ByteSpanGeneral(ByteSpanGeneral&& other) + template + ByteSpanGeneral(ByteSpanGeneral&& other) requires(CONST || !SRC_CONST) : m_data(other.data()) , m_size(other.size()) { - other.m_data = nullptr; - other.m_size = 0; + other.clear(); } - template - ByteSpanGeneral(const ByteSpanGeneral& other) requires(CONST) - : m_data(other.data()) - , m_size(other.size()) - { } - template - ByteSpanGeneral(ByteSpanGeneral&& other) requires(CONST) - : m_data(other.data()) - , m_size(other.size()) - { - other.m_data = nullptr; - other.m_size = 0; - } - ByteSpanGeneral(Span other) - : m_data(other.data()) - , m_size(other.size()) - { } - ByteSpanGeneral(const Span& other) requires(CONST) - : m_data(other.data()) - , m_size(other.size()) - { } - ByteSpanGeneral& operator=(ByteSpanGeneral other) + template + ByteSpanGeneral(const Span& other) requires(is_same_v || (is_same_v && CONST)) + : m_data(other.data()) + , m_size(other.size()) + { } + template + ByteSpanGeneral(Span&& other) requires(is_same_v || (is_same_v && CONST)) + : m_data(other.data()) + , m_size(other.size()) + { + other.clear(); + } + + template + ByteSpanGeneral& operator=(const ByteSpanGeneral& other) requires(CONST || !SRC_CONST) { m_data = other.data(); m_size = other.size(); return *this; } - template - ByteSpanGeneral& operator=(const ByteSpanGeneral& other) requires(CONST) - { - m_data = other.data(); - m_size = other.size(); - return *this; - } - ByteSpanGeneral& operator=(Span other) - { - m_data = other.data(); - m_size = other.size(); - return *this; - } - ByteSpanGeneral& operator=(const Span& other) requires(CONST) + template + ByteSpanGeneral& operator=(ByteSpanGeneral&& other) requires(CONST || !SRC_CONST) { m_data = other.data(); m_size = other.size(); + other.clear(); return *this; } template - requires(CONST || !is_const_v) - static ByteSpanGeneral from(S& value) + static ByteSpanGeneral from(S& value) requires(CONST || !is_const_v) { return ByteSpanGeneral(reinterpret_cast(&value), sizeof(S)); } template - requires(!CONST && !is_const_v) - S& as() + S& as() const requires(!CONST || is_const_v) { ASSERT(m_data); ASSERT(m_size >= sizeof(S)); @@ -97,30 +78,13 @@ namespace BAN } template - requires(is_const_v) - S& as() const - { - ASSERT(m_data); - ASSERT(m_size >= sizeof(S)); - return *reinterpret_cast(m_data); - } - - template - requires(!CONST && !is_const_v) - Span as_span() + Span as_span() const requires(!CONST || is_const_v) { ASSERT(m_data); return Span(reinterpret_cast(m_data), m_size / sizeof(S)); } - template - const Span as_span() const - { - ASSERT(m_data); - return Span(reinterpret_cast(m_data), m_size / sizeof(S)); - } - - ByteSpanGeneral slice(size_type offset, size_type length = size_type(-1)) + ByteSpanGeneral slice(size_type offset, size_type length = size_type(-1)) const { ASSERT(m_data); ASSERT(m_size >= offset); @@ -130,22 +94,23 @@ namespace BAN return ByteSpanGeneral(m_data + offset, length); } - value_type& operator[](size_type offset) - { - ASSERT(offset < m_size); - return m_data[offset]; - } - const value_type& operator[](size_type offset) const + value_type& operator[](size_type offset) const { ASSERT(offset < m_size); return m_data[offset]; } - value_type* data() { return m_data; } - const value_type* data() const { return m_data; } + value_type* data() const { return m_data; } + bool empty() const { return m_size == 0; } size_type size() const { return m_size; } + void clear() + { + m_data = nullptr; + m_size = 0; + } + private: value_type* m_data { nullptr }; size_type m_size { 0 }; diff --git a/BAN/include/BAN/Span.h b/BAN/include/BAN/Span.h index 8db901b748..eac985eaf8 100644 --- a/BAN/include/BAN/Span.h +++ b/BAN/include/BAN/Span.h @@ -14,121 +14,91 @@ namespace BAN public: using value_type = T; using size_type = size_t; - using iterator = IteratorSimple; - using const_iterator = ConstIteratorSimple; + using iterator = IteratorSimple; + using const_iterator = ConstIteratorSimple; + + private: + template + static inline constexpr bool can_init_from_v = is_same_v || is_same_v; public: Span() = default; - Span(T*, size_type); - Span(Span&); + Span(value_type* data, size_type size) + : m_data(data) + , m_size(size) + { } + template - requires(is_same_v) - Span(const Span&); + Span(const Span& other) requires can_init_from_v + : m_data(other.m_data) + , m_size(other.m_size) + { } + template + Span(Span&& other) requires can_init_from_v + : m_data(other.m_data) + , m_size(other.m_size) + { + other.clear(); + } + + template + Span& operator=(const Span& other) requires can_init_from_v + { + m_data = other.m_data; + m_size = other.m_size; + return *this; + } + template + Span& operator=(Span&& other) requires can_init_from_v + { + m_data = other.m_data; + m_size = other.m_size; + return *this; + } iterator begin() { return iterator(m_data); } iterator end() { return iterator(m_data + m_size); } const_iterator begin() const { return const_iterator(m_data); } const_iterator end() const { return const_iterator(m_data + m_size); } - T& operator[](size_type); - const T& operator[](size_type) const; + value_type& operator[](size_type index) const + { + ASSERT(index < m_size); + return m_data[index]; + } - T* data(); - const T* data() const; + value_type* data() const + { + ASSERT(m_data); + return m_data; + } - bool empty() const; - size_type size() const; + bool empty() const { return m_size == 0; } + size_type size() const { return m_size; } - void clear(); + void clear() + { + m_data = nullptr; + m_size = 0; + } - Span slice(size_type, size_type = ~size_type(0)); + Span slice(size_type start, size_type length = ~size_type(0)) const + { + ASSERT(m_data); + ASSERT(start <= m_size); + if (length == ~size_type(0)) + length = m_size - start; + ASSERT(m_size - start >= length); + return Span(m_data + start, length); + } - Span as_const() const { return Span(m_data, m_size); } + Span as_const() const { return *this; } private: - T* m_data = nullptr; + value_type* m_data = nullptr; size_type m_size = 0; + + friend class Span; }; - template - Span::Span(T* data, size_type size) - : m_data(data) - , m_size(size) - { - } - - template - Span::Span(Span& other) - : m_data(other.data()) - , m_size(other.size()) - { - } - - template - template - requires(is_same_v) - Span::Span(const Span& other) - : m_data(other.data()) - , m_size(other.size()) - { - } - - template - T& Span::operator[](size_type index) - { - ASSERT(m_data); - ASSERT(index < m_size); - return m_data[index]; - } - - template - const T& Span::operator[](size_type index) const - { - ASSERT(m_data); - ASSERT(index < m_size); - return m_data[index]; - } - - template - T* Span::data() - { - return m_data; - } - - template - const T* Span::data() const - { - return m_data; - } - - template - bool Span::empty() const - { - return m_size == 0; - } - - template - typename Span::size_type Span::size() const - { - return m_size; - } - - template - void Span::clear() - { - m_data = nullptr; - m_size = 0; - } - - template - Span Span::slice(size_type start, size_type length) - { - ASSERT(m_data); - ASSERT(start <= m_size); - if (length == ~size_type(0)) - length = m_size - start; - ASSERT(m_size - start >= length); - return Span(m_data + start, length); - } - }