Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

span

Overview
Examples
Reference

Authors

  • Glen Fernandes

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.

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;
}
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;

    friend constexpr iterator begin(span s) noexcept {
        return s.begin();
    }

    friend constexpr iterator end(span s) noexcept {
        return s.end();
    }
};

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<std::remove_pointer_t<decltype(std::declval<R&>().data())> >;

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 */

constexpr span() noexcept;

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);

Constraints

is_convertible_v<I(*)[], T(*)[]> is true.

Preconditions
  • [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);

Constraints

is_convertible_v<I(*)[], T(*)[]> is true.

Preconditions
  • 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]);

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;

Constraints
  • 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;

Constraints
  • 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);

Constraints
  • 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,
  • r.data() is well-formed and is_convertible_v<remove_pointer_t<decltype(declval<R&>().data())>(*)[], 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 r.data() and size r.size().
Throws

What and when r.data() 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;

Constraints
  • 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().

template<std::size_t C> constexpr span<T, C> first() const;

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;

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;

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;

Preconditions

c <= size() is true.

Effects

Equivalent to: return {data(), c};

constexpr span<T, dynamic_extent> last(size_type c) const;

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;

Preconditions

o <= size() && (c == dynamic_extent || o + c <= size()) is true.

Effects

Equivalent to: return {data() + o, c == dynamic_extent ? size() - o : c};

constexpr size_type size() const noexcept;

Returns

The number of elements in the span.

constexpr size_type size_bytes() const noexcept;

Effects

Equivalent to: return size() * sizeof(T);

constexpr bool empty() const noexcept;

Effects

Equivalent to: return size() == 0;

constexpr reference operator[](size_type i) const;

Preconditions

i < size() is true.

Effects

Equivalent to: return *(data() + i);

constexpr reference front() const;

Preconditions

empty() is false.

Effects

Equivalent to: return *data();

constexpr reference back() const;

Preconditions

empty() is false.

Effects

Equivalent to: return *(data() + (size() - 1);

constexpr pointer data() const noexcept;

Returns

A pointer to the first element in the span.

constexpr iterator begin() const noexcept;

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;

Returns

A constant iterator which is the past-the-end value.

constexpr reverse_iterator rbegin() const noexcept;

Effects

Equivalent to: return reverse_iterator(end());

constexpr reverse_iterator rend() const noexcept;

Effects

Equivalent to: return reverse_iterator(begin());

constexpr const_iterator cbegin() const noexcept;

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;

Returns

A constant iterator which is the past-the-end value.

constexpr const_reverse_iterator crbegin() const noexcept;

Effects

Equivalent to: return const_reverse_iterator(cend());

constexpr const_reverse_iterator crend() const noexcept;

Effects

Equivalent to: return const_reverse_iterator(cbegin());

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;

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;

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.


PrevUpHomeNext