From bcf147f096dab109a23f47f0b5cf81ac6eca50d0 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 14 Jul 2022 12:19:08 +0100 Subject: [PATCH] Added etl::poly_span Refacted parts of etl::span --- include/etl/poly_span.h | 696 ++++++++-------- include/etl/span.h | 131 +-- test/CMakeLists.txt | 5 +- test/test_poly_span_dynamic_extent.cpp | 225 ++++-- test/test_poly_span_fixed_extent.cpp | 567 +++++++++++++ ..._span.cpp => test_span_dynamic_extent.cpp} | 64 +- test/test_span_fixed_extent.cpp | 749 ++++++++++++++++++ test/vs2019/etl.vcxproj | 4 +- test/vs2019/etl.vcxproj.filters | 8 +- 9 files changed, 1994 insertions(+), 455 deletions(-) create mode 100644 test/test_poly_span_fixed_extent.cpp rename test/{test_span.cpp => test_span_dynamic_extent.cpp} (91%) create mode 100644 test/test_span_fixed_extent.cpp diff --git a/include/etl/poly_span.h b/include/etl/poly_span.h index 3110c4df..db05bcba 100644 --- a/include/etl/poly_span.h +++ b/include/etl/poly_span.h @@ -46,7 +46,7 @@ SOFTWARE. #include "private/dynamic_extent.h" #if ETL_USING_CPP11 && ETL_USING_STL -#include + #include #endif ///\defgroup poly_span poly_span @@ -70,7 +70,7 @@ namespace etl template friend class etl::poly_span; - template + template friend class const_iterator; typedef TBase value_type; @@ -249,7 +249,7 @@ namespace etl //*************************************************************************** /// Poly Span - Fixed Extent //*************************************************************************** - template + template class poly_span { public: @@ -265,9 +265,9 @@ namespace etl typedef ETL_OR_STD::reverse_iterator reverse_iterator; - static ETL_CONSTANT size_t Extent = Extent_; + static ETL_CONSTANT size_t extent = Extent; - template + template friend class poly_span; //************************************************************************* @@ -285,16 +285,13 @@ namespace etl template ETL_CONSTEXPR poly_span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT : pbegin(etl::addressof(*begin_)) + , element_size(sizeof(typename etl::iterator_traits::value_type)) { typedef typename etl::iterator_traits::value_type data_type; typedef typename etl::iterator_traits::iterator_category iterator_category; ETL_STATIC_ASSERT((etl::is_same::iterator_category>::value), "Not a random access iterator"); ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(data_type); - - element_size = Element_Size; } //************************************************************************* @@ -303,16 +300,13 @@ namespace etl template ETL_CONSTEXPR poly_span(const TIterator begin_, const TIterator end_) : pbegin(etl::addressof(*begin_)) + , element_size(sizeof(typename etl::iterator_traits::value_type)) { typedef typename etl::iterator_traits::value_type data_type; typedef typename etl::iterator_traits::iterator_category iterator_category; ETL_STATIC_ASSERT((etl::is_same::value), "Not a random access iterator"); ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(data_type); - - element_size = Element_Size; } //************************************************************************* @@ -321,13 +315,10 @@ namespace etl template ETL_CONSTEXPR poly_span(U(&begin_)[N]) ETL_NOEXCEPT : pbegin(begin_) + , element_size(sizeof(U)) { ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - - element_size = Element_Size; } //************************************************************************* @@ -336,13 +327,10 @@ namespace etl template ETL_CONSTEXPR poly_span(etl::array& a) ETL_NOEXCEPT : pbegin(a.data()) + , element_size(sizeof(U)) { ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - - element_size = Element_Size; } //************************************************************************* @@ -351,13 +339,10 @@ namespace etl template ETL_CONSTEXPR poly_span(const etl::array& a) ETL_NOEXCEPT : pbegin(a.data()) + , element_size(sizeof(U)) { ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - - element_size = Element_Size; } #if ETL_USING_CPP11 && ETL_USING_STL @@ -367,13 +352,10 @@ namespace etl template ETL_CONSTEXPR poly_span(std::array& a) ETL_NOEXCEPT : pbegin(a.data()) + , element_size(sizeof(U)) { ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - - element_size = Element_Size; } //************************************************************************* @@ -382,13 +364,10 @@ namespace etl template ETL_CONSTEXPR poly_span(const std::array& a) ETL_NOEXCEPT : pbegin(a.data()) + , element_size(sizeof(U)) { ETL_STATIC_ASSERT(N <= Extent, "Array data overflow"); ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - - element_size = Element_Size; } #endif @@ -410,23 +389,23 @@ namespace etl , element_size(other.element_size) { } -// -// //************************************************************************* -// /// Returns a reference to the first element. -// //************************************************************************* -// ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT -// { -// return *pbegin; -// } -// -// //************************************************************************* -// /// Returns a reference to the last element. -// //************************************************************************* -// ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT -// { -// return *(pend - 1); -// } -// + + //************************************************************************* + /// Returns a reference to the first element. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT + { + return *pbegin; + } + + //************************************************************************* + /// Returns a reference to the last element. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT + { + return *element_at(Extent - 1U); + } + //************************************************************************* /// Returns a pointer to the first element of the internal storage. //************************************************************************* @@ -435,44 +414,44 @@ namespace etl return pbegin; } - ////************************************************************************* - ///// Returns an iterator to the beginning of the poly_span. - ////************************************************************************* - //ETL_NODISCARD ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT - //{ - // return iterator(pbegin, 0U, element_size); - //} + //************************************************************************* + /// Returns an iterator to the beginning of the poly_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR iterator begin() const ETL_NOEXCEPT + { + return iterator(pbegin, 0U, element_size); + } - ////************************************************************************* - ///// Returns an iterator to the end of the poly_span. - ////************************************************************************* - //ETL_NODISCARD ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT - //{ - // return iterator(pbegin, extent, element_size); - //} + //************************************************************************* + /// Returns an iterator to the end of the poly_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT + { + return iterator(pbegin, Extent, element_size); + } + + //************************************************************************* + // Returns an reverse iterator to the reverse beginning of the poly_span. + //************************************************************************* + ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT + { + return reverse_iterator(end()); + } + + //************************************************************************* + /// Returns a reverse iterator to the end of the poly_span. + //************************************************************************* + ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT + { + return reverse_iterator(begin()); + } -// //************************************************************************* -// // Returns an reverse iterator to the reverse beginning of the poly_span. -// //************************************************************************* -// ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT -// { -// return reverse_iterator(pend); -// } -// -// //************************************************************************* -// /// Returns a reverse iterator to the end of the poly_span. -// //************************************************************************* -// ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT -// { -// return reverse_iterator(pbegin); -// } -// //************************************************************************* /// Returns true if the poly_span size is zero. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT { - return (Extent != 0U) + return (Extent == 0U); } //************************************************************************* @@ -499,108 +478,133 @@ namespace etl return Extent * element_size; } -// //************************************************************************* -// /// Assign from a poly_span. -// //************************************************************************* -// ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT -// { -// pbegin = other.pbegin; -// pend = other.pend; -// return *this; -// } -// -// //************************************************************************* -// /// Returns a reference to the indexed value. -// //************************************************************************* -// ETL_CONSTEXPR reference operator[](const size_t i) const -// { -// return pbegin[i]; -// } -// -// //************************************************************************* -// /// Obtains a poly_span that is a view over the first COUNT elements of this poly_span. -// //************************************************************************* -// template -// ETL_CONSTEXPR etl::poly_span first() const -// { -// return etl::poly_span(pbegin, pbegin + COUNT); -// } -// -// //************************************************************************* -// /// Obtains a poly_span that is a view over the first count elements of this poly_span. -// //************************************************************************* -// ETL_CONSTEXPR etl::poly_span first(size_t count) const -// { -// return etl::poly_span(pbegin, pbegin + count); -// } -// -// //************************************************************************* -// /// Obtains a poly_span that is a view over the last COUNT elements of this poly_span. -// //************************************************************************* -// template -// ETL_CONSTEXPR etl::poly_span last() const -// { -// return etl::poly_span(pend - COUNT, pend); -// } -// -// //************************************************************************* -// /// Obtains a poly_span that is a view over the last count elements of this poly_span. -// //************************************************************************* -// ETL_CONSTEXPR etl::poly_span last(size_t count) const -// { -// return etl::poly_span(pend - count, pend); -// } -// -//#if ETL_USING_CPP11 -// //************************************************************************* -// /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. -// //************************************************************************* -// template -// ETL_CONSTEXPR -// etl::poly_span subspan() const -// { -// if (COUNT == etl::dynamic_extent) -// { -// return etl::poly_span(pbegin + OFFSET, pend); -// } -// else -// { -// return etl::poly_span(pbegin + OFFSET, pbegin + OFFSET + COUNT); -// } -// } -//#else -// //************************************************************************* -// /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. -// //************************************************************************* -// template -// ETL_CONSTEXPR -// etl::poly_span subspan() const -// { -// if (COUNT == etl::dynamic_extent) -// { -// return etl::poly_span(pbegin + OFFSET, pend); -// } -// else -// { -// return etl::poly_span(pbegin + OFFSET, pbegin + OFFSET + COUNT); -// } -// } -//#endif -// -// //************************************************************************* -// /// Obtains a poly_span that is a view from 'offset' over the next 'count' elements of this poly_span. -// //************************************************************************* -// ETL_CONSTEXPR14 etl::poly_span subspan(size_t offset, size_t count = etl::dynamic_extent) const -// { -// if (count == etl::dynamic_extent) -// { -// return etl::poly_span(pbegin + offset, pend); -// } -// else -// { -// return etl::poly_span(pbegin + offset, pbegin + offset + count); -// } -// } + //************************************************************************* + /// Assign from a poly_span. + //************************************************************************* + ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT + { + pbegin = other.pbegin; + element_size = other.element_size; + return *this; + } + + //************************************************************************* + /// Assign from a poly_span. + //************************************************************************* + template + ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT + { + pbegin = other.pbegin; + element_size = other.element_size; + return *this; + } + + //************************************************************************* + /// Returns a reference to the indexed value. + //************************************************************************* + ETL_CONSTEXPR reference operator[](size_t i) const + { + return *element_at(i); + } + + //************************************************************************* + /// Obtains a poly_span that is a view over the first COUNT elements of this poly_span. + //************************************************************************* + template + ETL_CONSTEXPR etl::poly_span first() const + { + return etl::poly_span(pbegin, 0U, COUNT, element_size); + } + + //************************************************************************* + /// Obtains a poly_span that is a view over the first count elements of this poly_span. + //************************************************************************* + ETL_CONSTEXPR etl::poly_span first(size_t count) const + { + return etl::poly_span(pbegin, 0U, count, element_size); + } + + //************************************************************************* + /// Obtains a poly_span that is a view over the last COUNT elements of this poly_span. + //************************************************************************* + template + ETL_CONSTEXPR etl::poly_span last() const + { + return etl::poly_span(pbegin, Extent - COUNT, COUNT, element_size); + } + + //************************************************************************* + /// Obtains a poly_span that is a view over the last count elements of this poly_span. + //************************************************************************* + ETL_CONSTEXPR etl::poly_span last(size_t count) const + { + return etl::poly_span(pbegin, Extent - count, count, element_size); + } + +#if ETL_USING_CPP11 + //************************************************************************* + /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. + //************************************************************************* + template + ETL_CONSTEXPR etl::poly_span subspan() const + { + return (COUNT == etl::dynamic_extent) ? etl::poly_span(pbegin, OFFSET, Extent, element_size) + : etl::poly_span(pbegin, OFFSET, COUNT, element_size); + } +#else + //************************************************************************* + /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. + //************************************************************************* + template + etl::poly_span subspan() const + { + if (COUNT == etl::dynamic_extent) + { + return etl::poly_span(pbegin, OFFSET, Extent, element_size); + } + else + { + return etl::poly_span(pbegin, OFFSET, element_size); + } + } +#endif + + //************************************************************************* + /// Obtains a poly_span that is a view from 'offset' over the next 'count' elements of this poly_span. + //************************************************************************* + ETL_CONSTEXPR14 etl::poly_span subspan(size_t offset, size_t count = etl::dynamic_extent) const + { + return (count == etl::dynamic_extent) ? etl::poly_span(pbegin, offset, Extent, element_size) + : etl::poly_span(pbegin, offset, count, element_size); + } + + protected: + + //*************************************************************************** + template + struct char_ptr_type + { + typedef typename etl::conditional::value, const char*, char*>::type type; + }; + + typedef typename char_ptr_type::type char_ptr_t; + + //*************************************************************************** + ETL_CONSTEXPR pointer element_at(size_t index) const ETL_NOEXCEPT + { + char_ptr_t base = reinterpret_cast(pbegin); + return reinterpret_cast(base + (index * element_size)); + } + + //************************************************************************* + /// Construct from iterator + offset + element size + /// extent_ is ignored. + //************************************************************************* + ETL_CONSTEXPR poly_span(TBase* pbegin_, size_t offset_, size_t extent_, size_t element_size_) ETL_NOEXCEPT + : pbegin(reinterpret_cast(reinterpret_cast(pbegin_) + (offset_ * element_size_))) + , element_size(element_size_) + { + } private: @@ -618,17 +622,17 @@ namespace etl typedef TBase element_type; typedef typename etl::remove_cv::type value_type; - typedef size_t size_type; - typedef TBase& reference; + typedef size_t size_type; + typedef TBase& reference; typedef const TBase& const_reference; - typedef TBase* pointer; + typedef TBase* pointer; typedef const TBase* const_pointer; typedef etl::private_poly_span::iterator iterator; - typedef const TBase* const_iterator; - typedef ETL_OR_STD::reverse_iterator reverse_iterator; - typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; + typedef ETL_OR_STD::reverse_iterator reverse_iterator; - template + static ETL_CONSTANT size_t extent = etl::dynamic_extent; + + template friend class poly_span; //************************************************************************* @@ -636,7 +640,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR poly_span() ETL_NOEXCEPT : pbegin(ETL_NULLPTR) - , extent(0U) + , span_extent(0U) , element_size(0U) { } @@ -647,16 +651,14 @@ namespace etl template ETL_CONSTEXPR poly_span(const TIterator begin_, const TSize size_) ETL_NOEXCEPT : pbegin(etl::addressof(*begin_)) - , extent(size_) + , element_size(sizeof(typename etl::iterator_traits::value_type)) + , span_extent(size_) { typedef typename etl::iterator_traits::value_type data_type; typedef typename etl::iterator_traits::iterator_category iterator_category; ETL_STATIC_ASSERT((etl::is_same::value), "Not a random access iterator"); ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(data_type); - element_size = Element_Size; } //************************************************************************* @@ -665,16 +667,14 @@ namespace etl template ETL_CONSTEXPR poly_span(const TIterator begin_, const TIterator end_) : pbegin(etl::addressof(*begin_)) - , extent(size_t(etl::distance(begin_, end_))) + , element_size(sizeof(typename etl::iterator_traits::value_type)) + , span_extent(size_t(etl::distance(begin_, end_))) { typedef typename etl::iterator_traits::value_type data_type; typedef typename etl::iterator_traits::iterator_category iterator_category; ETL_STATIC_ASSERT((etl::is_same::value), "Not a random access iterator"); ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(data_type); - element_size = Element_Size; } //************************************************************************* @@ -683,12 +683,10 @@ namespace etl template ETL_CONSTEXPR poly_span(U(&begin_)[N]) ETL_NOEXCEPT : pbegin(begin_) - , extent(N) + , element_size(sizeof(U)) + , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - element_size = Element_Size; } //************************************************************************* @@ -697,12 +695,10 @@ namespace etl template ETL_CONSTEXPR poly_span(etl::array& a) ETL_NOEXCEPT : pbegin(a.data()) - , extent(N) + , element_size(sizeof(U)) + , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - element_size = Element_Size; } //************************************************************************* @@ -711,12 +707,10 @@ namespace etl template ETL_CONSTEXPR poly_span(const etl::array& a) ETL_NOEXCEPT : pbegin(a.data()) - , extent(N) + , element_size(sizeof(U)) + , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of the data type"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - element_size = Element_Size; } #if ETL_USING_CPP11 && ETL_USING_STL @@ -726,12 +720,10 @@ namespace etl template ETL_CONSTEXPR poly_span(std::array& a) ETL_NOEXCEPT : pbegin(a.data()) - , extent(N) + , element_size(sizeof(U)) + , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - element_size = Element_Size; } //************************************************************************* @@ -740,12 +732,10 @@ namespace etl template ETL_CONSTEXPR poly_span(const std::array& a) ETL_NOEXCEPT : pbegin(a.data()) - , extent(N) + , element_size(sizeof(U)) + , span_extent(N) { ETL_STATIC_ASSERT((etl::is_base_of::value || etl::is_same::value), "TBase not a base of U"); - - static ETL_CONSTANT size_t Element_Size = sizeof(U); - element_size = Element_Size; } #endif @@ -754,7 +744,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR poly_span(const poly_span& other) ETL_NOEXCEPT : pbegin(other.pbegin) - , extent(other.extent) + , span_extent(other.span_extent) , element_size(other.element_size) { } @@ -765,7 +755,7 @@ namespace etl template ETL_CONSTEXPR poly_span(const poly_span& other) ETL_NOEXCEPT : pbegin(other.pbegin) - , extent(other.extent) + , span_extent(other.span_extent) , element_size(other.element_size) { } @@ -783,7 +773,7 @@ namespace etl //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT { - return *element_at(extent - 1U); + return *element_at(span_extent - 1U); } //************************************************************************* @@ -807,31 +797,31 @@ namespace etl //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR iterator end() const ETL_NOEXCEPT { - return iterator(pbegin, extent, element_size); + return iterator(pbegin, span_extent, element_size); + } + + //************************************************************************* + // Returns an reverse iterator to the reverse beginning of the poly_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT + { + return reverse_iterator(end()); + } + + //************************************************************************* + /// Returns a reverse iterator to the end of the poly_span. + //************************************************************************* + ETL_NODISCARD ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT + { + return reverse_iterator(begin()); } -// //************************************************************************* -// // Returns an reverse iterator to the reverse beginning of the poly_span. -// //************************************************************************* -// ETL_NODISCARD ETL_CONSTEXPR reverse_iterator rbegin() const ETL_NOEXCEPT -// { -// return reverse_iterator(pend); -// } -// -// //************************************************************************* -// /// Returns a reverse iterator to the end of the poly_span. -// //************************************************************************* -// ETL_NODISCARD ETL_CONSTEXPR reverse_iterator rend() const ETL_NOEXCEPT -// { -// return reverse_iterator(pbegin); -// } -// //************************************************************************* /// Returns true if the poly_span size is zero. //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR bool empty() const ETL_NOEXCEPT { - return (extent == 0); + return (span_extent == 0); } //************************************************************************* @@ -839,7 +829,7 @@ namespace etl //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT { - return extent; + return span_extent; } //************************************************************************* @@ -855,18 +845,31 @@ namespace etl //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT { - return element_size * extent; + return element_size * span_extent; } -// //************************************************************************* -// /// Assign from a poly_span. -// //************************************************************************* -// ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT -// { -// pbegin = other.pbegin; -// pend = other.pend; -// return *this; -// } + //************************************************************************* + /// Assign from a poly_span. + //************************************************************************* + ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT + { + pbegin = other.pbegin; + span_extent = other.span_extent; + element_size = other.element_size; + return *this; + } + + //************************************************************************* + /// Assign from a poly_span. + //************************************************************************* + template + ETL_CONSTEXPR14 poly_span& operator =(const poly_span& other) ETL_NOEXCEPT + { + pbegin = other.pbegin; + span_extent = other.span_extent; + element_size = other.element_size; + return *this; + } //************************************************************************* /// Returns a reference to the indexed value. @@ -876,72 +879,64 @@ namespace etl return *element_at(i); } -// //************************************************************************* -// /// Obtains a poly_span that is a view over the first COUNT elements of this poly_span. -// //************************************************************************* -// template -// ETL_CONSTEXPR etl::poly_span first() const -// { -// return etl::poly_span(pbegin, pbegin + COUNT); -// } -// -// //************************************************************************* -// /// Obtains a poly_span that is a view over the first count elements of this poly_span. -// //************************************************************************* -// ETL_CONSTEXPR etl::poly_span first(size_t count) const -// { -// return etl::poly_span(pbegin, pbegin + count); -// } -// -// //************************************************************************* -// /// Obtains a poly_span that is a view over the last COUNT elements of this poly_span. -// //************************************************************************* -// template -// ETL_CONSTEXPR etl::poly_span last() const -// { -// return etl::poly_span(pend - COUNT, pend); -// } -// -// //************************************************************************* -// /// Obtains a poly_span that is a view over the last count elements of this poly_span. -// //************************************************************************* -// ETL_CONSTEXPR etl::poly_span last(size_t count) const -// { -// return etl::poly_span(pend - count, pend); -// } + //************************************************************************* + /// Obtains a poly_span that is a view over the first COUNT elements of this poly_span. + //************************************************************************* + template + ETL_CONSTEXPR etl::poly_span first() const + { + return etl::poly_span(pbegin, 0U, COUNT, element_size); + } + + //************************************************************************* + /// Obtains a poly_span that is a view over the first count elements of this poly_span. + //************************************************************************* + ETL_CONSTEXPR etl::poly_span first(size_t count) const + { + return etl::poly_span(pbegin, 0U, count, element_size); + } + + //************************************************************************* + /// Obtains a poly_span that is a view over the last COUNT elements of this poly_span. + //************************************************************************* + template + ETL_CONSTEXPR etl::poly_span last() const + { + return etl::poly_span(pbegin, span_extent - COUNT, COUNT, element_size); + } + + //************************************************************************* + /// Obtains a poly_span that is a view over the last count elements of this poly_span. + //************************************************************************* + ETL_CONSTEXPR etl::poly_span last(size_t count) const + { + return etl::poly_span(pbegin, span_extent - count, count, element_size); + } #if ETL_USING_CPP11 //************************************************************************* /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. //************************************************************************* template - ETL_CONSTEXPR - etl::poly_span subspan() const + ETL_CONSTEXPR etl::poly_span subspan() const { - if (COUNT == etl::dynamic_extent) - { - return etl::poly_span(pbegin, OFFSET, extent, element_size); - } - else - { - return etl::poly_span(pbegin, OFFSET, COUNT, element_size); - } + return (COUNT == etl::dynamic_extent) ? etl::poly_span(pbegin, OFFSET, span_extent, element_size) + : etl::poly_span(pbegin, OFFSET, COUNT, element_size); } #else //************************************************************************* /// Obtains a poly_span that is a view from OFFSET over the next COUNT elements of this poly_span. //************************************************************************* template - ETL_CONSTEXPR - etl::poly_span subspan() const + etl::poly_span subspan() const { if (COUNT == etl::dynamic_extent) { - return etl::poly_span(pbegin, OFFSET, extent, element_size); + return etl::poly_span(pbegin, OFFSET, span_extent, element_size); } else { - return etl::poly_span(pbegin, OFFSET, COUNT, element_size); + return etl::poly_span(pbegin, OFFSET, span_extent, element_size); } } #endif @@ -951,14 +946,8 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 etl::poly_span subspan(size_t offset, size_t count = etl::dynamic_extent) const { - if (count == etl::dynamic_extent) - { - return etl::poly_span(pbegin, offset, extent - offset, element_size); - } - else - { - return etl::poly_span(pbegin, offset, count, element_size); - } + return (count == etl::dynamic_extent) ? etl::poly_span(pbegin, offset, span_extent - offset, element_size) + : etl::poly_span(pbegin, offset, count, element_size); } protected: @@ -968,7 +957,7 @@ protected: //************************************************************************* ETL_CONSTEXPR poly_span(TBase* pbegin_, size_t offset_, size_t extent_, size_t element_size_) ETL_NOEXCEPT : pbegin(reinterpret_cast(reinterpret_cast(pbegin_) + (offset_ * element_size_))) - , extent(extent_) + , span_extent(extent_) , element_size(element_size_) { } @@ -976,10 +965,13 @@ protected: private: //*************************************************************************** - template - using transfer_const = typename etl::conditional::value, typename etl::add_const::type, TTo>::type; + template + struct char_ptr_type + { + typedef typename etl::conditional::value, const char*, char*>::type type; + }; - typedef transfer_const* char_ptr_t; + typedef typename char_ptr_type::type char_ptr_t; //*************************************************************************** ETL_CONSTEXPR pointer element_at(size_t index) const ETL_NOEXCEPT @@ -989,41 +981,59 @@ protected: } pointer pbegin; - size_t extent; + size_t span_extent; size_t element_size; }; -// -// //************************************************************************* -// /// Template deduction guides. -// //************************************************************************* -//#if ETL_USING_CPP17 -// template -// poly_span(TArray& a) -// ->poly_span; -// -// template -// poly_span(const TIterator begin_, const TIterator end_) -// ->poly_span, etl::dynamic_extent>; -// -// template -// poly_span(const TIterator begin_, const TSize size_) -// ->poly_span, etl::dynamic_extent>; -//#endif -// -// //************************************************************************* -// /// Hash function. -// //************************************************************************* -//#if ETL_USING_8BIT_TYPES -// template -// struct hash > -// { -// size_t operator()(const etl::poly_span& view) const -// { -// return etl::private_hash::generic_hash(reinterpret_cast(&view[0]), -// reinterpret_cast(&view[view.size()])); -// } -// }; -//#endif + + //************************************************************************* + /// Template deduction guides. + //************************************************************************* +#if ETL_USING_CPP17 + template + poly_span(const TIterator begin_, const TIterator end_) + ->poly_span, etl::dynamic_extent>; + + template + poly_span(const TIterator begin_, const TSize size_) + ->poly_span, etl::dynamic_extent>; + + template + poly_span(T(&)[N]) + ->poly_span; + + template + poly_span(etl::array&) + ->poly_span; + + template + poly_span(const etl::array&) + ->poly_span; + +#if ETL_USING_STL + template + poly_span(std::array&) + ->poly_span; + + template + poly_span(const std::array&) + ->poly_span; +#endif +#endif + + //************************************************************************* + /// Hash function. + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template + struct hash > + { + size_t operator()(const etl::poly_span& view) const + { + return etl::private_hash::generic_hash(reinterpret_cast(&view[0]), + reinterpret_cast(&view[view.size()])); + } + }; +#endif } #endif diff --git a/include/etl/span.h b/include/etl/span.h index 2da3264c..5a92f92a 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -52,7 +52,7 @@ SOFTWARE. namespace etl { //*************************************************************************** - /// Span + /// Span - Fixed Extent //*************************************************************************** template class span @@ -167,6 +167,44 @@ namespace etl } #endif +#if ETL_USING_CPP11 + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template >::value && + !etl::is_array>::value&& + etl::is_same, etl::remove_cv_t::value_type>>::value, void>::type> + ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT + : pbegin(a.data()) + { + } +#else + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + span(TContainer& a, typename etl::enable_if::type>::value && + !etl::is_array::value && + etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type) ETL_NOEXCEPT + : pbegin(a.data()) + { + } + + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if::type>::value && + !etl::is_array::value&& + etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type) ETL_NOEXCEPT + : pbegin(a.data()) + { + } +#endif + //************************************************************************* /// Copy constructor //************************************************************************* @@ -303,7 +341,7 @@ namespace etl template ETL_CONSTEXPR etl::span last() const { - return etl::span((pbegin + Extent) - COUNT, (pbegin + Extent)); + return etl::span(pbegin + Extent - COUNT, (pbegin + Extent)); } //************************************************************************* @@ -320,32 +358,25 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR - etl::span subspan() const + etl::span subspan() const { - if (COUNT == etl::dynamic_extent) - { - return etl::span(pbegin + OFFSET, (pbegin + Extent)); - } - else - { - return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); - } + return (COUNT == etl::dynamic_extent) ? etl::span(pbegin + OFFSET, (pbegin + Extent)) + : etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); } #else //************************************************************************* /// Obtains a span that is a view from OFFSET over the next COUNT elements of this span. //************************************************************************* template - ETL_CONSTEXPR - etl::span subspan() const + etl::span subspan() const { if (COUNT == etl::dynamic_extent) { - return etl::span(pbegin + OFFSET, (pbegin + Extent)); + return etl::span(pbegin + OFFSET, (pbegin + Extent)); } else { - return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); + return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); } } #endif @@ -355,14 +386,8 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 etl::span subspan(size_t offset, size_t count = etl::dynamic_extent) const { - if (count == etl::dynamic_extent) - { - return etl::span(pbegin + offset, (pbegin + Extent)); - } - else - { - return etl::span(pbegin + offset, pbegin + offset + count); - } + return (count == etl::dynamic_extent) ? etl::span(pbegin + offset, (pbegin + Extent)) + : etl::span(pbegin + offset, pbegin + offset + count); } private: @@ -371,7 +396,7 @@ namespace etl }; //*************************************************************************** - /// Span specialisation + /// Span - Dynamic Extent //*************************************************************************** template class span @@ -691,32 +716,25 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR - etl::span subspan() const + etl::span subspan() const { - if (COUNT == etl::dynamic_extent) - { - return etl::span(pbegin + OFFSET, pend); - } - else - { - return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); - } + return (COUNT == etl::dynamic_extent) ? etl::span(pbegin + OFFSET, pend) + : etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); } #else //************************************************************************* /// Obtains a span that is a view from OFFSET over the next COUNT elements of this span. //************************************************************************* template - ETL_CONSTEXPR - etl::span subspan() const + etl::span subspan() const { if (COUNT == etl::dynamic_extent) { - return etl::span(pbegin + OFFSET, pend); + return etl::span(pbegin + OFFSET, pend); } else { - return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); + return etl::span(pbegin + OFFSET, pbegin + OFFSET + COUNT); } } #endif @@ -726,11 +744,8 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 etl::span subspan(size_t offset, size_t count = etl::dynamic_extent) const { - if (count == etl::dynamic_extent) - { - return etl::span(pbegin + offset, pend); - } - return etl::span(pbegin + offset, pbegin + offset + count); + return (count == etl::dynamic_extent) ? etl::span(pbegin + offset, pend) + : etl::span(pbegin + offset, pbegin + offset + count); } private: @@ -743,25 +758,43 @@ namespace etl /// Template deduction guides. //************************************************************************* #if ETL_USING_CPP17 - template - span(TArray& a) - ->span; - template span(const TIterator begin_, const TIterator end_) ->span, etl::dynamic_extent>; template - span(const TIterator begin_, const TSize size_) + span(const TIterator begin_, const TSize size_) ->span, etl::dynamic_extent>; + + template + span(T(&)[N]) + -> span; + + template + span(etl::array&) + -> span; + + template + span(const etl::array&) + -> span; + +#if ETL_USING_STL + template + span(std::array&) + ->span; + + template + span(const std::array&) + ->span; +#endif #endif //************************************************************************* /// Hash function. //************************************************************************* #if ETL_USING_8BIT_TYPES - template - struct hash > + template + struct hash > { size_t operator()(const etl::span& view) const { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index dde57b83..25f19f8b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -196,6 +196,8 @@ set(TEST_SOURCE_FILES test_parameter_type.cpp test_parity_checksum.cpp test_pearson.cpp + test_poly_span_dynamic_extent.cpp + test_poly_span_fixed_extent.cpp test_pool.cpp test_pool_external_buffer.cpp test_priority_queue.cpp @@ -225,7 +227,8 @@ set(TEST_SOURCE_FILES test_shared_message.cpp test_singleton.cpp test_smallest.cpp - test_span.cpp + test_span_dynamic_extent.cpp + test_span_fixed_extent.cpp test_stack.cpp test_standard_deviation.cpp test_state_chart.cpp diff --git a/test/test_poly_span_dynamic_extent.cpp b/test/test_poly_span_dynamic_extent.cpp index 148b750c..d9ab34e9 100644 --- a/test/test_poly_span_dynamic_extent.cpp +++ b/test/test_poly_span_dynamic_extent.cpp @@ -5,7 +5,7 @@ Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com -Copyright(c) 2020 John Wellbelove +Copyright(c) 2022 John Wellbelove Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal @@ -44,6 +44,10 @@ namespace virtual int value() const = 0; virtual void value(int) = 0; + virtual ~Base() + { + } + virtual bool operator ==(const Base& rhs) const { return value() == rhs.value(); @@ -128,7 +132,7 @@ namespace CHECK(s.empty()); CHECK_EQUAL(0U, s.size()); CHECK_EQUAL(0U, s.size_bytes()); - //CHECK(s.begin() == s.end()); + CHECK(s.begin() == s.end()); } //************************************************************************* @@ -177,6 +181,7 @@ namespace CHECK_EQUAL(data[3].value(), s[3].value()); } +#if ETL_USING_STL //************************************************************************* TEST(test_poly_span_construct_from_std_array) { @@ -204,6 +209,7 @@ namespace CHECK_EQUAL(data[2].value(), s[2].value()); CHECK_EQUAL(data[3].value(), s[3].value()); } +#endif //************************************************************************* TEST(test_poly_span_construct_from_etl_array) @@ -233,6 +239,7 @@ namespace CHECK_EQUAL(data[3].value(), s[3].value()); } +#if ETL_USING_STL //************************************************************************* TEST(test_poly_span_copy_construct) { @@ -240,11 +247,28 @@ namespace etl::poly_span s1 = a; etl::poly_span s2 = s1; const etl::poly_span s3 = s1; - //CHECK(equal(s1, s2)); CHECK(!s2.empty()); CHECK(!s3.empty()); + CHECK(std::equal(s1.begin(), s1.end(), s2.begin())); } + //************************************************************************* + TEST(test_poly_span_assignment) + { + std::array a = { 1, 2, 3, 4 }; + etl::poly_span s1 = a; + etl::poly_span s2; + etl::poly_span s3; + + s2 = s1; + s3 = s1; + + CHECK(!s2.empty()); + CHECK(!s3.empty()); + CHECK(std::equal(s1.begin(), s1.end(), s2.begin())); + } +#endif + //************************************************************************* TEST(test_poly_span_multi_derived) { @@ -350,7 +374,38 @@ namespace } //************************************************************************* - TEST(test_poly_span_random_access_iteratorUse) + TEST(test_poly_span_reverse_iterator) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s1(data); + + etl::poly_span::reverse_iterator itr1 = s1.rbegin(); + + CHECK(itr1 != s1.rend()); + + CHECK_EQUAL(data[3].value(), (*itr1).value()); + CHECK_EQUAL(data[3].value(), itr1->value()); + ++itr1; + CHECK_EQUAL(data[2].value(), (*itr1).value()); + CHECK_EQUAL(data[2].value(), itr1->value()); + itr1++; + CHECK_EQUAL(data[1].value(), (*itr1).value()); + CHECK_EQUAL(data[1].value(), itr1->value()); + itr1 += 1; + CHECK_EQUAL(data[0].value(), (*itr1).value()); + CHECK_EQUAL(data[0].value(), itr1->value()); + itr1 = itr1 + 1; + CHECK(itr1 == s1.rend()); + itr1 -= 1; + CHECK_EQUAL(data[0].value(), (*itr1).value()); + CHECK_EQUAL(data[0].value(), itr1->value()); + itr1 = itr1 - 1; + CHECK_EQUAL(data[1].value(), (*itr1).value()); + CHECK_EQUAL(data[1].value(), itr1->value()); + } + + //************************************************************************* + TEST(test_poly_span_random_access_iterator_use) { int data[] = { 25, 4, 3, -2, 1 }; etl::poly_span s = data; @@ -371,11 +426,6 @@ namespace CHECK_EQUAL(s[1].value(), s1[0].value()); CHECK_EQUAL(s[2].value(), s1[1].value()); - //auto s2 = s.subspan<1, 2>(); - //CHECK_EQUAL(2, s2.size()); - //CHECK_EQUAL(data[1].value(), s2[0].value()); - //CHECK_EQUAL(data[2].value(), s2[1].value()); - auto s2 = s.subspan(2); CHECK_EQUAL(3, s2.size()); CHECK_EQUAL(s[2].value(), s2[0].value()); @@ -383,59 +433,116 @@ namespace CHECK_EQUAL(s[4].value(), s2[2].value()); } - ////************************************************************************* - //TEST(test_poly_span_first) - //{ - // const int data[] = { 1, 2, 3, 4, 5 }; - // etl::poly_span s(data); - // - // CHECK_THROW(s.first(6), etl::poly_span_out_of_range); - // CHECK_EQUAL(s.first(5).size(), 5); - // CHECK(s.first(0).empty()); - // - // auto s1 = s.first(3); - // CHECK_EQUAL(3, s1.size()); - // CHECK_EQUAL(1, s1[0]); - // CHECK_EQUAL(3, s1[2]); - //} + //************************************************************************* + TEST(test_poly_span_first) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s1(data); - ////************************************************************************* - //TEST(test_poly_span_last) - //{ - // const int data[] = { 1, 2, 3, 4, 5 }; - // etl::poly_span s(data); - // - // CHECK_THROW(s.last(6), etl::poly_span_out_of_range); - // CHECK_EQUAL(s.last(5).size(), 5); - // - // auto s2 = s.last(2); - // CHECK_EQUAL(2, s2.size()); - // CHECK_EQUAL(4, s2[0]); - // CHECK_EQUAL(5, s2[1]); - //} + auto s2 = s1.first(3); + auto s3 = s1.first<3>(); - ////************************************************************************* - //TEST(test_poly_span_equal_view) - //{ - // std::vector v = { 1.0, 2.0, 3.0 }; - // etl::poly_span s1 = v; - // etl::poly_span cs2 = v; + CHECK_EQUAL(data[0].value(), s2[0].value()); + CHECK_EQUAL(data[1].value(), s2[1].value()); + CHECK_EQUAL(data[2].value(), s2[2].value()); - // CHECK(!etl::poly_span{}.equal_view(s1)); - // CHECK(s1.equal_view(cs2)); - // CHECK(s1.last(2).equal_view(cs2.subspan(1))); - //} + CHECK_EQUAL(data[0].value(), s3[0].value()); + CHECK_EQUAL(data[1].value(), s3[1].value()); + CHECK_EQUAL(data[2].value(), s3[2].value()); + } - ////************************************************************************* - //TEST(test_poly_span_at) - //{ - // const int data[] = { 1, 2, 3 }; - // etl::poly_span s(data); - // - // CHECK_EQUAL(s.at(0), 1); - // CHECK_EQUAL(s.at(2), 3); - // CHECK_THROW(s.at(3), etl::poly_span_out_of_range); - // CHECK_THROW(s.at(-1), etl::poly_span_out_of_range); - //} + //************************************************************************* + TEST(test_poly_span_last) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s1(data); + + auto s2 = s1.last(3); + auto s3 = s1.last<3>(); + + CHECK_EQUAL(data[1].value(), s2[0].value()); + CHECK_EQUAL(data[2].value(), s2[1].value()); + CHECK_EQUAL(data[3].value(), s2[2].value()); + + CHECK_EQUAL(data[1].value(), s3[0].value()); + CHECK_EQUAL(data[2].value(), s3[1].value()); + CHECK_EQUAL(data[3].value(), s3[2].value()); + } + + //************************************************************************* + TEST(test_hash) + { + int data[] = { 1, 2, 3, 4 }; + etl::poly_span s1(data); + + size_t hashdata = etl::private_hash::generic_hash(reinterpret_cast(&s1[0]), + reinterpret_cast(&s1[s1.size()])); + + size_t hashview = etl::hash>()(s1); + + CHECK_EQUAL(hashdata, hashview); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_c_array) + { + int data[] = { 1, 2, 3, 4 }; + + etl::poly_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_template_deduction_guide_for_std_array) + { + std::array data = { 1, 2, 3, 4 }; + + etl::poly_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } +#endif + + //************************************************************************* + TEST(test_template_deduction_guide_for_etl_array) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::poly_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterators) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::poly_span s{ data.begin(), data.end() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterator_and_size) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::poly_span s{ data.begin(), data.size() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } } } diff --git a/test/test_poly_span_fixed_extent.cpp b/test/test_poly_span_fixed_extent.cpp new file mode 100644 index 00000000..0c73eb17 --- /dev/null +++ b/test/test_poly_span_fixed_extent.cpp @@ -0,0 +1,567 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2022 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/poly_span.h" + +#include +#include +#include +#include +#include + +namespace +{ + //*************************************************************************** + struct Base + { + virtual int value() const = 0; + virtual void value(int) = 0; + + virtual ~Base() + { + } + + virtual bool operator ==(const Base& rhs) const + { + return value() == rhs.value(); + } + }; + + //*************************************************************************** + struct AnotherBase + { + virtual double another_value() const = 0; + + virtual bool operator ==(const AnotherBase& rhs) const + { + return another_value() == rhs.another_value(); + } + }; + + //*************************************************************************** + struct Derived : Base + { + Derived(int v_) + : v1(v_) + { + } + + int value() const override + { + return v1; + } + + void value(int i) override + { + v1 = i; + } + + int v1; + }; + + //*************************************************************************** + struct MultiDerived : AnotherBase, Base + { + MultiDerived(int v1_, double v2_) + : v1(v1_) + , v2(v2_) + { + } + + int value() const override + { + return v1; + } + + void value(int i) override + { + v1 = i; + } + + double another_value() const override + { + return v2; + } + + int v1; + double v2; + }; + + //*************************************************************************** + template + bool equal(const TSpan& span, TSource& source) + { + auto sb = std::begin(source); + return (span.size() == (std::end(source) - sb)) && std::equal(span.begin(), span.end(), sb); + } + + SUITE(test_poly_span_fixed_extent) + { + //************************************************************************* + TEST(test_poly_span_default_construct) + { + etl::poly_span s; + CHECK_EQUAL(0U, s.size_of_element()); + CHECK(!s.empty()); + CHECK_EQUAL(4U, s.size()); + CHECK_EQUAL(0U, s.size_bytes()); + CHECK(s.begin() == s.end()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_iterators) + { + std::vector data = { 1, 2, 3, 4 }; + + etl::poly_span s(data.begin(), data.end()); + CHECK_EQUAL(sizeof(Derived), s.size_of_element()); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_c_array) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s(data); + CHECK_EQUAL(sizeof(Derived), s.size_of_element()); + CHECK(!s.empty()); + CHECK_EQUAL(std::size(data), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_const_c_array) + { + const Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s(data); + CHECK_EQUAL(sizeof(Derived), s.size_of_element()); + CHECK(!s.empty()); + CHECK_EQUAL(std::size(data), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_poly_span_construct_from_std_array) + { + std::array data{ Derived(1), Derived(2), Derived(3), Derived(4) }; + etl::poly_span s(data); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_const_std_array) + { + const std::array data{ Derived(1), Derived(2), Derived(3), Derived(4) }; + etl::poly_span s(data); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } +#endif + + //************************************************************************* + TEST(test_poly_span_construct_from_etl_array) + { + etl::array data{ Derived(1), Derived(2), Derived(3), Derived(4) }; + etl::poly_span s(data); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + + //************************************************************************* + TEST(test_poly_span_construct_from_const_etl_array) + { + const etl::array data{ Derived(1), Derived(2), Derived(3), Derived(4) }; + etl::poly_span s(data); + CHECK(!s.empty()); + CHECK_EQUAL(data.size(), s.size()); + CHECK_EQUAL(s.size() * sizeof(Derived), s.size_bytes()); + CHECK_EQUAL(data[0].value(), s[0].value()); + CHECK_EQUAL(data[1].value(), s[1].value()); + CHECK_EQUAL(data[2].value(), s[2].value()); + CHECK_EQUAL(data[3].value(), s[3].value()); + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_poly_span_copy_construct) + { + std::array a = { 1, 2, 3, 4 }; + etl::poly_span s1 = a; + etl::poly_span s2 = s1; + const etl::poly_span s3 = s1; + CHECK(!s2.empty()); + CHECK(!s3.empty()); + CHECK(std::equal(s1.begin(), s1.end(), s2.begin())); + } + + //************************************************************************* + TEST(test_poly_span_assignment) + { + std::array a = { 1, 2, 3, 4 }; + etl::poly_span s1 = a; + etl::poly_span s2 = a; + etl::poly_span s3 = a; + + s2 = s1; + s3 = s1; + + CHECK(!s2.empty()); + CHECK(!s3.empty()); + CHECK(std::equal(s1.begin(), s1.end(), s2.begin())); + } +#endif + + //************************************************************************* + TEST(test_poly_span_multi_derived) + { + std::vector data = { { 0, 1.2 }, { 1, 2.3 }, { 2, 3.4 }, { 3, 4.5 } }; + + etl::poly_span s1(data.begin(), data.end()); + etl::poly_span s2(data.begin(), data.end()); + + CHECK_EQUAL(data[0].value(), s1[0].value()); + CHECK_EQUAL(data[1].value(), s1[1].value()); + CHECK_EQUAL(data[2].value(), s1[2].value()); + CHECK_EQUAL(data[3].value(), s1[3].value()); + + CHECK_EQUAL(data[0].another_value(), s2[0].another_value()); + CHECK_EQUAL(data[1].another_value(), s2[1].another_value()); + CHECK_EQUAL(data[2].another_value(), s2[2].another_value()); + CHECK_EQUAL(data[3].another_value(), s2[3].another_value()); + } + + //************************************************************************* + TEST(test_poly_span_front_back) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s(data); + + CHECK_EQUAL(data[0].value(), s.front().value()); + CHECK_EQUAL(data[3].value(), s.back().value()); + } + + //************************************************************************* + TEST(test_poly_span_const_front_back) + { + const Derived data[] = { 1, 2, 3, 4 }; + const etl::poly_span s(data); + + CHECK_EQUAL(data[0].value(), s.front().value()); + CHECK_EQUAL(data[3].value(), s.back().value()); + } + + //************************************************************************* + TEST(test_poly_span_iterator) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s1(data); + + etl::poly_span::iterator itr1 = s1.begin(); + + CHECK(itr1 != s1.end()); + + CHECK_EQUAL(data[0].value(), (*itr1).value()); + CHECK_EQUAL(data[0].value(), itr1->value()); + ++itr1; + CHECK_EQUAL(data[1].value(), (*itr1).value()); + CHECK_EQUAL(data[1].value(), itr1->value()); + itr1++; + CHECK_EQUAL(data[2].value(), (*itr1).value()); + CHECK_EQUAL(data[2].value(), itr1->value()); + itr1 += 1; + CHECK_EQUAL(data[3].value(), (*itr1).value()); + CHECK_EQUAL(data[3].value(), itr1->value()); + itr1 = itr1 + 1; + CHECK(itr1 == s1.end()); + itr1 -= 1; + CHECK_EQUAL(data[3].value(), (*itr1).value()); + CHECK_EQUAL(data[3].value(), itr1->value()); + itr1 = itr1 - 1; + CHECK_EQUAL(data[2].value(), (*itr1).value()); + CHECK_EQUAL(data[2].value(), itr1->value()); + + itr1 = s1.begin(); + etl::poly_span::iterator itr2 = itr1 + 1; + + CHECK(itr1 < itr2); + CHECK(itr1 <= itr1); + CHECK(itr1 <= itr2); + CHECK(itr2 > itr1); + CHECK(itr2 >= itr2); + CHECK(itr2 >= itr1); + CHECK(itr1 == itr1); + CHECK(itr2 == itr2); + CHECK(itr1 != itr2); + CHECK(itr2 != itr1); + + CHECK(!(itr1 > itr2)); + CHECK(!(itr2 <= itr1)); + CHECK(!(itr2 < itr1)); + CHECK(!(itr1 >= itr2)); + CHECK(!(itr1 == itr2)); + CHECK(!(itr2 == itr1)); + CHECK(!(itr1 != itr1)); + CHECK(!(itr2 != itr2)); + + itr1 = s1.begin(); + + (*itr1).value(2); + CHECK_EQUAL(2, (*itr1).value()); + + itr1->value(3); + CHECK_EQUAL(3, itr1->value()); + + etl::poly_span s2; + CHECK(s2.begin() == s2.end()); + } + + //************************************************************************* + TEST(test_poly_span_reverse_iterator) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s1(data); + + etl::poly_span::reverse_iterator itr1 = s1.rbegin(); + + CHECK(itr1 != s1.rend()); + + CHECK_EQUAL(data[3].value(), (*itr1).value()); + CHECK_EQUAL(data[3].value(), itr1->value()); + ++itr1; + CHECK_EQUAL(data[2].value(), (*itr1).value()); + CHECK_EQUAL(data[2].value(), itr1->value()); + itr1++; + CHECK_EQUAL(data[1].value(), (*itr1).value()); + CHECK_EQUAL(data[1].value(), itr1->value()); + itr1 += 1; + CHECK_EQUAL(data[0].value(), (*itr1).value()); + CHECK_EQUAL(data[0].value(), itr1->value()); + itr1 = itr1 + 1; + CHECK(itr1 == s1.rend()); + itr1 -= 1; + CHECK_EQUAL(data[0].value(), (*itr1).value()); + CHECK_EQUAL(data[0].value(), itr1->value()); + itr1 = itr1 - 1; + CHECK_EQUAL(data[1].value(), (*itr1).value()); + CHECK_EQUAL(data[1].value(), itr1->value()); + } + + //************************************************************************* + TEST(test_poly_span_random_access_iterator_use) + { + int data[] = { 25, 4, 3, -2, 1 }; + etl::poly_span s = data; + + std::sort(s.begin(), s.end()); + CHECK(std::is_sorted(std::begin(data), std::end(data))); + } + + //************************************************************************* + TEST(test_poly_span_subspan_dynamic) + { + Derived data[] = { 1, 2, 3, 4, 5 }; + etl::poly_span s(data); + + auto s1 = s.subspan(1, 2); + CHECK_EQUAL(2, s1.size()); + + CHECK_EQUAL(s[1].value(), s1[0].value()); + CHECK_EQUAL(s[2].value(), s1[1].value()); + + auto s2 = s.subspan(2); + CHECK_EQUAL(5U, s2.size()); + CHECK_EQUAL(s[2].value(), s2[0].value()); + CHECK_EQUAL(s[3].value(), s2[1].value()); + CHECK_EQUAL(s[4].value(), s2[2].value()); + } + + //************************************************************************* + TEST(test_poly_span_subspan_fixed) + { + Derived data[] = { 1, 2, 3, 4, 5 }; + etl::poly_span s(data); + + auto s1 = s.subspan<1, 2>(); + CHECK_EQUAL(2U, s1.size()); + + CHECK_EQUAL(s[1].value(), s1[0].value()); + CHECK_EQUAL(s[2].value(), s1[1].value()); + + auto s2 = s.subspan<2>(); + CHECK_EQUAL(3U, s2.size()); + CHECK_EQUAL(s[2].value(), s2[0].value()); + CHECK_EQUAL(s[3].value(), s2[1].value()); + CHECK_EQUAL(s[4].value(), s2[2].value()); + } + + //************************************************************************* + TEST(test_poly_span_first) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s1(data); + + auto s2 = s1.first(3); + auto s3 = s1.first<3>(); + + CHECK_EQUAL(data[0].value(), s2[0].value()); + CHECK_EQUAL(data[1].value(), s2[1].value()); + CHECK_EQUAL(data[2].value(), s2[2].value()); + + CHECK_EQUAL(data[0].value(), s3[0].value()); + CHECK_EQUAL(data[1].value(), s3[1].value()); + CHECK_EQUAL(data[2].value(), s3[2].value()); + } + + //************************************************************************* + TEST(test_poly_span_last) + { + Derived data[] = { 1, 2, 3, 4 }; + etl::poly_span s1(data); + + auto s2 = s1.last(3); + auto s3 = s1.last<3>(); + + CHECK_EQUAL(data[1].value(), s2[0].value()); + CHECK_EQUAL(data[2].value(), s2[1].value()); + CHECK_EQUAL(data[3].value(), s2[2].value()); + + CHECK_EQUAL(data[1].value(), s3[0].value()); + CHECK_EQUAL(data[2].value(), s3[1].value()); + CHECK_EQUAL(data[3].value(), s3[2].value()); + } + + //************************************************************************* + TEST(test_hash) + { + int data[] = { 1, 2, 3, 4 }; + etl::poly_span s1(data); + + size_t hashdata = etl::private_hash::generic_hash(reinterpret_cast(&s1[0]), + reinterpret_cast(&s1[s1.size()])); + + size_t hashview = etl::hash>()(s1); + + CHECK_EQUAL(hashdata, hashview); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_c_array) + { + int data[] = { 1, 2, 3, 4 }; + + etl::poly_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_template_deduction_guide_for_std_array) + { + std::array data = { 1, 2, 3, 4 }; + + etl::poly_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } +#endif + + //************************************************************************* + TEST(test_template_deduction_guide_for_etl_array) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::poly_span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterators) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::poly_span s{ data.begin(), data.end() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterator_and_size) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::poly_span s{ data.begin(), data.size() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + } +} diff --git a/test/test_span.cpp b/test/test_span_dynamic_extent.cpp similarity index 91% rename from test/test_span.cpp rename to test/test_span_dynamic_extent.cpp index 518c5ac9..d8b682e7 100644 --- a/test/test_span.cpp +++ b/test/test_span_dynamic_extent.cpp @@ -38,7 +38,7 @@ SOFTWARE. namespace { - SUITE(test_span) + SUITE(test_span_dynamic_extent) { static const size_t SIZE = 10UL; @@ -630,6 +630,68 @@ namespace CHECK_EQUAL(hashdata, hashcview); } + //************************************************************************* + TEST(test_template_deduction_guide_for_c_array) + { + int data[] = { 1, 2, 3, 4 }; + + etl::span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_template_deduction_guide_for_std_array) + { + std::array data = { 1, 2, 3, 4 }; + + etl::span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } +#endif + + //************************************************************************* + TEST(test_template_deduction_guide_for_etl_array) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterators) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::span s{ data.begin(), data.end() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterator_and_size) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::span s{ data.begin(), data.size() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + //************************************************************************* void f_issue_481(etl::span value) { diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp new file mode 100644 index 00000000..589cfd3b --- /dev/null +++ b/test/test_span_fixed_extent.cpp @@ -0,0 +1,749 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/span.h" +#include "etl/array.h" + +#include +#include +#include +#include + +namespace +{ + SUITE(test_span_fixed_extent) + { + static const size_t SIZE = 10UL; + + typedef etl::array EtlData; + typedef std::array StlData; + typedef std::vector StlVData; + + typedef etl::span View; + typedef etl::span CView; + + EtlData etldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + StlData stldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + StlVData stlvdata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + EtlData etldatasmaller = { 0, 1, 2, 3, 4, 5, 5, 7, 8, 9 }; + + EtlData etloriginal = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + EtlData etlmodified = { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }; + + const EtlData cetldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const StlData cstldata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const StlVData cstlvdata = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + int cdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int* pcdata = cdata; + + const int ccdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + const int* pccdata = ccdata; + + //************************************************************************* + TEST(test_default_constructor) + { + View view; + + CHECK_EQUAL(10U, view.size()); + CHECK_EQUAL(10U, view.max_size()); + CHECK(!view.empty()); + } + + //************************************************************************* + TEST(test_constructor_etl_array_1) + { + View view(etldata); + + CHECK_EQUAL(etldata.size(), view.size()); + CHECK_EQUAL(etldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_etl_array_1_const) + { + CView view(cetldata); + + CHECK_EQUAL(cetldata.size(), view.size()); + CHECK_EQUAL(cetldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), cetldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_etl_array_2) + { + View view(etldata.begin(), etldata.end()); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_etl_array_2_const) + { + CView view(cetldata.begin(), cetldata.end()); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), cetldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_1) + { + View view(stldata); + + CHECK_EQUAL(stldata.size(), view.size()); + CHECK_EQUAL(stldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), stldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_1_const) + { + CView view(cstldata); + + CHECK_EQUAL(cstldata.size(), view.size()); + CHECK_EQUAL(cstldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), cstldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_2) + { + View view(stldata.begin(), stldata.end()); + + CHECK_EQUAL(stldata.size(), view.size()); + CHECK_EQUAL(stldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), stldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_array_2_const) + { + CView view(cstldata.begin(), cstldata.end()); + + CHECK_EQUAL(cstldata.size(), view.size()); + CHECK_EQUAL(cstldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), cstldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_vector_1) + { + View view(stlvdata); + + CHECK_EQUAL(stlvdata.size(), view.size()); + CHECK_EQUAL(stlvdata.size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), stlvdata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_stl_vector_1_const) + { + CView view(cstlvdata); + + CHECK_EQUAL(cstlvdata.size(), view.size()); + CHECK_EQUAL(cstlvdata.size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), cstlvdata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_1) + { + View view(pcdata, SIZE); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), pcdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_1_const) + { + CView view(pccdata, SIZE); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), pccdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_2) + { + View view(cdata); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), cdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_constructor_c_array_2_const) + { + CView view(ccdata); + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), ccdata); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_implicit_constructor_c_array_2) + { + CView view; + + view = ccdata; + + CHECK_EQUAL(SIZE, view.size()); + CHECK_EQUAL(SIZE, view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), ccdata); + CHECK(isEqual); + } + +#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED) + //************************************************************************* + TEST(test_cpp17_deduced_constructor) + { + etl::array data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + etl::span span1{ data }; + etl::span span2{ data.begin(), data.end() }; + etl::span span3{ data.begin(), data.size() }; + etl::span span4{ span1 }; + + int c_array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + etl::span span5{ c_array }; + + bool isEqual = false; + + isEqual = std::equal(span1.begin(), span1.end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span2.begin(), span2.end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span3.begin(), span3.end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span4.begin(), span4.end(), data.begin()); + CHECK(isEqual); + + isEqual = std::equal(span5.begin(), span5.end(), c_array); + CHECK(isEqual); + } +#endif + + //************************************************************************* + TEST(test_constructor_range) + { + View view(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.size(), view.size()); + CHECK_EQUAL(etldata.size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_assign_from_span) + { + View view1(etldata); + View view2; + + CView cview1(etldata); + CView cview2; + + view2 = view1; + cview2 = cview1; + + CHECK_EQUAL(view1.size(), view2.size()); + CHECK_EQUAL(view1.max_size(), view2.max_size()); + + CHECK_EQUAL(cview1.size(), cview2.size()); + CHECK_EQUAL(cview1.max_size(), cview2.max_size()); + + bool isEqual; + + isEqual = std::equal(view1.begin(), view1.end(), view2.begin()); + CHECK(isEqual); + + isEqual = std::equal(cview1.begin(), cview1.end(), cview2.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_modify_range) + { + View view(etloriginal.begin(), etloriginal.end()); + + CHECK_EQUAL(etloriginal.size(), view.size()); + CHECK_EQUAL(etloriginal.size(), view.max_size()); + + std::fill(view.begin(), view.end(), 10); + + bool isEqual; + + isEqual = std::equal(etloriginal.begin(), etloriginal.end(), etlmodified.begin()); + CHECK(isEqual); + + isEqual = std::equal(etldata.begin(), etldata.end(), etlmodified.begin()); + CHECK(!isEqual); + } + + //************************************************************************* + TEST(test_begin_end) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.begin(), view.begin()); + CHECK_EQUAL(etldata.begin(), cview.begin()); + + CHECK_EQUAL(etldata.end(), view.rbegin().base()); + CHECK_EQUAL(etldata.end(), cview.rbegin().base()); + + CHECK_EQUAL(etldata.end(), view.end()); + CHECK_EQUAL(etldata.end(), cview.end()); + + CHECK_EQUAL(etldata.begin(), view.rend().base()); + CHECK_EQUAL(etldata.begin(), cview.rend().base()); + } + + //************************************************************************* + TEST(test_front_back) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.front(), view.front()); + CHECK_EQUAL(etldata.front(), cview.front()); + + CHECK_EQUAL(etldata.back(), view.back()); + CHECK_EQUAL(etldata.back(), cview.back()); + } + + //************************************************************************* + TEST(test_data) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + CHECK_EQUAL(etldata.data(), view.data()); + CHECK_EQUAL(etldata.data(), cview.data()); + } + + //************************************************************************* + TEST(test_index_operator) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + for (size_t i = 0UL; i < etldata.size(); ++i) + { + CHECK_EQUAL(etldata[i], view[i]); + CHECK_EQUAL(etldata[i], cview[i]); + } + } + + //************************************************************************* + TEST(test_assignment_operator) + { + View view(etldata); + CView cview = view; + + CHECK_EQUAL(etldata.size(), view.size()); + CHECK_EQUAL(etldata.max_size(), view.max_size()); + + bool isEqual = std::equal(view.begin(), view.end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_empty) + { + View view1(etldata.begin(), etldata.begin()); + CHECK(!view1.empty()); + } + + //************************************************************************* + TEST(test_size) + { + View view(etldata); + + CHECK_EQUAL(etldata.size(), view.size()); + } + + //************************************************************************* + TEST(test_size_bytes) + { + View view(etldata); + + CHECK_EQUAL(etldata.size() * sizeof(EtlData::value_type), view.size_bytes()); + } + + //************************************************************************* + TEST(test_swap) + { + View view1(etldata); + View view2(etldatasmaller); + + std::swap(view1, view2); + + CHECK_EQUAL(etldata.size(), view1.size()); + CHECK_EQUAL(etldatasmaller.size(), view2.size()); + + bool isEqual; + + isEqual = std::equal(view1.begin(), view1.end(), etldatasmaller.begin()); + CHECK(isEqual); + + isEqual = std::equal(view2.begin(), view2.end(), etldata.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST(test_first) + { + std::vector original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector first = { 0, 1, 2, 3, 4, 5 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.first<6>(); + isEqual = std::equal(result.begin(), result.end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), result.extent); + CHECK_EQUAL(first.size(), result.size()); + + auto cresult = cview.first<6>(); + isEqual = std::equal(cresult.begin(), cresult.end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), cresult.extent); + CHECK_EQUAL(first.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_first_2) + { + std::vector original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector first = { 0, 1, 2, 3, 4, 5 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.first(6); + isEqual = std::equal(result.begin(), result.end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), result.size()); + + auto cresult = cview.first(6); + isEqual = std::equal(cresult.begin(), cresult.end(), first.begin()); + CHECK(isEqual); + CHECK_EQUAL(first.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_last) + { + std::vector original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector last = { 4, 5, 6, 7, 8, 9 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.last<6>(); + isEqual = std::equal(result.begin(), result.end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), result.extent); + CHECK_EQUAL(last.size(), result.size()); + + auto cresult = cview.last<6>(); + isEqual = std::equal(cresult.begin(), cresult.end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), cresult.extent); + CHECK_EQUAL(last.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_last_2) + { + std::vector original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector last = { 4, 5, 6, 7, 8, 9 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto result = view.last(6); + isEqual = std::equal(result.begin(), result.end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), result.size()); + + auto cresult = cview.last(6); + isEqual = std::equal(cresult.begin(), cresult.end(), last.begin()); + CHECK(isEqual); + CHECK_EQUAL(last.size(), cresult.size()); + } + + //************************************************************************* + TEST(test_subspan) + { + std::vector original = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector sub1 = { 2, 3, 4, 5 }; + std::vector sub2 = { 2, 3, 4, 5, 6, 7 }; + View view(original); + CView cview(original); + + bool isEqual; + + auto span1 = view.subspan<2, 4>(); + isEqual = std::equal(span1.begin(), span1.end(), sub1.begin()); + CHECK(isEqual); + CHECK_EQUAL(sub1.size(), span1.extent); + CHECK_EQUAL(sub1.size(), span1.size()); + + auto cspan1 = cview.subspan<2, 4>(); + isEqual = std::equal(cspan1.begin(), cspan1.end(), sub1.begin()); + CHECK(isEqual); + CHECK_EQUAL(sub1.size(), cspan1.extent); + CHECK_EQUAL(sub1.size(), cspan1.size()); + + auto span2 = view.subspan<2>(); + isEqual = std::equal(sub2.begin(), sub2.end(), span2.begin()); + CHECK(isEqual); + CHECK_EQUAL(span2.size(), span2.extent); + + auto cspan2 = cview.subspan<2>(); + isEqual = std::equal(sub2.begin(), sub2.end(), cspan2.begin()); + CHECK(isEqual); + CHECK_EQUAL(original.size() - 2U, cspan2.extent); + + auto span3 = view.subspan(2, 4); + isEqual = std::equal(sub1.begin(), sub1.end(), span3.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, span3.extent); + + auto cspan3 = cview.subspan(2, 4); + isEqual = std::equal(sub1.begin(), sub1.end(), cspan3.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, cspan3.extent); + + auto span4 = view.subspan(2); + isEqual = std::equal(sub2.begin(), sub2.end(), span4.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, span4.extent); + + auto cspan4 = cview.subspan(2); + isEqual = std::equal(sub2.begin(), sub2.end(), cspan4.begin()); + CHECK(isEqual); + CHECK_EQUAL(etl::dynamic_extent, cspan4.extent); + } + + //************************************************************************* + TEST(test_hash) + { + View view(etldata.begin(), etldata.end()); + CView cview(etldata.begin(), etldata.end()); + + size_t hashdata = etl::private_hash::generic_hash(reinterpret_cast(&etldata[0]), + reinterpret_cast(&etldata[etldata.size()])); + + size_t hashview = etl::hash()(view); + size_t hashcview = etl::hash()(cview); + + CHECK_EQUAL(hashdata, hashview); + CHECK_EQUAL(hashdata, hashcview); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_c_array) + { + int data[] = { 1, 2, 3, 4 }; + + etl::span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_template_deduction_guide_for_std_array) + { + std::array data = { 1, 2, 3, 4 }; + + etl::span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } +#endif + + //************************************************************************* + TEST(test_template_deduction_guide_for_etl_array) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::span s = data; + + CHECK_EQUAL(std::size(data), s.extent); + CHECK_EQUAL(std::size(data), s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterators) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::span s{ data.begin(), data.end() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + TEST(test_template_deduction_guide_for_iterator_and_size) + { + etl::array data = { 1, 2, 3, 4 }; + + etl::span s{ data.begin(), data.size() }; + + CHECK_EQUAL(etl::dynamic_extent, s.extent); + CHECK_EQUAL(4U, s.size()); + CHECK((std::is_same_v>)); + } + + //************************************************************************* + void f_issue_481(etl::span value) + { + } + + TEST(test_issue_481) + { + // Should compile. + char c[10]; + f_issue_481(c); + } + + //************************************************************************* + struct C_issue_482 {}; + + void f_issue_482(etl::span) + { + } + + void f_issue_482(etl::span) + { + } + + TEST(test_issue_482) + { + etl::array c; + + // Should compile without ambiguous function error. + f_issue_482(c); + } + + //************************************************************************* + void f_issue_482_2(etl::span) + { + } + + void f_issue_482_2(etl::span) + { + } + + TEST(test_issue_482_2) + { + etl::array c; + + // Should compile without ambiguous function error. + f_issue_482(c); + } + + //************************************************************************* + void f_issue_486(etl::span value) + { + } + + TEST(test_issue_486) + { + //std::array c; + + // Should not compile. + //etl::span value(c); + + // Should not compile. + //f_issue_486(c); + } + }; +} diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index 8f8958b1..097fa781 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -11003,6 +11003,7 @@ + @@ -11746,7 +11747,8 @@ true - + + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index bcf9d2df..32f645b2 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -1739,7 +1739,7 @@ Tests\Containers - + Tests\Containers @@ -3269,6 +3269,12 @@ Tests\Containers + + Tests\Containers + + + Tests\Containers +