1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
8 \brief A non-owning container over contiguous data.
12 A QSpan references a contiguous portion of another contiguous container.
13 It acts as an interface type for all kinds of contiguous containers,
14 without the need to construct an owning container such as QList or
17 The data referenced by a QSpan may be represented as an array (or
18 array-compatible data-structure such as QList, std::vector,
19 QVarLengthArray, etc.). QSpan itself merely stores a pointer to the data,
20 so users must ensure that QSpan objects do not outlive the data they
23 Unlike views such as QStringView, QLatin1StringView and QUtf8StringView,
24 referenced data can be modified through a QSpan object. To prevent this,
25 construct a QSpan over a \c{const T}:
28 int numbers[] = {0, 1, 2};
29 QSpan<int> span = numbers;
31 // numbers == {42, 1, 2};
32 QSpan<const int> cspan = numbers;
33 cspan[0] = 0; // ERROR: cspan[0] is read-only
36 A QSpan can be \e{fixed-size} or \e{variable-sized}.
38 A variable-sized span is formed by omitting the second template argument
39 (or setting it to \c{std::dynamic_extent}, which is, however, only
40 available in C++20 builds), as seen in the example above.
42 A fixed-size span is formed by passing a number as the second template
46 int numbers[] = {0, 1, 2};
47 QSpan<int, 3> span = numbers;
48 QSpan<const int, 3> = numbers; // also OK
51 As the name suggests, a fixed-size span's size() is fixed at compile-time
52 whereas the size() of a variable-sized span is determined only at run-time.
54 A fixed-size span is not default-constructible (unless its \l extent is zero
55 (0)). A variable-sized span \e{is} default-constructible and will have
56 \c{data() == nullptr} and \c{size() == 0}.
58 A fixed-size span can be implicitly converted into a variable-sized one.
59 The opposite direction (variable-length into fixed-length) has the
60 precondition that both span's sizes must match.
62 Unlike with owning containers, \c{const} is \e{shallow} in QSpan: you can
63 still modify the data through a const QSpan (but not through a
64 \c{QSpan<const T>}), and begin() and end() are not overloaded on
65 \c{const}/non-\c{const}. There are cbegin() and cend(), though, that return
66 const_iterators which prevent modification of the data even though \c{T} is
69 int numbers[] = {0, 1, 2};
70 const QSpan<int> span = numbers;
71 span.front() = 42; // OK, numbers[0] == 42 now
72 *span.begin() = 31; // OK, numbers[0] == 31 now
73 *span.cbegin() = -1; // ERROR: cannot assign through a const_iterator
76 QSpan should be passed by value, not by reference-to-const:
79 void consume(QSpan<const int> data); // OK
80 void consume(const QSpan<const int> &data); // works, but is non-idiomatic and less efficient
83 \c{QSpan<T,N>} is a \e{Literal Type}, regardless of whether \c{T} is a
86 \section2 QSpan vs. std::span
89 QSpan is closely modelled after
90 \l{https://en.cppreference.com/w/cpp/container/span}{std::span}, but has a
91 few differences which we'll discuss here. Since they both implicitly
92 convert into each other, you're free to choose whichever one you like best
96 \li QSpan is using the signed qsizetype as \c{size_type}
97 whereas \c{std::span} uses \c{size_t}.
98 \li All QSpan constructors are implicit;
99 many \c{std::span} ones are \c{explicit}.
100 \li QSpan can be constructed from rvalue owning containers, \c{std::span} can not.
103 The last two are required for source-compatibility when functions that took
104 owning containers are converted to take QSpan instead, which is a
105 vitally-important use-case in Qt. The use of qsizetype is for consistency
106 with the rest of Qt containers. QSpan template arguments still use size_t
107 to avoid introducing unnecessary error conditions (negative sizes).
109 \section2 Compatible Iterators
110 \target span-compatible-iterators
112 QSpan can be constructed from an iterator and size or from an
113 iterator pair, provided the iterators are \e{compatible} ones.
114 Eventually, this should mean C++20 \c{std::contiguous_iterator} and
115 \c{std::sentinel_for}, but while Qt still supports C++17, only raw pointers
116 are considered contiguous iterators.
118 \section2 Compatible Ranges
119 \target span-compatible-ranges
121 QSpan can also be constructed from a \e{compatible} range. A range is
122 compatible if it has \l{span-compatible-iterators}{compatible iterators}.
124 \sa QList, QStringView, QLatin1StringView, QUtf8StringView
128// Nested types and constants
132 \typedef QSpan::element_type
134 An alias for \c{T}. Includes the \c{const}, if any.
136 This alias is provided for compatbility with the STL.
138 \sa value_type, pointer
142 \typedef QSpan::value_type
144 An alias for \c{T}. Excludes the \c{const}, if any.
146 This alias is provided for compatbility with the STL.
152 \typedef QSpan::size_type
154 An alias for qsizetype. This \l{span-STL}{differs from \c{std::span}}.
156 This alias is provided for compatbility with the STL.
160 \typedef QSpan::difference_type
162 An alias for qptrdiff. This \l{span-STL}{differs from \c{std::span}}.
164 This alias is provided for compatbility with the STL.
168 \typedef QSpan::pointer
170 An alias for \c{T*} and \c{element_type*}, respectively. Includes the \c{const}, if any.
172 This alias is provided for compatbility with the STL.
174 \sa element_type, const_pointer, reference, iterator
178 \typedef QSpan::const_pointer
180 An alias for \c{const T*} and \c{const element_type*}, respectively.
182 This alias is provided for compatbility with the STL.
184 \sa element_type, pointer, const_reference, const_iterator
188 \typedef QSpan::reference
190 An alias for \c{T&} and \c{element_type&}, respectively. Includes the \c{const}, if any.
192 This alias is provided for compatbility with the STL.
194 \sa element_type, const_reference, pointer
198 \typedef QSpan::const_reference
200 An alias for \c{const T&} and \c{const element_type&}, respectively.
202 This alias is provided for compatbility with the STL.
204 \sa element_type, reference, const_pointer
208 \typedef QSpan::iterator
210 An alias for \c{T*} and \c{pointer}, respectively. Includes the \c{const}, if any.
212 \sa pointer, const_iterator, reverse_iterator
216 \typedef QSpan::const_iterator
218 An alias for \c{const T*} and \c{const_pointer}, respectively.
220 \sa const_pointer, iterator, const_reverse_iterator
224 \typedef QSpan::reverse_iterator
226 An alias for \c{std::reverse_iterator<iterator>}. Includes the \c{const}, if any.
228 \sa iterator, const_reverse_iterator
232 \typedef QSpan::const_reverse_iterator
234 An alias for \c{std::reverse_iterator<const_iterator>}.
236 \sa const_iterator, reverse_iterator
240 \variable QSpan::extent
242 The second template argument of \c{QSpan<T, E>}, that is, \c{E}. This is
243 \c{std::dynamic_extent} for variable-sized spans.
245 \note While all other sizes and indexes in QSpan use qsizetype, this
246 variable, like \c{E}, is actually of type \c{size_t}, for compatibility with
247 \c{std::span} and \c{std::dynamic_extent}.
253// Constructors and SMFs
257 \fn template <typename T, size_t E> QSpan<T,E>::QSpan()
261 This constructor is only present if \c{E} is either zero (0) or
262 \c{std::dynamic_extent}. In other words: only fixed-zero-sized or variable-sized spans
263 are default-constructible.
269 \fn template <typename T, size_t E> QSpan<T,E>::QSpan(const QSpan &other)
270 \fn template <typename T, size_t E> QSpan<T,E>::QSpan(QSpan &&other)
271 \fn template <typename T, size_t E> QSpan<T,E> &QSpan<T,E>::operator=(const QSpan &other)
272 \fn template <typename T, size_t E> QSpan<T,E> &QSpan<T,E>::operator=(QSpan &&other)
273 \fn template <typename T, size_t E> QSpan<T,E>::~QSpan()
275 These Special Member Functions are implicitly-defined.
277 \note Moves are equivalent to copies. Only data() and size() are copied
278 from span to span, not the referenced data.
282 \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)
284 Constructs a QSpan referencing the data starting at \a first and having length
287 \c{[first, count)} must be a valid range.
289 \note This constructor participates in overload resolution only if \c{It}
290 is \l{span-compatible-iterators}{a compatible iterator}.
294 \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)
296 Constructs a QSpan referencing the data starting at \a first and having length
297 (\a last - \a first).
299 \c{[first, last)} must be a valid range.
301 \note This constructor participates in overload resolution only if \c{It}
302 is \l{span-compatible-iterators}{a compatible iterator}.
306 \fn template <typename T, size_t E> template <size_t N> QSpan<T,E>::QSpan(q20::type_identity_t<T> (&arr)[N]);
307 \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);
308 \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);
310 Constructs a QSpan referencing the data in the supplied array \a arr.
312 \note This constructor participates in overload resolution only if
314 \li either \c{N} or \l{extent} are \c{std::dynamic_extent} or otherwise \l{extent} \c{==} \c{N}
315 \li and either \c{S} or \c{const S} are the same as \c{T}.
318 \note \c{q20::type_identity_t} is a C++17 backport of C++20's
319 \l{https://en.cppreference.com/w/cpp/types/type_identity}{\c{std::type_identity_t}}.
323 \fn template <typename T, size_t E> template <typename Range, QSpan<T, E>::if_compatible_range<Range> = true> QSpan<T,E>::QSpan(Range &&r)
325 Constructs a QSpan referencing the data in the supplied range \a r.
327 \note This constructor participates in overload resolution only if \c{Range}
328 is \l{span-compatible-ranges}{a compatible range}.
332 \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);
333 \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);
335 Constructs a QSpan referencing the data in the supplied span \a other.
337 \note This constructor participates in overload resolution only if
339 \li either \c{N} or \l{extent} are \c{std::dynamic_extent} or \l{extent} \c{==} \c{N}
340 \li and either \c{S} or \c{const S} are the same as \c{T}.
345 \fn template <typename T, size_t E> QSpan<T, E>::QSpan(std::initializer_list<value_type> il);
347 Constructs a QSpan referencing the data in the supplied initializer list \a il.
349 \note This constructor participates in overload resolution only if \c{T} is \c{const}-qualified.
351 \note This constructor is \c{noexcept} only if \c{E} is \c{std::dynamic_extent}.
353 \note If \c{E} is not \c{std::dynamic_extent} and the size of \a il is not \c{E}, the behavior is undefined.
357// Member functions: sizes
361 \fn template <typename T, size_t E> auto QSpan<T, E>::size() const
363 Returns the size of the span, that is, the number of elements it references.
365 \sa size_bytes(), empty(), isEmpty()
369 \fn template <typename T, size_t E> auto QSpan<T, E>::size_bytes() const
371 Returns the size of the span in bytes, that is, the number of elements
372 multiplied by \c{sizeof(T)}.
374 \sa size(), empty(), isEmpty()
378 \fn template <typename T, size_t E> auto QSpan<T, E>::empty() const
379 \fn template <typename T, size_t E> auto QSpan<T, E>::isEmpty() const
381 Returns whether the span is empty, that is, whether \c{size() == 0}.
383 These functions do the same thing: empty() is provided for STL
384 compatibility and isEmpty() is provided for Qt compatibility.
386 \sa size(), size_bytes()
394 \fn template <typename T, size_t E> QSpan<T, E>::operator[](size_type idx) const
396 Returns a reference to the element at index \a idx in the span.
398 The index must be in range, that is, \a idx >= 0 and \a idx < size(),
399 otherwise the behavior is undefined.
401 \sa front(), back(), size(), empty()
405 \fn template <typename T, size_t E> auto QSpan<T, E>::front() const
407 Returns a reference to the first element in the span.
409 The span must not be empty, otherwise the behavior is undefined.
411 \sa operator[](), back(), size(), empty()
415 \fn template <typename T, size_t E> auto QSpan<T, E>::back() const
417 Returns a reference to the last element in the span.
419 The span must not be empty, otherwise the behavior is undefined.
421 \sa operator[](), front(), size(), empty()
425 \fn template <typename T, size_t E> auto QSpan<T, E>::data() const
427 Returns a pointer to the beginning of the span.
429 The same as calling begin().
439 \fn template <typename T, size_t E> auto QSpan<T, E>::begin() const
441 Returns an interator pointing at the beginning of the span.
443 Because QSpan iterators are just pointers, this is the same as calling
446 \sa end(), cbegin(), rbegin(), crbegin(), data()
450 \fn template <typename T, size_t E> auto QSpan<T, E>::end() const
452 Returns an iterator pointing to one past the end of the span.
454 Because QSpan iterators are just pointers, this it the same as calling
457 \sa begin(), cend(), rend(), crend(), data(), size()
461 \fn template <typename T, size_t E> auto QSpan<T, E>::cbegin() const
463 Returns a const_iterator pointing to the beginning of the span.
465 This will return a read-only iterator even if \c{T} is not \c{const}:
467 QSpan<int> span = ~~~;
468 *span.begin() = 42; // OK
469 *span.cbegin() = 42; // ERROR: cannot assign through a const_iterator
472 \sa cend(), begin(), crbegin(), rbegin(), data()
476 \fn template <typename T, size_t E> auto QSpan<T, E>::cend() const
478 Returns a const_iterator pointing to one past the end of the span.
480 \sa cbegin(), end(), crend(), rend(), data(), size()
484 \fn template <typename T, size_t E> auto QSpan<T, E>::rbegin() const
486 Returns a reverse_iterator pointing to the beginning of the reversed span.
488 \sa rend(), crbegin(), begin(), cbegin()
492 \fn template <typename T, size_t E> auto QSpan<T, E>::rend() const
494 Returns a reverse_iterator pointing to one past the end of the reversed span.
496 \sa rbegin(), crend(), end(), cend()
500 \fn template <typename T, size_t E> auto QSpan<T, E>::crbegin() const
502 Returns a const_reverse_iterator pointing to the beginning of the reversed span.
504 \sa crend(), rbegin(), cbegin(), begin()
508 \fn template <typename T, size_t E> auto QSpan<T, E>::crend() const
510 Returns a const_reverse_iterator pointing to one past the end of the reversed span.
512 \sa crbegin(), rend(), cend(), end()
516// compile-time subspans:
520 \fn template <typename T, size_t E> template <std::size_t Count> auto QSpan<T, E>::first() const
523 Returns a fixed-sized span of size \c{Count} referencing the first \c{Count} elements of \c{*this}.
525 The span must hold at least \c{Count} elements (\c{E} >= \c{Count} \e{and}
526 size() >= \c{Count}), otherwise the behavior is undefined.
528 \sa first(QSpan<T,E>::size_type), last(), subspan()
532 \fn template <typename T, size_t E> template <std::size_t Count> auto QSpan<T, E>::last() const
535 Returns a fixed-sized span of size \c{Count} referencing the last \c{Count} elements of \c{*this}.
537 The span must hold at least \c{Count} elements (\c{E} >= \c{Count} \e{and}
538 size() >= \c{Count}), otherwise the behavior is undefined.
540 \sa last(QSpan<T,E>::size_type), first(), subspan()
544 \fn template <typename T, size_t E> template <std::size_t Offset> auto QSpan<T, E>::subspan() const
547 Returns a span of size \c{E - Offset} referencing the remainder of this span
548 after dropping the first \c{Offset} elements.
550 If \c{*this} is a variable-sized span, the return type is a variable-sized
551 span, otherwise it is a fixed-sized span.
553 This span must hold at least \c{Offset} elements (\c{E} >= \c{Offset} \e{and}
554 size() >= \c{Offset}), otherwise the behavior is undefined.
556 \sa subspan(QSpan<T,E>::size_type), subspan(), first(), last()
559#if 0 // needs fix for QTBUG-118080 integrated into qt5.git
561 \fn template <typename T, size_t E> template <std::size_t Offset, std::size_t Count> auto QSpan<T, E>::subspan() const
564 Returns a span of size \c{Count} referencing the \c{Count} elements of this
565 span starting at \c{Offset}.
567 If \c{*this} is a variable-sized span, the return type is a variable-sized
568 span, otherwise it is a fixed-sized span.
570 This span must hold at least \c{Offset + Count} elements (\c{E} >=
571 \c{Offset + Count} \e{and} size() >= \c{Offset + Count}), otherwise the
572 behavior is undefined.
574 \sa subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type), subspan(), first(), last()
583 \fn template <typename T, size_t E> auto QSpan<T, E>::first(qsizetype n) const
586 Returns a variable-sized span of size \a n referencing the first \a n elements of \c{*this}.
588 \a n must be non-negative.
590 The span must hold at least \a n elements (\c{E} >= \a n \e{and} size() >=
591 \a n), otherwise the behavior is undefined.
593 \sa {first-t}{first<N>()}, last(QSpan<T,E>::size_type), subspan(QSpan<T,E>::size_type),
594 subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type)
599 \fn template <typename T, size_t E> auto QSpan<T, E>::last(qsizetype n) const
602 Returns a variable-sized span of size \a n referencing the last \a n elements of \c{*this}.
604 \a n must be non-negative.
606 The span must hold at least \a n elements (\c{E} >= \a n \e{and}
607 size() >= \a n), otherwise the behavior is undefined.
609 \sa last(), first(QSpan<T,E>::size_type), subspan(QSpan<T,E>::size_type),
610 subspan(QSpan<T,E>::size_type, QSpan<T,E>::size_type), sliced()
614 \fn template <typename T, size_t E> auto QSpan<T, E>::subspan(qsizetype pos) const
615 \fn template <typename T, size_t E> auto QSpan<T, E>::sliced(qsizetype pos) const
618 Returns a variable-sized span of size \c{size() - pos} referencing the
619 remainder of this span after dropping the first \a pos elements.
621 \a pos must be non-negative.
623 This span must hold at least \a pos elements (\c{E} >= \a pos \e{and}
624 size() >= \a pos), otherwise the behavior is undefined.
626 These functions do the same thing: subspan() is provided for STL
627 compatibility and sliced() is provided for Qt compatibility.
629 \sa subspan(), first(QSpan<T,E>::size_type), last(QSpan<T,E>::size_type)
633 \fn template <typename T, size_t E> auto QSpan<T, E>::subspan(qsizetype pos, qsizetype n) const
634 \fn template <typename T, size_t E> auto QSpan<T, E>::sliced(qsizetype pos, qsizetype n) const
637 Returns a variable-sized span of size \a n referencing the \a n elements of
638 this span starting at \a pos.
640 Both \a pos and \a n must be non-negative.
642 This span must hold at least \c{pos + n} elements (\c{E} >=
643 \c{pos + n} \e{and} size() >= \c{pos + n}), otherwise the
644 behavior is undefined.
646 These functions do the same thing: subspan() is provided for STL
647 compatibility and sliced() is provided for Qt compatibility.
649 \sa subspan(), first(QSpan<T,E>::size_type), last(QSpan<T,E>::size_type)