From 0740b2c0ee64785d9f88469f9c9a97d8fe31dbeb Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 12 Mar 2026 11:31:02 +0000 Subject: [PATCH] Changes to disable construction from rvalue temporaries --- include/etl/span.h | 138 ++++++++++++++++++++++-------- test/test_span_dynamic_extent.cpp | 18 ++++ test/test_span_fixed_extent.cpp | 18 ++++ 3 files changed, 136 insertions(+), 38 deletions(-) diff --git a/include/etl/span.h b/include/etl/span.h index 69c1b2e2..c053d37b 100644 --- a/include/etl/span.h +++ b/include/etl/span.h @@ -223,7 +223,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 span(const TIteratorBegin begin_, const TIteratorEnd end_, - typename etl::enable_if::value, void>::type* = 0) ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS) + typename etl::enable_if::value, void>::type* = 0) ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS) : pbegin(etl::to_address(begin_)) { ETL_ASSERT(etl::distance(begin_, end_) == Extent, ETL_ERROR(span_size_mismatch)); @@ -239,19 +239,40 @@ namespace etl { } +#if ETL_USING_CPP11 //************************************************************************* /// Construct from a container or other type that supports /// data() and size() member functions. //************************************************************************* template - ETL_CONSTEXPR14 span(TContainer& a, typename etl::enable_if::value && - !etl::is_std_array::type>::value && - !etl::is_etl_array::type>::value && - !etl::is_pointer::type>::value && - !etl::is_array::value && - has_size::value && - has_data::value && - etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) + ETL_CONSTEXPR14 span(TContainer&& a, typename etl::enable_if::value && + !etl::is_std_array::type>::value && + !etl::is_etl_array::type>::value && + !etl::is_pointer::type>::value && + !etl::is_array::value && + etl::is_lvalue_reference::value && + has_size::value && + has_data::value && + etl::is_convertible::type&>().data()), pointer>::value && + etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS) + : pbegin(a.data()) + { + ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch)); + } +#else + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + span(TContainer& a, typename etl::enable_if::value && + !etl::is_std_array::type>::value && + !etl::is_etl_array::type>::value && + !etl::is_pointer::type>::value && + !etl::is_array::value && + has_size::value && + has_data::value && + etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) : pbegin(a.data()) { ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch)); @@ -262,24 +283,25 @@ namespace etl /// data() and size() member functions. //************************************************************************* template - ETL_CONSTEXPR14 span(const TContainer& a, typename etl::enable_if::value && - !etl::is_std_array::type>::value && - !etl::is_etl_array::type>::value && - !etl::is_pointer::type>::value && - has_size::value && - has_data::value && - etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) + span(const TContainer& a, typename etl::enable_if::value && + !etl::is_std_array::type>::value && + !etl::is_etl_array::type>::value && + !etl::is_pointer::type>::value && + has_size::value && + has_data::value && + etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) : pbegin(a.data()) { ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch)); } +#endif //************************************************************************* /// Constructor from etl array. //************************************************************************* template ETL_CONSTEXPR span(etl::array& other, typename etl::enable_if<(Size == Extent) && - etl::is_convertible::value, void>::type* = 0) ETL_NOEXCEPT + etl::is_convertible::value, void>::type* = 0) ETL_NOEXCEPT : pbegin(other.data()) { } @@ -294,13 +316,18 @@ namespace etl { } +#if ETL_USING_CPP11 + template + span(etl::array&&) = delete; +#endif + #if ETL_USING_STL && ETL_USING_CPP11 //************************************************************************* /// Constructor from std array. //************************************************************************* template ETL_CONSTEXPR span(std::array& other, typename etl::enable_if<(Size == Extent) && - etl::is_convertible::value, void>::type* = 0) ETL_NOEXCEPT + etl::is_convertible::value, void>::type* = 0) ETL_NOEXCEPT : pbegin(other.data()) { } @@ -314,6 +341,9 @@ namespace etl : pbegin(other.data()) { } + + template + span(std::array&&) = delete; #endif //************************************************************************* @@ -351,7 +381,8 @@ namespace etl /// From fixed extent std::span. //************************************************************************* template - ETL_CONSTEXPR span(const std::span& other, typename etl::enable_if<(Size == Extent), int>::type* = 0) ETL_NOEXCEPT + ETL_CONSTEXPR span(const std::span& other, typename etl::enable_if<(Size == Extent) && + etl::is_convertible::value, int>::type* = 0) ETL_NOEXCEPT : pbegin(other.data()) { } @@ -361,7 +392,8 @@ namespace etl /// From dynamic extent std::span. //************************************************************************* template - ETL_CONSTEXPR14 span(const std::span& other, typename etl::enable_if<(Size == etl::dynamic_extent), int>::type* = 0) ETL_NOEXCEPT + ETL_CONSTEXPR14 span(const std::span& other, typename etl::enable_if<(Size == etl::dynamic_extent && + etl::is_convertible::value), int>::type* = 0) ETL_NOEXCEPT : pbegin(other.data()) { ETL_ASSERT(other.size() == Extent, ETL_ERROR(span_size_mismatch)); @@ -758,19 +790,40 @@ namespace etl { } +#if ETL_USING_CPP11 //************************************************************************* /// Construct from a container or other type that supports /// data() and size() member functions. //************************************************************************* template - ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if::value && - !etl::is_std_array::type>::value && - !etl::is_etl_array::type>::value && - !etl::is_pointer::type>::value && - !etl::is_array::value && - has_size::value && - has_data::value && - etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT + ETL_CONSTEXPR span(TContainer&& a, typename etl::enable_if::value && + !etl::is_std_array::type>::value && + !etl::is_etl_array::type>::value && + !etl::is_pointer::type>::value && + !etl::is_array::value && + etl::is_lvalue_reference::value && + has_size::value && + has_data::value && + etl::is_convertible::type&>().data()), pointer>::value && + etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT + : pbegin(a.data()) + , pend(a.data() + a.size()) + { + } +#else + //************************************************************************* + /// Construct from a container or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + span(TContainer& a, typename etl::enable_if::value && + !etl::is_std_array::type>::value && + !etl::is_etl_array::type>::value && + !etl::is_pointer::type>::value && + !etl::is_array::value && + has_size::value && + has_data::value && + etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT : pbegin(a.data()) , pend(a.data() + a.size()) { @@ -781,25 +834,26 @@ namespace etl /// data() and size() member functions. //************************************************************************* template - ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if::value && - !etl::is_std_array::type>::value && - !etl::is_etl_array::type>::value && - !etl::is_pointer::type>::value && - !etl::is_array::value && - has_size::value && - has_data::value && - etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT + span(const TContainer& a, typename etl::enable_if::value && + !etl::is_std_array::type>::value && + !etl::is_etl_array::type>::value && + !etl::is_pointer::type>::value && + !etl::is_array::value && + has_size::value && + has_data::value && + etl::is_same::type, typename etl::remove_cv::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT : pbegin(a.data()) , pend(a.data() + a.size()) { } +#endif #if ETL_USING_STL && ETL_USING_CPP20 //************************************************************************* /// Constructor from std span. //************************************************************************* template - ETL_CONSTEXPR span(std::span& other) ETL_NOEXCEPT + ETL_CONSTEXPR span(std::span& other, typename etl::enable_if::value, int>::type* = 0) ETL_NOEXCEPT : pbegin(other.data()) , pend(other.data() + other.size()) { @@ -809,7 +863,7 @@ namespace etl /// Constructor from const std span. //************************************************************************* template - ETL_CONSTEXPR span(const std::span& other) ETL_NOEXCEPT + ETL_CONSTEXPR span(const std::span& other, typename etl::enable_if::value, int>::type* = 0) ETL_NOEXCEPT : pbegin(other.data()) , pend(other.data() + other.size()) { @@ -836,6 +890,11 @@ namespace etl { } +#if ETL_USING_CPP11 + template + span(etl::array&&) = delete; +#endif + #if ETL_USING_STL && ETL_USING_CPP11 //************************************************************************* /// Constructor from std array. @@ -856,6 +915,9 @@ namespace etl pend(other.data() + Size) { } + + template + span(std::array&&) = delete; #endif //************************************************************************* diff --git a/test/test_span_dynamic_extent.cpp b/test/test_span_dynamic_extent.cpp index 586eadcb..832b4b22 100644 --- a/test/test_span_dynamic_extent.cpp +++ b/test/test_span_dynamic_extent.cpp @@ -1627,5 +1627,23 @@ namespace } #include "etl/private/diagnostic_pop.h" + + //************************************************************************* + TEST(test_not_constructible_from_rvalue_container) + { +#if ETL_USING_CPP17 + CHECK(!(etl::is_constructible_v)); + CHECK(!(etl::is_constructible_v)); + + CHECK(!(etl::is_constructible_v)); + CHECK(!(etl::is_constructible_v)); +#else + CHECK(!(etl::is_constructible::value)); + CHECK(!(etl::is_constructible::value)); + + CHECK(!(etl::is_constructible::value)); + CHECK(!(etl::is_constructible::value)); +#endif + } } } diff --git a/test/test_span_fixed_extent.cpp b/test/test_span_fixed_extent.cpp index a507ad7f..a79ebb70 100644 --- a/test/test_span_fixed_extent.cpp +++ b/test/test_span_fixed_extent.cpp @@ -1312,5 +1312,23 @@ namespace } #include "etl/private/diagnostic_pop.h" + + //************************************************************************* + TEST(test_not_constructible_from_rvalue_container) + { +#if ETL_USING_CPP17 + CHECK(!(etl::is_constructible_v)); + CHECK(!(etl::is_constructible_v)); + + CHECK(!(etl::is_constructible_v)); + CHECK(!(etl::is_constructible_v)); +#else + CHECK(!(etl::is_constructible::value)); + CHECK(!(etl::is_constructible::value)); + + CHECK(!(etl::is_constructible::value)); + CHECK(!(etl::is_constructible::value)); +#endif + } } }