[/ Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) ] [section:span span] [simplesect Authors] * Glen Fernandes [endsimplesect] [section Overview] This header <boost/core/span.hpp> provides class template `span`, which is a view over a sequence of objects. It implements the C++20 standard library `std::span` facility. This implementation supports C++11 and higher. In addition to referencing the sequence of objects, the span knows the count of objects. There are two kinds of spans: * Dynamic size (`span<T>` or `span<T, dynamic_extent>`) * Static size (`span<T, N>`) Dynamic size spans have a count that can be a value known at run time. Static size spans have a count that must be known at compile time. [endsect] [section Examples] The following snippet shows a function to compute a SHA1 hash whose parameters and return type use spans. ``` auto sha1(boost::span<const unsigned char> input, boost::span<unsigned char, SHA_DIGEST_LENGTH> ouput) { SHA_CTX context; SHA1_Init(&context); SHA1_Update(&context, input.data(), input.size()); SHA1_Final(output.data(), &context); return output; } ``` [endsect] [section Reference] ``` namespace boost { constexpr std::size_t dynamic_extent = -1; template<class T, std::size_t E = dynamic_extent> class span { public: typedef T element_type; typedef std::remove_cv_t<T> value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef T* iterator; typedef const T* const_iterator; typedef std::reverse_iterator<T*> reverse_iterator; typedef std::reverse_iterator<const T*> const_reverse_iterator; static constexpr std::size_t extent = E; constexpr span() noexcept; explicit(E != dynamic_extent) template<class I> constexpr span(I* f, size_type c); explicit(E != dynamic_extent) template<class I, class L> constexpr span(I* f, L* l); template<std::size_t N> constexpr span(type_identity_t<T> (&a)[N]); template<class U, std::size_t N> constexpr span(std::array<U, N>& a) noexcept; template<class U, std::size_t N> constexpr span(const std::array<U, N>& a) noexcept; explicit(E != dynamic_extent) template<class R> constexpr span(R&& r); explicit(E != dynamic_extent && N == dynamic_extent) template<class U, std::size_t N> constexpr span(const span<U, N>& s) noexcept; template<std::size_t C> constexpr span<T, C> first() const; template<std::size_t C> constexpr span<T, C> last() const; template<std::size_t O, std::size_t C = dynamic_extent> constexpr span<T, see below> subspan() const; constexpr span<T, dynamic_extent> first(size_type c) const; constexpr span<T, dynamic_extent> last(size_type c) const; constexpr span<T, dynamic_extent> subspan(size_type o, size_type c = dynamic_extent) const; constexpr size_type size() const noexcept; constexpr size_type size_bytes() const noexcept; constexpr bool empty() const noexcept; constexpr reference operator[](size_type i) const; constexpr reference front() const; constexpr reference back() const; constexpr pointer data() const noexcept; constexpr iterator begin() const noexcept; constexpr iterator end() const noexcept; constexpr reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; }; template<class I, class L> span(I*, L) -> span<I>; template<class T, std::size_t N> span(T(&)[N]) -> span<T, N>; template<class T, std::size_t N> span(std::array<T, N>&) -> span<T, N>; template<class T, std::size_t N> span(const std::array<T, N>&) -> span<const T, N>; template<class R> span(R&&) -> span<remove_pointer_t<iterator_t<R> > >; template<class T, std::size_t E> span<const std::byte, E == dynamic_extent ? dynamic_extent : sizeof(T) * E> as_bytes(span<T, E> s) noexcept; template<class T, std::size_t E> span<std::byte, E == dynamic_extent ? dynamic_extent : sizeof(T) * E> as_writable_bytes(span<T, E> s) noexcept; } /* boost */ ``` [section Constructors] [variablelist [[`constexpr span() noexcept;`] [[variablelist [[Constraints][`E == dynamic_extent || E == 0` is `true`.]] [[Postconditions][`size() == 0 && data() == nullptr`.]]]]] [[`explicit(E != dynamic_extent) template<class I> constexpr span(I* f, size_type c);`] [[variablelist [[Constraints] [`is_convertible_v<I(*)[], T(*)[]>` is `true`.]] [[Preconditions] [[itemized_list [`[f, f + c)` is a valid range.] [If `E` is not equal to `dynamic_extent`, then `c` is equal to `E`.]]]] [[Effects][Constructs a `span` with data `f` and size `c`.]] [[Throws][Nothing.]]]]] [[`explicit(E != dynamic_extent) template<class I, class L> constexpr span(I* f, L* l);`] [[variablelist [[Constraints] [`is_convertible_v<I(*)[], T(*)[]>` is `true`.]] [[Preconditions] [[itemized_list [If `E` is not equal to `dynamic_extent`, then `l - f` is equal to `E`.] [`[f, l)` is a valid range.]]]] [[Effects][Constructs a `span` with data `f` and size `l - f`.]] [[Throws][Nothing.]]]]] [[`template<std::size_t N> constexpr span(type_identity_t<T> (&a)[N]);`] [[variablelist [[Constraints][`E == dynamic_extent || E == N` is `true`.]] [[Effects][Constructs a `span` that is a view over the supplied array.]] [[Postconditions][`size() == N && data() == &a[0]` is `true`.]]]]] [[`template<class U, std::size_t N> constexpr span(std::array<U, N>& a) noexcept;`] [[variablelist [[Constraints] [[itemized_list [`E == dynamic_extent || E == N` is `true`, and] [`U(*)[]` is convertible to `T(*)[]`.]]]] [[Effects][Constructs a `span` that is a view over the supplied array.]] [[Postconditions][`size() == N && data() == a.data()` is `true`.]]]]] [[`template<class U, std::size_t N> constexpr span(const std::array<U, N>& a) noexcept;`] [[variablelist [[Constraints] [[itemized_list [`E == dynamic_extent || E == N` is `true`, and] [`U(*)[]` is convertible to `T(*)[]`.]]]] [[Effects][Constructs a `span` that is a view over the supplied array.]] [[Postconditions][`size() == N && data() == a.data()` is `true`.]]]]] [[`explicit(E != dynamic_extent) template<class R> constexpr span(R&& r);`] [[variablelist [[Constraints] [[itemized_list [`is_lvalue_reference_v<R> || is_const_v<T>` is `true`] [`remove_cvref_t<R>` is not a specialization of `span`,] [`remove_cvref_t<R>` is not a specialization of `array`,] [`is_array_v<remove_cvref_t<R>>` is `false`,] [`data(r)` is well-formed and `is_convertible_v<remove_pointer_t<iterator_t<R> >(*)[], T(*)[]>` is `true`, and] [`r.size()` is well-formed and `is_convertible_v<decltype(declval<R&>().size()), size_t>` is `true`.]]]] [[Effects][Constructs a `span` with data `data(r)` and size `r.size()`.]] [[Throws][What and when data(r) and r.size() throw.]]]]] [[`explicit(E != dynamic_extent && N == dynamic_extent) template<class U, std::size_t N> constexpr span(const span<U, N>& s) noexcept;`] [[variablelist [[Constraints] [[itemized_list [`E == dynamic_extent || N == dynamic_extent || E == N` is `true`, and] [`is_convertible_v<U(*)[], T(*)[]>` is `true`.]]]] [[Preconditions] [If `E` is not equal to `dynamic_extent`, then `s.size()` is equal to `E`.]] [[Effects] [Constructs a `span` that is a view over the range `[s.data(), s.data() + s.size())`.]] [[Postconditions][`size() == s.size() && data() == s.data()`.]]]]]] [endsect] [section Subviews] [variablelist [[`template<std::size_t C> constexpr span<T, C> first() const;`] [[variablelist [[Mandates][`C <= E` is `true`.]] [[Preconditions][`C <= size()` is `true`.]] [[Effects] [Equivalent to `return R{data(), C};` where `R` is the return type.]]]]] [[`template<std::size_t C> constexpr span<T, C> last() const;`] [[variablelist [[Mandates][`C <= E` is `true`.]] [[Preconditions][`C <= size()` is `true`.]] [[Effects] [Equivalent to `return R{data() + (size() - C), C};` where `R` is the return type.]]]]] [[`template<std::size_t O, std::size_t C = dynamic_extent> constexpr span<T, see below> subspan() const;`] [[variablelist [[Mandates][`O <= E && (C == dynamic_extent || C <= E - O)` is `true`.]] [[Preconditions] [`O <= size() && (C == dynamic_extent || C <= size() - O)` is `true`.]] [[Effects] [Equivalent to `return span<T, see below>(data() + O, C != dynamic_extent ? C : size() - O);`.]] [[Remarks] [The second template argument of the returned span type is: `C != dynamic_extent ? C : (E != dynamic_extent ? E - O : dynamic_extent)`]]]]] [[`constexpr span<T, dynamic_extent> first(size_type c) const;`] [[variablelist [[Preconditions][`c <= size()` is `true`.]] [[Effects][Equivalent to: `return {data(), c};`]]]]] [[`constexpr span<T, dynamic_extent> last(size_type c) const;`] [[variablelist [[Preconditions][`c <= size()` is `true`.]] [[Effects][Equivalent to: `return {data() + (size() - c), c};`]]]]] [[`constexpr span<T, dynamic_extent> subspan(size_type o, size_type c = dynamic_extent) const;`] [[variablelist [[Preconditions] [`o <= size() && (c == dynamic_extent || o + c <= size())` is `true`.]] [[Effects] [Equivalent to: `return {data() + o, c == dynamic_extent ? size() - o : c};`]]]]]] [endsect] [section Observers] [variablelist [[`constexpr size_type size() const noexcept;`] [[variablelist [[Returns][The number of elements in the span.]]]]] [[`constexpr size_type size_bytes() const noexcept;`] [[variablelist [[Effects][Equivalent to: `return size() * sizeof(T);`]]]]] [[`constexpr bool empty() const noexcept;`] [[variablelist [[Effects][Equivalent to: `return size() == 0;`]]]]]] [endsect] [section Element access] [variablelist [[`constexpr reference operator[](size_type i) const;`] [[variablelist [[Preconditions][`i < size()` is `true`.]] [[Effects][Equivalent to: `return *(data() + i);`]]]]] [[`constexpr reference front() const;`] [[variablelist [[Preconditions][`empty()` is `false`.]] [[Effects][Equivalent to: `return *data();`]]]]] [[`constexpr reference back() const;`] [[variablelist [[Preconditions][`empty()` is `false`.]] [[Effects][Equivalent to: `return *(data() + (size() - 1);`]]]]] [[`constexpr pointer data() const noexcept;`] [[variablelist [[Returns][A pointer to the first element in the span.]]]]]] [endsect] [section Iterator support] [variablelist [[`constexpr iterator begin() const noexcept;`] [[variablelist [[Returns][A constant iterator referring to the first element in the span. If `empty()`, then it returns the same value as `cend()`.]]]]] [[`constexpr iterator end() const noexcept;`] [[variablelist [[Returns][A constant iterator which is the past-the-end value.]]]]] [[`constexpr reverse_iterator rbegin() const noexcept;`] [[variablelist [[Effects][Equivalent to: `return reverse_iterator(end());`]]]]] [[`constexpr reverse_iterator rend() const noexcept;`] [[variablelist [[Effects][Equivalent to: `return reverse_iterator(begin());`]]]]] [[`constexpr const_iterator cbegin() const noexcept;`] [[variablelist [[Returns] [A constant iterator referring to the first element in the span. If `empty()`, then it returns the same value as `cend()`.]]]]] [[`constexpr const_iterator cend() const noexcept;`] [[variablelist [[Returns][A constant iterator which is the past-the-end value.]]]]] [[`constexpr const_reverse_iterator crbegin() const noexcept;`] [[variablelist [[Effects][Equivalent to: `return const_reverse_iterator(cend());`]]]]] [[`constexpr const_reverse_iterator crend() const noexcept;`] [[variablelist [[Effects] [Equivalent to: `return const_reverse_iterator(cbegin());`]]]]]] [endsect] [section Views of object representation] [variablelist [[`template<class T, std::size_t E> span<const std::byte, E == dynamic_extent ? dynamic_extent : sizeof(T) * E> as_bytes(span<T, E> s) noexcept;`] [[variablelist [[Effects] [Equivalent to: `return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};`.]]]]] [[`template<class T, std::size_t E> span<std::byte, E == dynamic_extent ? dynamic_extent : sizeof(T) * E> as_writable_bytes(span<T, E> s) noexcept;`] [[variablelist [[Constraints][`is_const_v<T>` is `false`.]] [[Effects] [Equivalent to: `return R{reinterpret_cast<byte*>(s.data()), s.size_bytes()};` where `R` is the return type.]]]]]] [endsect] [endsect] [endsect]