Changes to disable construction from rvalue temporaries

This commit is contained in:
John Wellbelove 2026-03-12 11:31:02 +00:00
parent 4bb4987e5a
commit 0740b2c0ee
3 changed files with 136 additions and 38 deletions

View File

@ -223,7 +223,7 @@ namespace etl
//************************************************************************* //*************************************************************************
template <typename TIteratorBegin, typename TIteratorEnd> template <typename TIteratorBegin, typename TIteratorEnd>
ETL_CONSTEXPR14 span(const TIteratorBegin begin_, const TIteratorEnd end_, ETL_CONSTEXPR14 span(const TIteratorBegin begin_, const TIteratorEnd end_,
typename etl::enable_if<!etl::is_integral<TIteratorEnd>::value, void>::type* = 0) ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS) typename etl::enable_if<!etl::is_integral<TIteratorEnd>::value, void>::type* = 0) ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS)
: pbegin(etl::to_address(begin_)) : pbegin(etl::to_address(begin_))
{ {
ETL_ASSERT(etl::distance(begin_, end_) == Extent, ETL_ERROR(span_size_mismatch)); 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 /// Construct from a container or other type that supports
/// data() and size() member functions. /// data() and size() member functions.
//************************************************************************* //*************************************************************************
template <typename TContainer> template <typename TContainer>
ETL_CONSTEXPR14 span(TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value && ETL_CONSTEXPR14 span(TContainer&& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value && !etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value && !etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value && !etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value && !etl::is_array<TContainer>::value &&
has_size<TContainer>::value && etl::is_lvalue_reference<TContainer&&>::value &&
has_data<TContainer>::value && has_size<TContainer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) has_data<TContainer>::value &&
etl::is_convertible<decltype(etl::declval<typename etl::remove_reference<TContainer>::type&>().data()), pointer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::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 <typename TContainer>
span(TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value &&
has_size<TContainer>::value &&
has_data<TContainer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0)
: pbegin(a.data()) : pbegin(a.data())
{ {
ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch)); ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch));
@ -262,24 +283,25 @@ namespace etl
/// data() and size() member functions. /// data() and size() member functions.
//************************************************************************* //*************************************************************************
template <typename TContainer> template <typename TContainer>
ETL_CONSTEXPR14 span(const TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value && span(const TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value && !etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value && !etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value && !etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
has_size<TContainer>::value && has_size<TContainer>::value &&
has_data<TContainer>::value && has_data<TContainer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0)
: pbegin(a.data()) : pbegin(a.data())
{ {
ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch)); ETL_ASSERT(a.size() == Extent, ETL_ERROR(span_size_mismatch));
} }
#endif
//************************************************************************* //*************************************************************************
/// Constructor from etl array. /// Constructor from etl array.
//************************************************************************* //*************************************************************************
template <typename U, size_t Size> template <typename U, size_t Size>
ETL_CONSTEXPR span(etl::array<U, Size>& other, typename etl::enable_if<(Size == Extent) && ETL_CONSTEXPR span(etl::array<U, Size>& other, typename etl::enable_if<(Size == Extent) &&
etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
: pbegin(other.data()) : pbegin(other.data())
{ {
} }
@ -294,13 +316,18 @@ namespace etl
{ {
} }
#if ETL_USING_CPP11
template <typename U, size_t Size>
span(etl::array<U, Size>&&) = delete;
#endif
#if ETL_USING_STL && ETL_USING_CPP11 #if ETL_USING_STL && ETL_USING_CPP11
//************************************************************************* //*************************************************************************
/// Constructor from std array. /// Constructor from std array.
//************************************************************************* //*************************************************************************
template <typename U, size_t Size> template <typename U, size_t Size>
ETL_CONSTEXPR span(std::array<U, Size>& other, typename etl::enable_if<(Size == Extent) && ETL_CONSTEXPR span(std::array<U, Size>& other, typename etl::enable_if<(Size == Extent) &&
etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT etl::is_convertible<U(*)[], T(*)[]>::value, void>::type* = 0) ETL_NOEXCEPT
: pbegin(other.data()) : pbegin(other.data())
{ {
} }
@ -314,6 +341,9 @@ namespace etl
: pbegin(other.data()) : pbegin(other.data())
{ {
} }
template <typename U, size_t Size>
span(std::array<U, Size>&&) = delete;
#endif #endif
//************************************************************************* //*************************************************************************
@ -351,7 +381,8 @@ namespace etl
/// From fixed extent std::span. /// From fixed extent std::span.
//************************************************************************* //*************************************************************************
template <typename U, size_t Size> template <typename U, size_t Size>
ETL_CONSTEXPR span(const std::span<U, Size>& other, typename etl::enable_if<(Size == Extent), int>::type* = 0) ETL_NOEXCEPT ETL_CONSTEXPR span(const std::span<U, Size>& other, typename etl::enable_if<(Size == Extent) &&
etl::is_convertible<U(*)[], T(*)[]>::value, int>::type* = 0) ETL_NOEXCEPT
: pbegin(other.data()) : pbegin(other.data())
{ {
} }
@ -361,7 +392,8 @@ namespace etl
/// From dynamic extent std::span. /// From dynamic extent std::span.
//************************************************************************* //*************************************************************************
template <typename U, size_t Size> template <typename U, size_t Size>
ETL_CONSTEXPR14 span(const std::span<U, Size>& other, typename etl::enable_if<(Size == etl::dynamic_extent), int>::type* = 0) ETL_NOEXCEPT ETL_CONSTEXPR14 span(const std::span<U, Size>& other, typename etl::enable_if<(Size == etl::dynamic_extent &&
etl::is_convertible<U(*)[], T(*)[]>::value), int>::type* = 0) ETL_NOEXCEPT
: pbegin(other.data()) : pbegin(other.data())
{ {
ETL_ASSERT(other.size() == Extent, ETL_ERROR(span_size_mismatch)); 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 /// Construct from a container or other type that supports
/// data() and size() member functions. /// data() and size() member functions.
//************************************************************************* //*************************************************************************
template <typename TContainer> template <typename TContainer>
ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value && ETL_CONSTEXPR span(TContainer&& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value && !etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value && !etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value && !etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value && !etl::is_array<TContainer>::value &&
has_size<TContainer>::value && etl::is_lvalue_reference<TContainer&&>::value &&
has_data<TContainer>::value && has_size<TContainer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT has_data<TContainer>::value &&
etl::is_convertible<decltype(etl::declval<typename etl::remove_reference<TContainer>::type&>().data()), pointer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::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 <typename TContainer>
span(TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value &&
has_size<TContainer>::value &&
has_data<TContainer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
: pbegin(a.data()) : pbegin(a.data())
, pend(a.data() + a.size()) , pend(a.data() + a.size())
{ {
@ -781,25 +834,26 @@ namespace etl
/// data() and size() member functions. /// data() and size() member functions.
//************************************************************************* //*************************************************************************
template <typename TContainer> template <typename TContainer>
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value && span(const TContainer& a, typename etl::enable_if<!etl::is_span<TContainer>::value &&
!etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value && !etl::is_std_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value && !etl::is_etl_array<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value && !etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<TContainer>::value && !etl::is_array<TContainer>::value &&
has_size<TContainer>::value && has_size<TContainer>::value &&
has_data<TContainer>::value && has_data<TContainer>::value &&
etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT etl::is_same<typename etl::remove_cv<T>::type, typename etl::remove_cv<typename etl::remove_reference<TContainer>::type::value_type>::type>::value, void>::type* = 0) ETL_NOEXCEPT
: pbegin(a.data()) : pbegin(a.data())
, pend(a.data() + a.size()) , pend(a.data() + a.size())
{ {
} }
#endif
#if ETL_USING_STL && ETL_USING_CPP20 #if ETL_USING_STL && ETL_USING_CPP20
//************************************************************************* //*************************************************************************
/// Constructor from std span. /// Constructor from std span.
//************************************************************************* //*************************************************************************
template <typename U, size_t Size> template <typename U, size_t Size>
ETL_CONSTEXPR span(std::span<U, Size>& other) ETL_NOEXCEPT ETL_CONSTEXPR span(std::span<U, Size>& other, typename etl::enable_if<etl::is_convertible<U(*)[], T(*)[]>::value, int>::type* = 0) ETL_NOEXCEPT
: pbegin(other.data()) : pbegin(other.data())
, pend(other.data() + other.size()) , pend(other.data() + other.size())
{ {
@ -809,7 +863,7 @@ namespace etl
/// Constructor from const std span. /// Constructor from const std span.
//************************************************************************* //*************************************************************************
template <typename U, size_t Size> template <typename U, size_t Size>
ETL_CONSTEXPR span(const std::span<U, Size>& other) ETL_NOEXCEPT ETL_CONSTEXPR span(const std::span<U, Size>& other, typename etl::enable_if<etl::is_convertible<U(*)[], T(*)[]>::value, int>::type* = 0) ETL_NOEXCEPT
: pbegin(other.data()) : pbegin(other.data())
, pend(other.data() + other.size()) , pend(other.data() + other.size())
{ {
@ -836,6 +890,11 @@ namespace etl
{ {
} }
#if ETL_USING_CPP11
template <typename U, size_t Size>
span(etl::array<U, Size>&&) = delete;
#endif
#if ETL_USING_STL && ETL_USING_CPP11 #if ETL_USING_STL && ETL_USING_CPP11
//************************************************************************* //*************************************************************************
/// Constructor from std array. /// Constructor from std array.
@ -856,6 +915,9 @@ namespace etl
pend(other.data() + Size) pend(other.data() + Size)
{ {
} }
template <typename U, size_t Size>
span(std::array<U, Size>&&) = delete;
#endif #endif
//************************************************************************* //*************************************************************************

View File

@ -1627,5 +1627,23 @@ namespace
} }
#include "etl/private/diagnostic_pop.h" #include "etl/private/diagnostic_pop.h"
//*************************************************************************
TEST(test_not_constructible_from_rvalue_container)
{
#if ETL_USING_CPP17
CHECK(!(etl::is_constructible_v<View, StlVData&&>));
CHECK(!(etl::is_constructible_v<CView, StlVData&&>));
CHECK(!(etl::is_constructible_v<View, EtlData&&>));
CHECK(!(etl::is_constructible_v<View, StlData&&>));
#else
CHECK(!(etl::is_constructible<View, StlVData&&>::value));
CHECK(!(etl::is_constructible<CView, StlVData&&>::value));
CHECK(!(etl::is_constructible<View, EtlData&&>::value));
CHECK(!(etl::is_constructible<View, StlData&&>::value));
#endif
}
} }
} }

View File

@ -1312,5 +1312,23 @@ namespace
} }
#include "etl/private/diagnostic_pop.h" #include "etl/private/diagnostic_pop.h"
//*************************************************************************
TEST(test_not_constructible_from_rvalue_container)
{
#if ETL_USING_CPP17
CHECK(!(etl::is_constructible_v<View, StlVData&&>));
CHECK(!(etl::is_constructible_v<CView, StlVData&&>));
CHECK(!(etl::is_constructible_v<View, EtlData&&>));
CHECK(!(etl::is_constructible_v<View, StlData&&>));
#else
CHECK(!(etl::is_constructible<View, StlVData&&>::value));
CHECK(!(etl::is_constructible<CView, StlVData&&>::value));
CHECK(!(etl::is_constructible<View, EtlData&&>::value));
CHECK(!(etl::is_constructible<View, StlData&&>::value));
#endif
}
} }
} }