diff --git a/include/etl/span.h b/include/etl/span.h index 0d43acc7..bb30cea5 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -60,6 +60,7 @@ namespace etl //*************************************************************************** class span_tag {}; + //*************************************************************************** ///\ingroup span /// Exception base for span //*************************************************************************** @@ -87,6 +88,20 @@ namespace etl } }; + //*************************************************************************** + ///\ingroup span + /// span size exception. + //*************************************************************************** + class span_size_mismatch : public span_exception + { + public: + + span_size_mismatch(string_type file_name_, numeric_type line_number_) + : span_exception(ETL_ERROR_TEXT("span:size", ETL_SPAN_FILE_ID"B"), file_name_, line_number_) + { + } + }; + //*************************************************************************** /// Span - Fixed Extent //*************************************************************************** @@ -134,11 +149,22 @@ namespace etl //************************************************************************* /// Construct from C array //************************************************************************* - template +#if ETL_USING_CPP11 + template::type> ETL_CONSTEXPR span(element_type(&begin_)[Array_Size]) ETL_NOEXCEPT : pbegin(begin_) { } +#else + //************************************************************************* + /// Construct from C array + //************************************************************************* + template + ETL_CONSTEXPR span(element_type(&begin_)[Array_Size], typename etl::enable_if<(Array_Size == Extent), void>::type* = 0) ETL_NOEXCEPT + : pbegin(begin_) + { + } +#endif #if ETL_USING_CPP11 //************************************************************************* @@ -191,13 +217,25 @@ namespace etl //************************************************************************* /// Copy constructor + /// From fixed extent span. //************************************************************************* template - ETL_CONSTEXPR span(const etl::span& other, typename etl::enable_if<(Extent == etl::dynamic_extent) || (N == etl::dynamic_extent) || (N == Extent), void>::type* = 0) ETL_NOEXCEPT + ETL_CONSTEXPR span(const etl::span& other, typename etl::enable_if::type* = 0) ETL_NOEXCEPT : pbegin(other.data()) { } + //************************************************************************* + /// Copy constructor + /// From dynamic extent span. + //************************************************************************* + template + ETL_CONSTEXPR span(const etl::span& other, typename etl::enable_if::type* = 0) + : pbegin(other.data()) + { + ETL_ASSERT(other.size() == Extent, ETL_ERROR(span_size_mismatch)); + } + //************************************************************************* /// Returns a reference to the first element. //************************************************************************* @@ -461,6 +499,16 @@ namespace etl : etl::span(pbegin + offset, pbegin + offset + count); } + //************************************************************************* + /// Moves the pointer to the first element of the span further by a specified number of elements. + ///\tparam elements Number of elements to move forward + //************************************************************************* + void advance(size_t elements) ETL_NOEXCEPT + { + elements = etl::min(elements, size()); + pbegin += elements; + } + //************************************************************************* /// Reinterpret the span as a span with different element type. //************************************************************************* @@ -492,7 +540,7 @@ namespace etl /// Span - Dynamic Extent //*************************************************************************** template - class span + class span : public span_tag { public: @@ -573,7 +621,8 @@ namespace etl /// data() and size() member functions. //************************************************************************* template - ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if::type>::value && + ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if::type>::value && + !etl::is_pointer::type>::value && !etl::is_array::value && etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT : pbegin(a.data()) @@ -586,7 +635,8 @@ namespace etl /// data() and size() member functions. //************************************************************************* template - ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if::type>::value && + ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if::type>::value && + !etl::is_pointer::type>::value && !etl::is_array::value && etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT : pbegin(a.data()) diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp index 75c9a8ea..fe6b50e4 100644 --- a/test/test_span_fixed_extent.cpp +++ b/test/test_span_fixed_extent.cpp @@ -1167,6 +1167,15 @@ namespace } } + //************************************************************************* + TEST(test_span_issue_1050_questions_on_span_constructors) + { + int arr[5]{}; + etl::span span1(arr); + etl::span span2(span1); + //etl::span span3(span1); // This line should fail to compile. + } + //************************************************************************* TEST(test_reinterpret_as) { @@ -1235,14 +1244,20 @@ namespace CHECK_EQUAL(etl::copy(data0, data1), true); } } - + //************************************************************************* - TEST(test_span_issue_1050_questions_on_span_constructors) + TEST(test_dynamic_span_to_fixed_span) { - int arr[5]{}; - etl::span span1(arr); - etl::span span2(span1); - //etl::span span3(span1); // This line should fail to compile. + int data[5] = { 0, 1, 2, 3, 4 }; + etl::span sp1(data); + + using span_4 = etl::span; + using span_5 = etl::span; + using span_8 = etl::span; + + CHECK_NO_THROW({ span_5 sp2(sp1); }); + CHECK_THROW({ span_4 sp3(sp1); }, etl::span_size_mismatch); + CHECK_THROW({ span_8 sp4(sp1); }, etl::span_size_mismatch); } #include "etl/private/diagnostic_pop.h"