Merge branch 'pull-request/#1055-Add-enable_if-restriction-for-span-constructor-from-c-array' into development

# Conflicts:
#	include/etl/span.h
#	test/test_span_fixed_extent.cpp
This commit is contained in:
John Wellbelove 2025-03-28 10:10:52 +00:00
commit dac1602291
2 changed files with 76 additions and 11 deletions

View File

@ -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<size_t Array_Size>
#if ETL_USING_CPP11
template<size_t Array_Size, typename = typename etl::enable_if<(Array_Size == Extent), void>::type>
ETL_CONSTEXPR span(element_type(&begin_)[Array_Size]) ETL_NOEXCEPT
: pbegin(begin_)
{
}
#else
//*************************************************************************
/// Construct from C array
//*************************************************************************
template<size_t Array_Size>
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 <typename U, size_t N>
ETL_CONSTEXPR span(const etl::span<U, N>& 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<U, N>& other, typename etl::enable_if<N == Extent, void>::type* = 0) ETL_NOEXCEPT
: pbegin(other.data())
{
}
//*************************************************************************
/// Copy constructor
/// From dynamic extent span.
//*************************************************************************
template <typename U, size_t N>
ETL_CONSTEXPR span(const etl::span<U, N>& other, typename etl::enable_if<N == etl::dynamic_extent, void>::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<element_type, etl::dynamic_extent>(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 <typename T>
class span<T, etl::dynamic_extent>
class span<T, etl::dynamic_extent> : public span_tag
{
public:
@ -573,7 +621,8 @@ namespace etl
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer>
ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<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())
@ -586,7 +635,8 @@ namespace etl
/// data() and size() member functions.
//*************************************************************************
template <typename TContainer>
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
!etl::is_array<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())

View File

@ -1167,6 +1167,15 @@ namespace
}
}
//*************************************************************************
TEST(test_span_issue_1050_questions_on_span_constructors)
{
int arr[5]{};
etl::span<int, 5> span1(arr);
etl::span<int, 5> span2(span1);
//etl::span<int, 10> 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<int, 5> span1(arr);
etl::span<int, 5> span2(span1);
//etl::span<int, 10> span3(span1); // This line should fail to compile.
int data[5] = { 0, 1, 2, 3, 4 };
etl::span<int> sp1(data);
using span_4 = etl::span<int, 4>;
using span_5 = etl::span<int, 5>;
using span_8 = etl::span<int, 8>;
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"