mirror of
https://github.com/boostorg/core.git
synced 2025-05-09 23:03:54 +00:00
397 lines
12 KiB
Plaintext
397 lines
12 KiB
Plaintext
[/
|
|
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]
|