diff options
Diffstat (limited to 'src/corelib/tools/qspan.qdoc')
-rw-r--r-- | src/corelib/tools/qspan.qdoc | 683 |
1 files changed, 683 insertions, 0 deletions
diff --git a/src/corelib/tools/qspan.qdoc b/src/corelib/tools/qspan.qdoc new file mode 100644 index 0000000000..9b55b09bf7 --- /dev/null +++ b/src/corelib/tools/qspan.qdoc @@ -0,0 +1,683 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \class QSpan + \inmodule QtCore + \since 6.7 + \brief A non-owning container over contiguous data. + \ingroup tools + \reentrant + + A QSpan references a contiguous portion of another contiguous container. + It acts as an interface type for all kinds of contiguous containers, + without the need to construct an owning container such as QList or + std::vector first. + + The data referenced by a QSpan may be represented as an array (or + array-compatible data-structure such as QList, std::vector, + QVarLengthArray, etc.). QSpan itself merely stores a pointer to the data, + so users must ensure that QSpan objects do not outlive the data they + reference. + + Unlike views such as QStringView, QLatin1StringView and QUtf8StringView, + referenced data can be modified through a QSpan object. To prevent this, + construct a QSpan over a \c{const T}: + + \code + int numbers[] = {0, 1, 2}; + QSpan<int> span = numbers; + span[0] = 42; + // numbers == {42, 1, 2}; + QSpan<const int> cspan = numbers; + cspan[0] = 0; // ERROR: cspan[0] is read-only + \endcode + + A QSpan can be \e{fixed-size} or \e{variable-sized}. + + A variable-sized span is formed by omitting the second template argument + (or setting it to \c{std::dynamic_extent}, which is, however, only + available in C++20 builds), as seen in the example above. + + A fixed-size span is formed by passing a number as the second template + argument: + + \code + int numbers[] = {0, 1, 2}; + QSpan<int, 3> span = numbers; + QSpan<const int, 3> = numbers; // also OK + \endcode + + As the name suggests, a fixed-size span's size() is fixed at compile-time + whereas the size() of a variable-sized span is determined only at run-time. + + A fixed-size span is not default-constructible (unless its \l extent is zero + (0)). A variable-sized span \e{is} default-constructible and will have + \c{data() == nullptr} and \c{size() == 0}. + + A fixed-size span can be implicitly converted into a variable-sized one. + The opposite direction (variable-length into fixed-length) has the + precondition that both span's sizes must match. + + Unlike with owning containers, \c{const} is \e{shallow} in QSpan: you can + still modify the data through a const QSpan (but not through a + \c{QSpan<const T>}), and begin() and end() are not overloaded on + \c{const}/non-\c{const}. There are cbegin() and cend(), though, that return + const_iterators which prevent modification of the data even though \c{T} is + not const: + \code + int numbers[] = {0, 1, 2}; + const QSpan<int> span = numbers; + span.front() = 42; // OK, numbers[0] == 42 now + *span.begin() = 31; // OK, numbers[0] == 31 now + *span.cbegin() = -1; // ERROR: cannot assign through a const_iterator + \endcode + + QSpan should be passed by value, not by reference-to-const: + + \code + void consume(QSpan<const int> data); // OK + void consume(const QSpan<const int> &data); // works, but is non-idiomatic and less efficient + \endcode + + \c{QSpan<T,N>} is a \e{Literal Type}, regardless of whether \c{T} is a + Literal Type or not. + + \section2 QSpan vs. std::span + \target span-STL + + QSpan is closely modelled after + \l{https://en.cppreference.com/w/cpp/container/span}{std::span}, but has a + few differences which we'll discuss here. Since they both implicitly + convert into each other, you're free to choose whichever one you like best + in your own code. + + \list + \li QSpan is using the signed qsizetype as \c{size_type} + whereas \c{std::span} uses \c{size_t}. + \li All QSpan constructors are implicit; + many \c{std::span} ones are \c{explicit}. + \li QSpan can be constructed from rvalue owning containers, \c{std::span} can not. + \endlist + + The last two are required for source-compatibility when functions that took + owning containers are converted to take QSpan instead, which is a + vitally-important use-case in Qt. The use of qsizetype is for consistency + with the rest of Qt containers. QSpan template arguments still use size_t + to avoid introducing unnecessary error conditions (negative sizes). + + \section2 Compatible Iterators + \target span-compatible-iterators + + QSpan can be constructed from an iterator and size or from an + iterator pair, provided the iterators are \e{compatible} ones. + Eventually, this should mean C++20 \c{std::contiguous_iterator} and + \c{std::sentinel_for}, but while Qt still supports C++17, only raw pointers + are considered contiguous iterators. + + \section2 Compatible Ranges + \target span-compatible-ranges + + QSpan can also be constructed from a \e{compatible} range. A range is + compatible if it has \l{span-compatible-iterators}{compatible iterators}. + + \sa QList, QStringView, QLatin1StringView, QUtf8StringView +*/ + +// +// Nested types and constants +// + +/*! + \typedef QSpan::element_type + + An alias for \c{T}. Includes the \c{const}, if any. + + This alias is provided for compatbility with the STL. + + \sa value_type, pointer +*/ + +/*! + \typedef QSpan::value_type + + An alias for \c{T}. Excludes the \c{const}, if any. + + This alias is provided for compatbility with the STL. + + \sa element_type +*/ + +/*! + \typedef QSpan::size_type + + An alias for qsizetype. This \l{span-STL}{differs from \c{std::span}}. + + This alias is provided for compatbility with the STL. +*/ + +/*! + \typedef QSpan::difference_type + + An alias for qptrdiff. This \l{span-STL}{differs from \c{std::span}}. + + This alias is provided for compatbility with the STL. +*/ + +/*! + \typedef QSpan::pointer + + An alias for \c{T*} and \c{element_type*}, respectively. Includes the \c{const}, if any. + + This alias is provided for compatbility with the STL. + + \sa element_type, const_pointer, reference, iterator +*/ + +/*! + \typedef QSpan::const_pointer + + An alias for \c{const T*} and \c{const element_type*}, respectively. + + This alias is provided for compatbility with the STL. + + \sa element_type, pointer, const_reference, const_iterator +*/ + +/*! + \typedef QSpan::reference + + An alias for \c{T&} and \c{element_type&}, respectively. Includes the \c{const}, if any. + + This alias is provided for compatbility with the STL. + + \sa element_type, const_reference, pointer +*/ + +/*! + \typedef QSpan::const_reference + + An alias for \c{const T&} and \c{const element_type&}, respectively. + + This alias is provided for compatbility with the STL. + + \sa element_type, reference, const_pointer +*/ + +/*! + \typedef QSpan::iterator + + An alias for \c{T*} and \c{pointer}, respectively. Includes the \c{const}, if any. + + \sa pointer, const_iterator, reverse_iterator +*/ + +/*! + \typedef QSpan::const_iterator + + An alias for \c{const T*} and \c{const_pointer}, respectively. + + \sa const_pointer, iterator, const_reverse_iterator +*/ + +/*! + \typedef QSpan::reverse_iterator + + An alias for \c{std::reverse_iterator<iterator>}. Includes the \c{const}, if any. + + \sa iterator, const_reverse_iterator +*/ + +/*! + \typedef QSpan::const_reverse_iterator + + An alias for \c{std::reverse_iterator<const_iterator>}. + + \sa const_iterator, reverse_iterator +*/ + +/*! + \variable QSpan::extent + + The second template argument of \c{QSpan<T, E>}, that is, \c{E}. This is + \c{std::dynamic_extent} for variable-sized spans. + + \note While all other sizes and indexes in QSpan use qsizetype, this + variable, like \c{E}, is actually of type \c{size_t}, for compatibility with + \c{std::span} and \c{std::dynamic_extent}. + + \sa size() +*/ + +// +// Constructors and SMFs +// + +/*! + \fn template <typename T, size_t E> QSpan<T,E>::QSpan() + + Default constructor. + + This constructor is only present if \c{E} is either zero (0) or + \c{std::dynamic_extent}. In other words: only fixed-zero-sized or variable-sized spans + are default-constructible. + + \sa extent +*/ + +/*! + \fn template <typename T, size_t E> QSpan<T,E>::QSpan(const QSpan &other) + \fn template <typename T, size_t E> QSpan<T,E>::QSpan(QSpan &&other) + \fn template <typename T, size_t E> QSpan<T,E> &QSpan<T,E>::operator=(const QSpan &other) + \fn template <typename T, size_t E> QSpan<T,E> &QSpan<T,E>::operator=(QSpan &&other) + \fn template <typename T, size_t E> QSpan<T,E>::~QSpan() + + These Special Member Functions are implicitly-defined. + + \note Moves are equivalent to copies. Only data() and size() are copied + from span to span, not the referenced data. +*/ + +/*! + \fn template <typename T, size_t E> template <typename It, QSpan<T, E>::if_compatible_iterator<It>> QSpan<T,E>::QSpan(It first, qsizetype count) + + Constructs a QSpan referencing the data starting at \a first and having length + \a count. + + \c{[first, count)} must be a valid range. + + \note This constructor participates in overload resolution only if \c{It} + is \l{span-compatible-iterators}{a compatible iterator}. +*/ + +/*! + \fn template <typename T, size_t E> template <typename It, QSpan<T, E>::if_compatible_iterator<It>> QSpan<T,E>::QSpan(It first, It last) + + Constructs a QSpan referencing the data starting at \a first and having length + (\a last - \a first). + + \c{[first, last)} must be a valid range. + + \note This constructor participates in overload resolution only if \c{It} + is \l{span-compatible-iterators}{a compatible iterator}. +*/ + +/*! + \fn template <typename T, size_t E> template <size_t N> QSpan<T,E>::QSpan(q20::type_identity_t<T> (&arr)[N]); + \fn template <typename T, size_t E> template <typename S, size_t N, QSpan<T, E>::if_qualification_conversion<S> = true> QSpan<T,E>::QSpan(std::array<S, N> &arr); + \fn template <typename T, size_t E> template <typename S, size_t N, QSpan<T, E>::if_qualification_conversion<S> = true> QSpan<T,E>::QSpan(const std::array<S, N> &arr); + + Constructs a QSpan referencing the data in the supplied array \a arr. + + \note This constructor participates in overload resolution only if + \list + \li either \c{N} or \l{extent} are \c{std::dynamic_extent} or otherwise \l{extent} \c{==} \c{N} + \li and either \c{S} or \c{const S} are the same as \c{T}. + \endlist + + \note \c{q20::type_identity_t} is a C++17 backport of C++20's + \l{https://en.cppreference.com/w/cpp/types/type_identity}{\c{std::type_identity_t}}. +*/ + +/*! + \fn template <typename T, size_t E> template <typename Range, QSpan<T, E>::if_compatible_range<Range> = true> QSpan<T,E>::QSpan(Range &&r) + + Constructs a QSpan referencing the data in the supplied range \a r. + + \note This constructor participates in overload resolution only if \c{Range} + is \l{span-compatible-ranges}{a compatible range}. +*/ + +/*! + \fn template <typename T, size_t E> template <typename S, size_t N, QSpan<T, E>::if_qualification_conversion<S> = true> QSpan<T,E>::QSpan(QSpan<S, N> other); + \fn template <typename T, size_t E> template <typename S, size_t N, QSpan<T, E>::if_qualification_conversion<S> = true> QSpan<T,E>::QSpan(std::span<S, N> other); + + Constructs a QSpan referencing the data in the supplied span \a other. + + \note This constructor participates in overload resolution only if + \list + \li either \c{N} or \l{extent} are \c{std::dynamic_extent} or \l{extent} \c{==} \c{N} + \li and either \c{S} or \c{const S} are the same as \c{T}. + \endlist +*/ + +/*! + \fn template <typename T, size_t E> QSpan<T, E>::QSpan(std::initializer_list<value_type> il); + + Constructs a QSpan referencing the data in the supplied initializer list \a il. + + \note This constructor participates in overload resolution only if \c{T} is \c{const}-qualified. + + \note This constructor is \c{noexcept} only if \c{E} is \c{std::dynamic_extent}. + + \note If \c{E} is not \c{std::dynamic_extent} and the size of \a il is not \c{E}, the behavior is undefined. +*/ + +// +// Member functions: sizes +// + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::size() const + + Returns the size of the span, that is, the number of elements it references. + + \sa size_bytes(), empty(), isEmpty() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::size_bytes() const + + Returns the size of the span in bytes, that is, the number of elements + multiplied by \c{sizeof(T)}. + + \sa size(), empty(), isEmpty() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::empty() const + \fn template <typename T, size_t E> auto QSpan<T, E>::isEmpty() const + + Returns whether the span is empty, that is, whether \c{size() == 0}. + + These functions do the same thing: empty() is provided for STL + compatibility and isEmpty() is provided for Qt compatibility. + + \sa size(), size_bytes() +*/ + +// +// element access +// + +/*! + \fn template <typename T, size_t E> QSpan<T, E>::operator[](size_type idx) const + + Returns a reference to the element at index \a idx in the span. + + The index must be in range, that is, \a idx >= 0 and \a idx < size(), + otherwise the behavior is undefined. + + \sa front(), back(), size(), empty() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::front() const + + Returns a reference to the first element in the span. + + The span must not be empty, otherwise the behavior is undefined. + + \sa operator[](), back(), size(), empty() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::back() const + + Returns a reference to the last element in the span. + + The span must not be empty, otherwise the behavior is undefined. + + \sa operator[](), front(), size(), empty() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::data() const + + Returns a pointer to the beginning of the span. + + The same as calling begin(). + + \sa begin(), front() +*/ + +// +// iterators +// + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::begin() const + + Returns an interator pointing at the beginning of the span. + + Because QSpan iterators are just pointers, this is the same as calling + data(). + + \sa end(), cbegin(), rbegin(), crbegin(), data() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::end() const + + Returns an iterator pointing to one past the end of the span. + + Because QSpan iterators are just pointers, this it the same as calling + \c{data() + size()}. + + \sa begin(), cend(), rend(), crend(), data(), size() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::cbegin() const + + Returns a const_iterator pointing to the beginning of the span. + + This will return a read-only iterator even if \c{T} is not \c{const}: + \code + QSpan<int> span = ~~~; + *span.begin() = 42; // OK + *span.cbegin() = 42; // ERROR: cannot assign through a const_iterator + \endcode + + \sa cend(), begin(), crbegin(), rbegin(), data() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::cend() const + + Returns a const_iterator pointing to one past the end of the span. + + \sa cbegin(), end(), crend(), rend(), data(), size() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::rbegin() const + + Returns a reverse_iterator pointing to the beginning of the reversed span. + + \sa rend(), crbegin(), begin(), cbegin() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::rend() const + + Returns a reverse_iterator pointing to one past the end of the reversed span. + + \sa rbegin(), crend(), end(), cend() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::crbegin() const + + Returns a const_reverse_iterator pointing to the beginning of the reversed span. + + \sa crend(), rbegin(), cbegin(), begin() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::crend() const + + Returns a const_reverse_iterator pointing to one past the end of the reversed span. + + \sa crbegin(), rend(), cend(), end() +*/ + +// +// compile-time subspans: +// + +/*! + \fn template <typename T, size_t E> template <std::size_t Count> auto QSpan<T, E>::first() const + \keyword first-t + + Returns a fixed-sized span of size \c{Count} referencing the first \c{Count} elements of \c{*this}. + + The span must hold at least \c{Count} elements (\c{E} >= \c{Count} \e{and} + size() >= \c{Count}), otherwise the behavior is undefined. + + \sa first(QSpan<T,E>::size_type), last(), subspan() +*/ + +/*! + \fn template <typename T, size_t E> template <std::size_t Count> auto QSpan<T, E>::last() const + \keyword last-t + + Returns a fixed-sized span of size \c{Count} referencing the last \c{Count} elements of \c{*this}. + + The span must hold at least \c{Count} elements (\c{E} >= \c{Count} \e{and} + size() >= \c{Count}), otherwise the behavior is undefined. + + \sa last(QSpan<T,E>::size_type), first(), subspan() +*/ + +/*! + \fn template <typename T, size_t E> template <std::size_t Offset> auto QSpan<T, E>::subspan() const + \keyword subspan-t1 + + Returns a span of size \c{E - Offset} referencing the remainder of this span + after dropping the first \c{Offset} elements. + + If \c{*this} is a variable-sized span, the return type is a variable-sized + span, otherwise it is a fixed-sized span. + + This span must hold at least \c{Offset} elements (\c{E} >= \c{Offset} \e{and} + size() >= \c{Offset}), otherwise the behavior is undefined. + + \sa subspan(QSpan<T,E>::size_type), subspan(), first(), last() +*/ + +/*! + \fn template <typename T, size_t E> template <std::size_t Offset, std::size_t Count> auto QSpan<T, E>::subspan() const + \keyword subspan-t2 + + Returns a span of size \c{Count} referencing the \c{Count} elements of this + span starting at \c{Offset}. + + If \c{*this} is a variable-sized span, the return type is a variable-sized + span, otherwise it is a fixed-sized span. + + This span must hold at least \c{Offset + Count} elements (\c{E} >= + \c{Offset + Count} \e{and} size() >= \c{Offset + Count}), otherwise the + behavior is undefined. + + \sa subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type), subspan(), first(), last() +*/ + +// +// runtime subspans: +// + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::first(qsizetype n) const + \keyword first-n + + Returns a variable-sized span of size \a n referencing the first \a n elements of \c{*this}. + + \a n must be non-negative. + + The span must hold at least \a n elements (\c{E} >= \a n \e{and} size() >= + \a n), otherwise the behavior is undefined. + + \sa {first-t}{first<N>()}, last(QSpan<T,E>::size_type), subspan(QSpan<T,E>::size_type), + subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type) + \sa sliced() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::last(qsizetype n) const + \keyword last-n + + Returns a variable-sized span of size \a n referencing the last \a n elements of \c{*this}. + + \a n must be non-negative. + + The span must hold at least \a n elements (\c{E} >= \a n \e{and} + size() >= \a n), otherwise the behavior is undefined. + + \sa last(), first(QSpan<T,E>::size_type), subspan(QSpan<T,E>::size_type), + subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type), sliced() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::subspan(qsizetype pos) const + \fn template <typename T, size_t E> auto QSpan<T, E>::sliced(qsizetype pos) const + \keyword subspan-n1 + + Returns a variable-sized span of size \c{size() - pos} referencing the + remainder of this span after dropping the first \a pos elements. + + \a pos must be non-negative. + + This span must hold at least \a pos elements (\c{E} >= \a pos \e{and} + size() >= \a pos), otherwise the behavior is undefined. + + These functions do the same thing: subspan() is provided for STL + compatibility and sliced() is provided for Qt compatibility. + + \sa subspan(), first(QSpan<T,E>::size_type), last(QSpan<T,E>::size_type) +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::subspan(qsizetype pos, qsizetype n) const + \fn template <typename T, size_t E> auto QSpan<T, E>::sliced(qsizetype pos, qsizetype n) const + \keyword subspan-n2 + + Returns a variable-sized span of size \a n referencing the \a n elements of + this span starting at \a pos. + + Both \a pos and \a n must be non-negative. + + This span must hold at least \c{pos + n} elements (\c{E} >= + \c{pos + n} \e{and} size() >= \c{pos + n}), otherwise the + behavior is undefined. + + These functions do the same thing: subspan() is provided for STL + compatibility and sliced() is provided for Qt compatibility. + + \sa subspan(), first(QSpan<T,E>::size_type), last(QSpan<T,E>::size_type) +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::as_bytes(QSpan s) + \since 6.8 + + Returns \a s as a \c{QSpan<const std::byte, E'>} whose size() is equal to + \c{s.size_bytes()}. + + If \c{E} is \c{std::dynamic_extent} then so is \c{E'}. + Otherwise, \c{E' = E * sizeof(T)}. + + \note \c{q20::dynamic_extent} is a C++17 backport of C++20's + \l{https://en.cppreference.com/w/cpp/container/span/dynamic_extent}{\c{std::dynamic_extent}}. + + \sa as_writable_bytes(), size_bytes() +*/ + +/*! + \fn template <typename T, size_t E> auto QSpan<T, E>::as_writable_bytes(QSpan s) + \since 6.8 + + Returns \a s as a \c{QSpan<std::byte, E'>} whose size() is equal to + \c{s.size_bytes()}. + + If \c{E} is \c{std::dynamic_extent} then so is \c{E'}. + Otherwise, \c{E' = E * sizeof(T)}. + + \note This function participates in overload resolution only if + \c{!std::is_const_v<T>}. + + \note \c{q20::dynamic_extent} is a C++17 backport of C++20's + \l{https://en.cppreference.com/w/cpp/container/span/dynamic_extent}{\c{std::dynamic_extent}}. + + \sa as_bytes(), size_bytes() +*/ |