Skip to content

Commit d5051a8

Browse files
committed
Span: Allow copy construction from convertible span.
Addition of these overloads help when Span<const T> is constructed from Span<T>.
1 parent b7f074e commit d5051a8

File tree

1 file changed

+57
-3
lines changed

1 file changed

+57
-3
lines changed

platform/Span.h

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,36 @@
2525

2626
namespace mbed {
2727

28+
// Internal details of span
29+
// It is used construct span from span of convertible types (non const -> const)
30+
namespace span_detail {
31+
32+
// If From type is convertible to To type then the compilation constant value is
33+
// true otherwise it is false.
34+
template<typename From, typename To>
35+
class is_convertible
36+
{
37+
struct true_type { char x[512]; };
38+
struct false_type { };
39+
40+
static const From& generator();
41+
static true_type sink(const To &);
42+
static false_type sink(...);
43+
44+
public:
45+
static const bool value = sizeof(true_type) == sizeof(sink(generator()));
46+
};
47+
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+
56+
}
57+
2858
/**
2959
* Special value for the Extent parameter of Span.
3060
* If the type use this value then the size of the array is stored in the object
@@ -269,6 +299,24 @@ struct Span {
269299
Span(element_type (&elements)[Extent]):
270300
_data(elements) { }
271301

302+
/**
303+
* Construct a Span object from another Span of the same size.
304+
*
305+
* @param other The Span object used to construct this.
306+
*
307+
* @note For span with a positive extent, this function is not accessible.
308+
*
309+
* @note OtherElementType(*)[] should be convertible to ElementType(*)[].
310+
*/
311+
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()) { }
319+
272320
/**
273321
* Return the size of the sequence viewed.
274322
*
@@ -540,16 +588,22 @@ struct Span<ElementType, SPAN_DYNAMIC_EXTENT> {
540588
Span(element_type (&elements)[Count]):
541589
_data(elements), _size(Count) { }
542590

543-
544591
/**
545592
* Construct a Span object from another Span.
546593
*
547594
* @param other The Span object used to construct this.
548595
*
549596
* @note For span with a positive extent, this function is not accessible.
597+
*
598+
* @note OtherElementType(*)[] should be convertible to ElementType(*)[].
550599
*/
551-
template<ptrdiff_t OtherExtent>
552-
Span(const Span<element_type, OtherExtent> &other):
600+
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+
):
553607
_data(other.data()), _size(other.size()) { }
554608

555609
/**

0 commit comments

Comments
 (0)