Skip to content

Commit af69e1f

Browse files
committed
Span: use static assert to kill copy construction from an incompatible span type.
Copy construction between Span of compatible type is allowed to fulfil the use case Span<T> -> Span<const T>. This is achieved by a templated copy constructor like constructor. In p0122, the overload is discarded from the constructor set if the ElementType of the Span in input is not convertible into the ElementType of the Span being constructed. To discard function overload, SFINAE has to be used which polutes the documentation and make the code harder to read and maintain. Unlike p0122, our Span class doesn't exposes (yet) functions with default argument or functions that convert container in input into span the only overload with the a single parameter that we exposes are: - template<size_t N> Span(ElementType (&element)[N]) - Span(const Span& other): <- generated by the compiler. For both of this functions we expect exact match and their resolution should not interfere with the constructor that converts from another type of Span. As a result it is possible to rely solely on C++ default resolution rules as we won't hit cases were constructors convert from another type (std::array, std container, span) and raise an error with a static assert if the element type can't be converted. If another copy - conversion - constructor is added then SFINAE has to be reintroduced.
1 parent d5051a8 commit af69e1f

File tree

1 file changed

+16
-23
lines changed

1 file changed

+16
-23
lines changed

platform/Span.h

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,6 @@ class is_convertible
4545
static const bool value = sizeof(true_type) == sizeof(sink(generator()));
4646
};
4747

48-
template<bool Condition, typename ResultType = void>
49-
struct enable_if;
50-
51-
template<typename ResultType>
52-
struct enable_if<true, ResultType> {
53-
typedef ResultType type;
54-
};
55-
5648
}
5749

5850
/**
@@ -309,13 +301,14 @@ struct Span {
309301
* @note OtherElementType(*)[] should be convertible to ElementType(*)[].
310302
*/
311303
template<typename OtherElementType>
312-
Span(
313-
const Span<OtherElementType, Extent> &other,
314-
typename span_detail::enable_if<
315-
span_detail::is_convertible<OtherElementType (*)[], ElementType (*)[]>::value
316-
>::type* = 0
317-
):
318-
_data(other.data()) { }
304+
Span(const Span<OtherElementType, Extent> &other):
305+
_data(other.data())
306+
{
307+
MBED_STATIC_ASSERT(
308+
(span_detail::is_convertible<OtherElementType (*)[], ElementType (*)[]>::value),
309+
"OtherElementType(*)[] should be convertible to ElementType (*)[]"
310+
);
311+
}
319312

320313
/**
321314
* Return the size of the sequence viewed.
@@ -499,7 +492,6 @@ struct Span {
499492
*/
500493
template<typename ElementType>
501494
struct Span<ElementType, SPAN_DYNAMIC_EXTENT> {
502-
503495
/**
504496
* Type of the element contained
505497
*/
@@ -598,13 +590,14 @@ struct Span<ElementType, SPAN_DYNAMIC_EXTENT> {
598590
* @note OtherElementType(*)[] should be convertible to ElementType(*)[].
599591
*/
600592
template<typename OtherElementType, ptrdiff_t OtherExtent>
601-
Span(
602-
const Span<OtherElementType, OtherExtent> &other,
603-
typename span_detail::enable_if<
604-
span_detail::is_convertible<OtherElementType (*)[], ElementType (*)[]>::value
605-
>::type* = NULL
606-
):
607-
_data(other.data()), _size(other.size()) { }
593+
Span(const Span<OtherElementType, OtherExtent> &other):
594+
_data(other.data()), _size(other.size())
595+
{
596+
MBED_STATIC_ASSERT(
597+
(span_detail::is_convertible<OtherElementType (*)[], ElementType (*)[]>::value),
598+
"OtherElementType(*)[] should be convertible to ElementType (*)[]"
599+
);
600+
}
608601

609602
/**
610603
* Return the size of the array viewed.

0 commit comments

Comments
 (0)