Add Span constructors for arrays and vectors
This commit is contained in:
parent
bb3d38fc06
commit
ab303a16d1
1 changed files with 21 additions and 13 deletions
34
src/span.h
34
src/span.h
|
@ -56,6 +56,20 @@ public:
|
|||
/** Default assignment operator. */
|
||||
Span& operator=(const Span& other) noexcept = default;
|
||||
|
||||
/** Construct a Span from an array. This matches the corresponding C++20 std::span constructor. */
|
||||
template <int N>
|
||||
constexpr Span(C (&a)[N]) noexcept : m_data(a), m_size(N) {}
|
||||
|
||||
/** Construct a Span for objects with .data() and .size() (std::string, std::array, std::vector, ...).
|
||||
*
|
||||
* This implements a subset of the functionality provided by the C++20 std::span range-based constructor.
|
||||
*
|
||||
* To prevent surprises, only Spans for constant value types are supported when passing in temporaries.
|
||||
* Note that this restriction does not exist when converting arrays or other Spans (see above).
|
||||
*/
|
||||
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>
|
||||
constexpr Span(V&& v) noexcept : m_data(v.data()), m_size(v.size()) {}
|
||||
|
||||
constexpr C* data() const noexcept { return m_data; }
|
||||
constexpr C* begin() const noexcept { return m_data; }
|
||||
constexpr C* end() const noexcept { return m_data + m_size; }
|
||||
|
@ -79,19 +93,13 @@ public:
|
|||
template <typename O> friend class Span;
|
||||
};
|
||||
|
||||
/** Create a span to a container exposing data() and size().
|
||||
*
|
||||
* This correctly deals with constness: the returned Span's element type will be
|
||||
* whatever data() returns a pointer to. If either the passed container is const,
|
||||
* or its element type is const, the resulting span will have a const element type.
|
||||
*
|
||||
* std::span will have a constructor that implements this functionality directly.
|
||||
*/
|
||||
template<typename A, int N>
|
||||
constexpr Span<A> MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
|
||||
|
||||
template<typename V>
|
||||
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()); }
|
||||
// MakeSpan helps constructing a Span of the right type automatically.
|
||||
/** MakeSpan for arrays: */
|
||||
template <typename A, int N> Span<A> constexpr MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
|
||||
/** MakeSpan for temporaries / rvalue references, only supporting const output. */
|
||||
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); }
|
||||
/** MakeSpan for (lvalue) references, supporting mutable output. */
|
||||
template <typename V> constexpr auto MakeSpan(V& v) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; }
|
||||
|
||||
/** Pop the last element off a span, and return a reference to that element. */
|
||||
template <typename T>
|
||||
|
|
Loading…
Reference in a new issue