Skip to content

Commit 2bbc3c3

Browse files
author
John Wellbelove
committed
Merge branch 'pull-request/#1051-Potential-fix-for-span-construct' into development
# Conflicts: # CONTRIBUTING.md # include/etl/span.h # test/test_span_fixed_extent.cpp
2 parents 0ca3043 + e9adc28 commit 2bbc3c3

File tree

2 files changed

+33
-20
lines changed

2 files changed

+33
-20
lines changed

include/etl/span.h

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,16 @@ SOFTWARE.
5050

5151
#include "private/dynamic_extent.h"
5252

53-
#if ETL_USING_CPP20 && ETL_USING_STL
54-
#include <span>
55-
#endif
56-
5753
///\defgroup span span
5854
///\ingroup containers
5955

6056
namespace etl
6157
{
6258
//***************************************************************************
59+
// Tag to indicate a class is a span.
60+
//***************************************************************************
61+
class span_tag {};
62+
6363
///\ingroup span
6464
/// Exception base for span
6565
//***************************************************************************
@@ -91,7 +91,7 @@ namespace etl
9191
/// Span - Fixed Extent
9292
//***************************************************************************
9393
template <typename T, size_t Extent = etl::dynamic_extent>
94-
class span
94+
class span : public span_tag
9595
{
9696
public:
9797

@@ -145,10 +145,11 @@ namespace etl
145145
/// Construct from a container or other type that supports
146146
/// data() and size() member functions.
147147
//*************************************************************************
148-
template <typename TContainer, typename = typename etl::enable_if<!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
148+
template <typename TContainer, typename = typename etl::enable_if<!etl::is_base_of<span_tag, etl::remove_reference_t<TContainer>>::value &&
149+
!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
149150
!etl::is_array<etl::remove_reference_t<TContainer>>::value&&
150151
etl::is_same<etl::remove_cv_t<T>, etl::remove_cv_t<typename etl::remove_reference_t<TContainer>::value_type>>::value, void>::type>
151-
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
152+
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
152153
: pbegin(a.data())
153154
{
154155
}
@@ -158,7 +159,8 @@ namespace etl
158159
/// data() and size() member functions.
159160
//*************************************************************************
160161
template <typename TContainer>
161-
span(TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
162+
span(TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
163+
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
162164
!etl::is_array<TContainer>::value &&
163165
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
164166
: pbegin(a.data())
@@ -170,9 +172,10 @@ namespace etl
170172
/// data() and size() member functions.
171173
//*************************************************************************
172174
template <typename TContainer>
173-
ETL_CONSTEXPR span(const TContainer& a, typename etl::enable_if<!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
174-
!etl::is_array<TContainer>::value&&
175-
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
175+
span(const TContainer& a, typename etl::enable_if<!etl::is_base_of<span_tag, typename etl::remove_reference<TContainer>::type>::value &&
176+
!etl::is_pointer<typename etl::remove_reference<TContainer>::type>::value &&
177+
!etl::is_array<TContainer>::value&&
178+
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
176179
: pbegin(a.data())
177180
{
178181
}
@@ -190,7 +193,7 @@ namespace etl
190193
/// Copy constructor
191194
//*************************************************************************
192195
template <typename U, size_t N>
193-
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) ETL_NOEXCEPT
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
194197
: pbegin(other.data())
195198
{
196199
}
@@ -414,14 +417,14 @@ namespace etl
414417
//*************************************************************************
415418
template <size_t OFFSET, size_t COUNT = etl::dynamic_extent>
416419
ETL_NODISCARD ETL_CONSTEXPR
417-
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET> subspan() const ETL_NOEXCEPT
420+
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET> subspan() const ETL_NOEXCEPT
418421
{
419422
// If Extent is static, check that OFFSET is within the original span
420423
ETL_STATIC_ASSERT((Extent != etl::dynamic_extent) ? OFFSET <= Extent : true, "OFFSET is not within the original span");
421424

422425
// If count is also static, check that OFFSET + COUNT is within the original span
423426
ETL_STATIC_ASSERT((Extent != etl::dynamic_extent) && (COUNT != etl::dynamic_extent) ? COUNT <= (Extent - OFFSET) : true, "OFFSET + COUNT is not within the original span");
424-
427+
425428
return (COUNT == etl::dynamic_extent) ? etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET>(pbegin + OFFSET, (pbegin + Extent))
426429
: etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET>(pbegin + OFFSET, pbegin + OFFSET + COUNT);
427430
}
@@ -437,7 +440,7 @@ namespace etl
437440

438441
// If count is also static, check that OFFSET + COUNT is within the original span
439442
ETL_STATIC_ASSERT((Extent != etl::dynamic_extent) && (COUNT != etl::dynamic_extent) ? COUNT <= (Extent - OFFSET) : true, "OFFSET + COUNT is not within the original span");
440-
443+
441444
if (COUNT == etl::dynamic_extent)
442445
{
443446
return etl::span<element_type, (COUNT != etl::dynamic_extent ? COUNT : Extent - OFFSET)>(pbegin + OFFSET, (pbegin + Extent));
@@ -500,7 +503,7 @@ namespace etl
500503
typedef const T& const_reference;
501504
typedef T* pointer;
502505
typedef const T* const_pointer;
503-
506+
504507
typedef T* iterator;
505508
typedef const T* const_iterator;
506509
typedef ETL_OR_STD::reverse_iterator<iterator> reverse_iterator;
@@ -555,10 +558,11 @@ namespace etl
555558
/// Construct from a container or other type that supports
556559
/// data() and size() member functions.
557560
//*************************************************************************
558-
template <typename TContainer, typename = typename etl::enable_if<!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
561+
template <typename TContainer, typename = typename etl::enable_if<!etl::is_base_of<span_tag, etl::remove_reference_t<TContainer>>::value &&
562+
!etl::is_pointer<etl::remove_reference_t<TContainer>>::value &&
559563
!etl::is_array<etl::remove_reference_t<TContainer>>::value &&
560564
etl::is_same<etl::remove_cv_t<T>, etl::remove_cv_t<typename etl::remove_reference_t<TContainer>::value_type>>::value, void>::type>
561-
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
565+
ETL_CONSTEXPR span(TContainer&& a) ETL_NOEXCEPT
562566
: pbegin(a.data())
563567
, pend(a.data() + a.size())
564568
{
@@ -824,7 +828,7 @@ namespace etl
824828
//*************************************************************************
825829
template <size_t OFFSET, size_t COUNT = etl::dynamic_extent>
826830
ETL_NODISCARD ETL_CONSTEXPR
827-
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent> subspan() const ETL_NOEXCEPT
831+
etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent> subspan() const ETL_NOEXCEPT
828832
{
829833
return (COUNT == etl::dynamic_extent) ? etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent>(pbegin + OFFSET, pend)
830834
: etl::span<element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent>(pbegin + OFFSET, pbegin + OFFSET + COUNT);
@@ -1049,4 +1053,4 @@ namespace etl
10491053
}
10501054
}
10511055

1052-
#endif
1056+
#endif

test/test_span_fixed_extent.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,15 @@ namespace
12351235
CHECK_EQUAL(etl::copy(data0, data1), true);
12361236
}
12371237
}
1238+
1239+
//*************************************************************************
1240+
TEST(test_span_issue_1050_questions_on_span_constructors)
1241+
{
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.
1246+
}
12381247

12391248
#include "etl/private/diagnostic_pop.h"
12401249
};

0 commit comments

Comments
 (0)