@@ -56,6 +56,20 @@ class Span
56
56
/* * Default assignment operator. */
57
57
Span& operator =(const Span& other) noexcept = default ;
58
58
59
+ /* * Construct a Span from an array. This matches the corresponding C++20 std::span constructor. */
60
+ template <int N>
61
+ constexpr Span (C (&a)[N]) noexcept : m_data(a), m_size(N) {}
62
+
63
+ /* * Construct a Span for objects with .data() and .size() (std::string, std::array, std::vector, ...).
64
+ *
65
+ * This implements a subset of the functionality provided by the C++20 std::span range-based constructor.
66
+ *
67
+ * To prevent surprises, only Spans for constant value types are supported when passing in temporaries.
68
+ * Note that this restriction does not exist when converting arrays or other Spans (see above).
69
+ */
70
+ template <typename V, typename std::enable_if<(std::is_const<C>::value || std::is_lvalue_reference<V>::value) && std::is_convertible<typename std::remove_pointer<decltype (std::declval<V&>().data())>::type (*)[], C (*)[]>::value && std::is_convertible<decltype (std::declval<V&>().size()), std::size_t >::value, int >::type = 0 >
71
+ constexpr Span (V&& v) noexcept : m_data(v.data()), m_size(v.size()) {}
72
+
59
73
constexpr C* data () const noexcept { return m_data; }
60
74
constexpr C* begin () const noexcept { return m_data; }
61
75
constexpr C* end () const noexcept { return m_data + m_size; }
@@ -79,19 +93,13 @@ class Span
79
93
template <typename O> friend class Span ;
80
94
};
81
95
82
- /* * Create a span to a container exposing data() and size().
83
- *
84
- * This correctly deals with constness: the returned Span's element type will be
85
- * whatever data() returns a pointer to. If either the passed container is const,
86
- * or its element type is const, the resulting span will have a const element type.
87
- *
88
- * std::span will have a constructor that implements this functionality directly.
89
- */
90
- template <typename A, int N>
91
- constexpr Span<A> MakeSpan (A (&a)[N]) { return Span<A>(a, N); }
92
-
93
- template <typename V>
94
- constexpr Span<typename std::remove_pointer<decltype (std::declval<V>().data())>::type> MakeSpan (V& v) { return Span<typename std::remove_pointer<decltype (std::declval<V>().data ())>::type>(v.data (), v.size ()); }
96
+ // MakeSpan helps constructing a Span of the right type automatically.
97
+ /* * MakeSpan for arrays: */
98
+ template <typename A, int N> Span<A> constexpr MakeSpan (A (&a)[N]) { return Span<A>(a, N); }
99
+ /* * MakeSpan for temporaries / rvalue references, only supporting const output. */
100
+ template <typename V> constexpr auto MakeSpan (V&& v) -> typename std::enable_if<!std::is_lvalue_reference<V>::value, Span<const typename std::remove_pointer<decltype(v.data())>::type>>::type { return std::forward<V>(v); }
101
+ /* * MakeSpan for (lvalue) references, supporting mutable output. */
102
+ template <typename V> constexpr auto MakeSpan (V& v) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; }
95
103
96
104
/* * Pop the last element off a span, and return a reference to that element. */
97
105
template <typename T>
0 commit comments