Skip to content

Commit dac1602

Browse files
author
John Wellbelove
committed
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
2 parents a2119d4 + 077518f commit dac1602

File tree

2 files changed

+76
-11
lines changed

2 files changed

+76
-11
lines changed

include/etl/span.h

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ namespace etl
6060
//***************************************************************************
6161
class span_tag {};
6262

63+
//***************************************************************************
6364
///\ingroup span
6465
/// Exception base for span
6566
//***************************************************************************
@@ -87,6 +88,20 @@ namespace etl
8788
}
8889
};
8990

91+
//***************************************************************************
92+
///\ingroup span
93+
/// span size exception.
94+
//***************************************************************************
95+
class span_size_mismatch : public span_exception
96+
{
97+
public:
98+
99+
span_size_mismatch(string_type file_name_, numeric_type line_number_)
100+
: span_exception(ETL_ERROR_TEXT("span:size", ETL_SPAN_FILE_ID"B"), file_name_, line_number_)
101+
{
102+
}
103+
};
104+
90105
//***************************************************************************
91106
/// Span - Fixed Extent
92107
//***************************************************************************
@@ -134,11 +149,22 @@ namespace etl
134149
//*************************************************************************
135150
/// Construct from C array
136151
//*************************************************************************
137-
template<size_t Array_Size>
152+
#if ETL_USING_CPP11
153+
template<size_t Array_Size, typename = typename etl::enable_if<(Array_Size == Extent), void>::type>
138154
ETL_CONSTEXPR span(element_type(&begin_)[Array_Size]) ETL_NOEXCEPT
139155
: pbegin(begin_)
140156
{
141157
}
158+
#else
159+
//*************************************************************************
160+
/// Construct from C array
161+
//*************************************************************************
162+
template<size_t Array_Size>
163+
ETL_CONSTEXPR span(element_type(&begin_)[Array_Size], typename etl::enable_if<(Array_Size == Extent), void>::type* = 0) ETL_NOEXCEPT
164+
: pbegin(begin_)
165+
{
166+
}
167+
#endif
142168

143169
#if ETL_USING_CPP11
144170
//*************************************************************************
@@ -191,11 +217,23 @@ namespace etl
191217

192218
//*************************************************************************
193219
/// Copy constructor
220+
/// From fixed extent span.
221+
//*************************************************************************
222+
template <typename U, size_t N>
223+
ETL_CONSTEXPR span(const etl::span<U, N>& other, typename etl::enable_if<N == Extent, void>::type* = 0) ETL_NOEXCEPT
224+
: pbegin(other.data())
225+
{
226+
}
227+
228+
//*************************************************************************
229+
/// Copy constructor
230+
/// From dynamic extent span.
194231
//*************************************************************************
195232
template <typename U, size_t N>
196-
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
233+
ETL_CONSTEXPR span(const etl::span<U, N>& other, typename etl::enable_if<N == etl::dynamic_extent, void>::type* = 0)
197234
: pbegin(other.data())
198235
{
236+
ETL_ASSERT(other.size() == Extent, ETL_ERROR(span_size_mismatch));
199237
}
200238

201239
//*************************************************************************
@@ -461,6 +499,16 @@ namespace etl
461499
: etl::span<element_type, etl::dynamic_extent>(pbegin + offset, pbegin + offset + count);
462500
}
463501

502+
//*************************************************************************
503+
/// Moves the pointer to the first element of the span further by a specified number of elements.
504+
///\tparam elements Number of elements to move forward
505+
//*************************************************************************
506+
void advance(size_t elements) ETL_NOEXCEPT
507+
{
508+
elements = etl::min(elements, size());
509+
pbegin += elements;
510+
}
511+
464512
//*************************************************************************
465513
/// Reinterpret the span as a span with different element type.
466514
//*************************************************************************
@@ -492,7 +540,7 @@ namespace etl
492540
/// Span - Dynamic Extent
493541
//***************************************************************************
494542
template <typename T>
495-
class span<T, etl::dynamic_extent>
543+
class span<T, etl::dynamic_extent> : public span_tag
496544
{
497545
public:
498546

@@ -573,7 +621,8 @@ namespace etl
573621
/// data() and size() member functions.
574622
//*************************************************************************
575623
template <typename TContainer>
576-
ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
624+
ETL_CONSTEXPR span(TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
625+
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
577626
!etl::is_array<TContainer>::value &&
578627
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
579628
: pbegin(a.data())
@@ -586,7 +635,8 @@ namespace etl
586635
/// data() and size() member functions.
587636
//*************************************************************************
588637
template <typename TContainer>
589-
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
638+
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
639+
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
590640
!etl::is_array<TContainer>::value &&
591641
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
592642
: pbegin(a.data())

test/test_span_fixed_extent.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,15 @@ namespace
11671167
}
11681168
}
11691169

1170+
//*************************************************************************
1171+
TEST(test_span_issue_1050_questions_on_span_constructors)
1172+
{
1173+
int arr[5]{};
1174+
etl::span<int, 5> span1(arr);
1175+
etl::span<int, 5> span2(span1);
1176+
//etl::span<int, 10> span3(span1); // This line should fail to compile.
1177+
}
1178+
11701179
//*************************************************************************
11711180
TEST(test_reinterpret_as)
11721181
{
@@ -1235,14 +1244,20 @@ namespace
12351244
CHECK_EQUAL(etl::copy(data0, data1), true);
12361245
}
12371246
}
1238-
1247+
12391248
//*************************************************************************
1240-
TEST(test_span_issue_1050_questions_on_span_constructors)
1249+
TEST(test_dynamic_span_to_fixed_span)
12411250
{
1242-
int arr[5]{};
1243-
etl::span<int, 5> span1(arr);
1244-
etl::span<int, 5> span2(span1);
1245-
//etl::span<int, 10> span3(span1); // This line should fail to compile.
1251+
int data[5] = { 0, 1, 2, 3, 4 };
1252+
etl::span<int> sp1(data);
1253+
1254+
using span_4 = etl::span<int, 4>;
1255+
using span_5 = etl::span<int, 5>;
1256+
using span_8 = etl::span<int, 8>;
1257+
1258+
CHECK_NO_THROW({ span_5 sp2(sp1); });
1259+
CHECK_THROW({ span_4 sp3(sp1); }, etl::span_size_mismatch);
1260+
CHECK_THROW({ span_8 sp4(sp1); }, etl::span_size_mismatch);
12461261
}
12471262

12481263
#include "etl/private/diagnostic_pop.h"

0 commit comments

Comments
 (0)