Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qspan.h
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QSPAN_H
5#define QSPAN_H
6
7#include <QtCore/qcompilerdetection.h>
8#include <QtCore/qtypes.h>
9#include <QtCore/qcontainerfwd.h>
10
11#include <array>
12#include <cstddef>
13#include <cassert>
14#include <initializer_list>
15#include <QtCore/q20iterator.h>
16#include <QtCore/q20memory.h>
17#ifdef __cpp_lib_span
18#include <span>
19#endif
20#include <QtCore/q20type_traits.h>
21
23
24// like std::dynamic_extent
25namespace q20 {
26 inline constexpr auto dynamic_extent = std::size_t(-1);
27} // namespace q20
28
30#ifdef __cpp_lib_span
31#ifdef __cpp_lib_concepts
32namespace std::ranges {
33// Officially, these are defined in <ranges>, but that is a heavy-hitter header.
34// OTOH, <span> must specialize these variable templates, too, so we assume that
35// <span> includes some meaningful subset of <ranges> and just go ahead and use them:
36template <typename T, std::size_t E>
37constexpr inline bool enable_borrowed_range<QT_PREPEND_NAMESPACE(QSpan)<T, E>> = true;
38template <typename T, std::size_t E>
39constexpr inline bool enable_view<QT_PREPEND_NAMESPACE(QSpan)<T, E>> = true;
40} // namespace std::ranges
41#endif // __cpp_lib_concepts
42#endif // __cpp_lib_span
44
45namespace QSpanPrivate {
46
47template <typename T, std::size_t E> class QSpanBase;
48
49template <typename T>
50struct is_qspan_helper : std::false_type {};
51template <typename T, std::size_t E>
52struct is_qspan_helper<QSpan<T, E>> : std::true_type {};
53template <typename T, std::size_t E>
54struct is_qspan_helper<QSpanBase<T, E>> : std::true_type {};
55template <typename T>
56using is_qspan = is_qspan_helper<q20::remove_cvref_t<T>>;
57
58template <typename T>
59struct is_std_span_helper : std::false_type {};
60#ifdef __cpp_lib_span
61template <typename T, std::size_t E>
62struct is_std_span_helper<std::span<T, E>> : std::true_type {};
63#endif // __cpp_lib_span
64template <typename T>
65using is_std_span = is_std_span_helper<q20::remove_cvref_t<T>>;
66
67template <typename T>
68struct is_std_array_helper : std::false_type {};
69template <typename T, std::size_t N>
70struct is_std_array_helper<std::array<T, N>> : std::true_type {};
71template <typename T>
72using is_std_array = is_std_array_helper<q20::remove_cvref_t<T>>;
73
74template <typename From, typename To>
76 std::is_convertible<From(*)[], To(*)[]>; // https://eel.is/c++draft/span.cons#note-1
77template <typename From, typename To>
79
80namespace AdlTester {
81#define MAKE_ADL_TEST(what) \
82 using std:: what; /* bring into scope */ \
83 template <typename T> using what ## _result = decltype( what (std::declval<T&&>())); \
84 /* end */
88#undef MAKE_ADL_TEST
89}
90
91// Replacements for std::ranges::XXX(), but only bringing in ADL XXX()s,
92// not doing the extra work C++20 requires
93template <typename Range>
94AdlTester::begin_result<Range> adl_begin(Range &&r) { using std::begin; return begin(r); }
95template <typename Range>
96AdlTester::data_result<Range> adl_data(Range &&r) { using std::data; return data(r); }
97template <typename Range>
98AdlTester::size_result<Range> adl_size(Range &&r) { using std::size; return size(r); }
99
100// Replacement for std::ranges::iterator_t (which depends on C++20 std::ranges::begin)
101// This one uses adl_begin() instead.
102template <typename Range>
103using iterator_t = decltype(QSpanPrivate::adl_begin(std::declval<Range&>()));
104template <typename Range>
106
107template <typename T>
109protected:
110 template <typename Iterator>
111 using is_compatible_iterator = std::conjunction<
112 // ### C++20: extend to contiguous_iteratorss
113 std::is_base_of<
114 std::random_access_iterator_tag,
115 typename std::iterator_traits<Iterator>::iterator_category
116 >,
118 std::remove_reference_t<q20::iter_reference_t<Iterator>>,
119 T
120 >
121 >;
122 template <typename Iterator, typename End>
123 using is_compatible_iterator_and_sentinel = std::conjunction<
124 // ### C++20: extend to contiguous_iterators and real sentinels
125 is_compatible_iterator<Iterator>,
126 std::negation<std::is_convertible<End, std::size_t>>
127 >;
128 template <typename Range, typename = void> // wrap use of SFINAE-unfriendly iterator_t:
129 struct is_compatible_range_helper : std::false_type {};
130 template <typename Range>
131 struct is_compatible_range_helper<Range, std::void_t<QSpanPrivate::iterator_t<Range>>>
132 : is_compatible_iterator<QSpanPrivate::iterator_t<Range>> {};
133 template <typename Range>
134 using is_compatible_range = std::conjunction<
135 // ### C++20: extend to contiguous_iterators
136 std::negation<is_qspan<Range>>,
137 std::negation<is_std_span<Range>>,
138 std::negation<is_std_array<Range>>,
139 std::negation<std::is_array<q20::remove_cvref_t<Range>>>,
140 is_compatible_range_helper<Range>
141 >;
142
143 // constraints
144 template <typename Iterator>
145 using if_compatible_iterator = std::enable_if_t<
147 , bool>;
148 template <typename Iterator, typename End>
149 using if_compatible_iterator_and_sentinel = std::enable_if_t<
151 , bool>;
152 template <typename Range>
153 using if_compatible_range = std::enable_if_t<is_compatible_range<Range>::value, bool>;
154}; // class QSpanCommon
155
156template <typename T, std::size_t E>
157class QSpanBase : protected QSpanCommon<T>
158{
159 static_assert(E < size_t{(std::numeric_limits<qsizetype>::max)()},
160 "QSpan only supports extents that fit into the signed size type (qsizetype).");
161
162 struct Enabled_t { explicit Enabled_t() = default; };
163 static inline constexpr Enabled_t Enable{};
164
165 template <typename S, std::size_t N>
166 using if_compatible_array = std::enable_if_t<
167 N == E && is_qualification_conversion_v<S, T>
168 , bool>;
169
170 template <typename S>
171 using if_qualification_conversion = std::enable_if_t<
172 is_qualification_conversion_v<S, T>
173 , bool>;
174protected:
175 using Base = QSpanCommon<T>;
176
177 // data members:
179 static constexpr qsizetype m_size = qsizetype(E);
180
181 // types and constants:
182 // (in QSpan only)
183
184 // constructors (need to be public d/t the way ctor inheriting works):
185public:
186 template <std::size_t E2 = E, std::enable_if_t<E2 == 0, bool> = true>
187 Q_IMPLICIT constexpr QSpanBase() noexcept : m_data{nullptr} {}
188
189 template <typename It, typename Base::template if_compatible_iterator<It> = true>
190 explicit constexpr QSpanBase(It first, qsizetype count)
191 : m_data{q20::to_address(first)}
192 {
194 }
195
196 template <typename It, typename End, typename Base::template if_compatible_iterator_and_sentinel<It, End> = true>
197 explicit constexpr QSpanBase(It first, End last)
198 : QSpanBase(first, last - first) {}
199
200 template <size_t N, std::enable_if_t<N == E, bool> = true>
201 Q_IMPLICIT constexpr QSpanBase(q20::type_identity_t<T> (&arr)[N]) noexcept
202 : QSpanBase(arr, N) {}
203
204 template <typename S, size_t N, if_compatible_array<S, N> = true>
205 Q_IMPLICIT constexpr QSpanBase(std::array<S, N> &arr) noexcept
206 : QSpanBase(arr.data(), N) {}
207
208 template <typename S, size_t N, if_compatible_array<S, N> = true>
209 Q_IMPLICIT constexpr QSpanBase(const std::array<S, N> &arr) noexcept
210 : QSpanBase(arr.data(), N) {}
211
212 template <typename Range, typename Base::template if_compatible_range<Range> = true>
213 Q_IMPLICIT constexpr QSpanBase(Range &&r)
214 : QSpanBase(QSpanPrivate::adl_data(r), // no forward<>() here (std doesn't have it, either)
215 qsizetype(QSpanPrivate::adl_size(r))) // ditto, no forward<>()
216 {}
217
218 template <typename S, if_qualification_conversion<S> = true>
219 Q_IMPLICIT constexpr QSpanBase(QSpan<S, E> other) noexcept
220 : QSpanBase(other.data(), other.size())
221 {}
222
223 template <typename S, if_qualification_conversion<S> = true>
224 Q_IMPLICIT constexpr QSpanBase(QSpan<S> other)
226 {}
227
228 template <typename U = T, std::enable_if_t<std::is_const_v<U>, bool> = true>
229 Q_IMPLICIT constexpr QSpanBase(std::initializer_list<std::remove_cv_t<T>> il)
230 : QSpanBase(il.begin(), il.size())
231 {}
232
233#ifdef __cpp_lib_span
234 template <typename S, if_qualification_conversion<S> = true>
235 Q_IMPLICIT constexpr QSpanBase(std::span<S, E> other) noexcept
236 : QSpanBase(other.data(), other.size())
237 {}
238
239 template <typename S, if_qualification_conversion<S> = true>
240 Q_IMPLICIT constexpr QSpanBase(std::span<S> other)
242 {}
243#endif // __cpp_lib_span
244}; // class QSpanBase (fixed extent)
245
246template <typename T>
247class QSpanBase<T, q20::dynamic_extent> : protected QSpanCommon<T>
248{
249 template <typename S>
250 using if_qualification_conversion = std::enable_if_t<
251 is_qualification_conversion_v<S, T>
252 , bool>;
253protected:
254 using Base = QSpanCommon<T>;
255
256 // data members:
259
260 // constructors (need to be public d/t the way ctor inheriting works):
261public:
262 Q_IMPLICIT constexpr QSpanBase() noexcept : m_data{nullptr}, m_size{0} {}
263
264 template <typename It, typename Base::template if_compatible_iterator<It> = true>
266 : m_data{q20::to_address(first)}, m_size{count} {}
267
268 template <typename It, typename End, typename Base::template if_compatible_iterator_and_sentinel<It, End> = true>
269 Q_IMPLICIT constexpr QSpanBase(It first, End last)
270 : QSpanBase(first, last - first) {}
271
272 template <size_t N>
273 Q_IMPLICIT constexpr QSpanBase(q20::type_identity_t<T> (&arr)[N]) noexcept
274 : QSpanBase(arr, N) {}
275
276 template <typename S, size_t N, if_qualification_conversion<S> = true>
277 Q_IMPLICIT constexpr QSpanBase(std::array<S, N> &arr) noexcept
278 : QSpanBase(arr.data(), N) {}
279
280 template <typename S, size_t N, if_qualification_conversion<S> = true>
281 Q_IMPLICIT constexpr QSpanBase(const std::array<S, N> &arr) noexcept
282 : QSpanBase(arr.data(), N) {}
283
284 template <typename Range, typename Base::template if_compatible_range<Range> = true>
285 Q_IMPLICIT constexpr QSpanBase(Range &&r)
286 : QSpanBase(QSpanPrivate::adl_data(r), // no forward<>() here (std doesn't have it, either)
287 qsizetype(QSpanPrivate::adl_size(r))) // ditto, no forward<>()
288 {}
289
290 template <typename S, size_t N, if_qualification_conversion<S> = true>
291 Q_IMPLICIT constexpr QSpanBase(QSpan<S, N> other) noexcept
292 : QSpanBase(other.data(), other.size())
293 {}
294
295 template <typename U = T, std::enable_if_t<std::is_const_v<U>, bool> = true>
296 Q_IMPLICIT constexpr QSpanBase(std::initializer_list<std::remove_cv_t<T>> il) noexcept
297 : QSpanBase(il.begin(), il.size())
298 {}
299
300#ifdef __cpp_lib_span
301 template <typename S, size_t N, if_qualification_conversion<S> = true>
302 Q_IMPLICIT constexpr QSpanBase(std::span<S, N> other) noexcept
303 : QSpanBase(other.data(), other.size())
304 {}
305#endif // __cpp_lib_span
306}; // class QSpanBase (dynamic extent)
307
308} // namespace QSpanPrivate
309
310template <typename T, std::size_t E>
311class QSpan
312#ifndef Q_QDOC
313 : private QSpanPrivate::QSpanBase<T, E>
314#endif
315{
317 Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
318 [[maybe_unused]] qsizetype n = 1) const
319 {
320 Q_ASSERT(pos >= 0);
321 Q_ASSERT(pos <= size());
322 Q_ASSERT(n >= 0);
323 Q_ASSERT(n <= size() - pos);
324 }
325
326 template <std::size_t N>
327 static constexpr bool subspan_always_succeeds_v = N <= E && E != q20::dynamic_extent;
328public:
329 // constants and types
330 using value_type = std::remove_cv_t<T>;
331#ifdef QT_COMPILER_HAS_LWG3346
332 using iterator_concept = std::contiguous_iterator_tag;
333 using element_type = T;
334#endif
335 using size_type = qsizetype; // difference to std::span
336 using difference_type = qptrdiff; // difference to std::span
337 using pointer = T*;
338 using const_pointer = const T*;
339 using reference = T&;
340 using const_reference = const T&;
341 using iterator = pointer; // implementation-defined choice
342 using const_iterator = const_pointer; // implementation-defined choice
343 using reverse_iterator = std::reverse_iterator<iterator>;
344 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
345 static constexpr std::size_t extent = E;
346
347 // [span.cons], constructors, copy, and assignment
348 using Base::Base;
349#ifdef Q_QDOC
350 template <typename It> using if_compatible_iterator = bool;
351 template <typename S> using if_qualification_conversion = bool;
352 template <typename Range> using if_compatible_range = bool;
353 template <typename It, if_compatible_iterator<It> = true> constexpr QSpan(It first, qsizetype count);
354 template <typename It, if_compatible_iterator<It> = true> constexpr QSpan(It first, It last);
355 template <size_t N> constexpr QSpan(q20::type_identity_t<T> (&arr)[N]) noexcept;
356 template <typename S, size_t N, if_qualification_conversion<S> = true> constexpr QSpan(std::array<S, N> &arr) noexcept;
357 template <typename S, size_t N, if_qualification_conversion<S> = true> constexpr QSpan(const std::array<S, N> &arr) noexcept;
358 template <typename Range, if_compatible_range<Range> = true> constexpr QSpan(Range &&r);
359 template <typename S, size_t N, if_qualification_conversion<S> = true> constexpr QSpan(QSpan<S, N> other) noexcept;
360 template <typename S, size_t N, if_qualification_conversion<S> = true> constexpr QSpan(std::span<S, N> other) noexcept;
361 constexpr QSpan(std::initializer_list<value_type> il);
362#endif // Q_QDOC
363
364 // [span.obs]
365 [[nodiscard]] constexpr size_type size() const noexcept { return this->m_size; }
366 [[nodiscard]] constexpr size_type size_bytes() const noexcept { return size() * sizeof(T); }
367 [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
368
369 // [span.elem]
370 [[nodiscard]] constexpr reference operator[](size_type idx) const
371 { verify(idx); return data()[idx]; }
372 [[nodiscard]] constexpr reference front() const { verify(); return *data(); }
373 [[nodiscard]] constexpr reference back() const { verify(); return data()[size() - 1]; }
374 [[nodiscard]] constexpr pointer data() const noexcept { return this->m_data; }
375
376 // [span.iterators]
377 [[nodiscard]] constexpr iterator begin() const noexcept { return data(); }
378 [[nodiscard]] constexpr iterator end() const noexcept { return data() + size(); }
379 [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); }
380 [[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
381 [[nodiscard]] constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
382 [[nodiscard]] constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
383 [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
384 [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); }
385
386 // [span.sub]
387 template <std::size_t Count>
388 [[nodiscard]] constexpr QSpan<T, Count> first() const
389 noexcept(subspan_always_succeeds_v<Count>)
390 {
391 static_assert(Count <= E,
392 "Count cannot be larger than the span's extent.");
393 verify(0, Count);
394 return QSpan<T, Count>{data(), Count};
395 }
396
397 template <std::size_t Count>
398 [[nodiscard]] constexpr QSpan<T, Count> last() const
399 noexcept(subspan_always_succeeds_v<Count>)
400 {
401 static_assert(Count <= E,
402 "Count cannot be larger than the span's extent.");
403 verify(0, Count);
404 return QSpan<T, Count>{data() + (size() - Count), Count};
405 }
406
407 template <std::size_t Offset>
408 [[nodiscard]] constexpr auto subspan() const
409 noexcept(subspan_always_succeeds_v<Offset>)
410 {
411 static_assert(Offset <= E,
412 "Offset cannot be larger than the span's extent.");
413 verify(Offset, 0);
414 if constexpr (E == q20::dynamic_extent)
415 return QSpan<T>{data() + Offset, qsizetype(size() - Offset)};
416 else
417 return QSpan<T, E - Offset>{data() + Offset, qsizetype(E - Offset)};
418 }
419
420 template <std::size_t Offset, std::size_t Count>
421 [[nodiscard]] constexpr auto subspan() const
422 noexcept(subspan_always_succeeds_v<Offset + Count>)
423 { return subspan<Offset>().template first<Count>(); }
424
425 [[nodiscard]] constexpr QSpan<T> first(size_type n) const { verify(0, n); return {data(), n}; }
426 [[nodiscard]] constexpr QSpan<T> last(size_type n) const { verify(0, n); return {data() + (size() - n), n}; }
427 [[nodiscard]] constexpr QSpan<T> subspan(size_type pos) const { verify(pos, 0); return {data() + pos, size() - pos}; }
428 [[nodiscard]] constexpr QSpan<T> subspan(size_type pos, size_type n) const { return subspan(pos).first(n); }
429
430 // Qt-compatibility API:
431 [[nodiscard]] bool isEmpty() const noexcept { return empty(); }
432 // nullary first()/last() clash with first<>() and last<>(), so they're not provided for QSpan
433 [[nodiscard]] constexpr QSpan<T> sliced(size_type pos) const { return subspan(pos); }
434 [[nodiscard]] constexpr QSpan<T> sliced(size_type pos, size_type n) const { return subspan(pos, n); }
435
436}; // class QSpan
437
438// [span.deduct]
439template <class It, class EndOrSize>
440QSpan(It, EndOrSize) -> QSpan<std::remove_reference_t<q20::iter_reference_t<It>>>;
441template <class T, std::size_t N>
442QSpan(T (&)[N]) -> QSpan<T, N>;
443template <class T, std::size_t N>
444QSpan(std::array<T, N> &) -> QSpan<T, N>;
445template <class T, std::size_t N>
446QSpan(const std::array<T, N> &) -> QSpan<const T, N>;
447template <class R>
448QSpan(R&&) -> QSpan<std::remove_reference_t<QSpanPrivate::range_reference_t<R>>>;
449
451
452#endif // QSPAN_H
Q_IMPLICIT constexpr QSpanBase(std::array< S, N > &arr) noexcept
Definition qspan.h:277
Q_IMPLICIT constexpr QSpanBase(QSpan< S, N > other) noexcept
Definition qspan.h:291
Q_IMPLICIT constexpr QSpanBase(It first, qsizetype count)
Definition qspan.h:265
Q_IMPLICIT constexpr QSpanBase(q20::type_identity_t< T >(&arr)[N]) noexcept
Definition qspan.h:273
Q_IMPLICIT constexpr QSpanBase(It first, End last)
Definition qspan.h:269
Q_IMPLICIT constexpr QSpanBase(Range &&r)
Definition qspan.h:285
Q_IMPLICIT constexpr QSpanBase(std::initializer_list< std::remove_cv_t< T > > il) noexcept
Definition qspan.h:296
Q_IMPLICIT constexpr QSpanBase() noexcept
Definition qspan.h:262
Q_IMPLICIT constexpr QSpanBase(const std::array< S, N > &arr) noexcept
Definition qspan.h:281
Q_IMPLICIT constexpr QSpanBase(std::array< S, N > &arr) noexcept
Definition qspan.h:205
constexpr QSpanBase(It first, qsizetype count)
Definition qspan.h:190
Q_IMPLICIT constexpr QSpanBase(QSpan< S, E > other) noexcept
Definition qspan.h:219
Q_IMPLICIT constexpr QSpanBase(Range &&r)
Definition qspan.h:213
Q_IMPLICIT constexpr QSpanBase(q20::type_identity_t< T >(&arr)[N]) noexcept
Definition qspan.h:201
Q_IMPLICIT constexpr QSpanBase(std::initializer_list< std::remove_cv_t< T > > il)
Definition qspan.h:229
Q_IMPLICIT constexpr QSpanBase(const std::array< S, N > &arr) noexcept
Definition qspan.h:209
Q_IMPLICIT constexpr QSpanBase() noexcept
Definition qspan.h:187
Q_IMPLICIT constexpr QSpanBase(QSpan< S > other)
Definition qspan.h:224
static constexpr qsizetype m_size
Definition qspan.h:179
constexpr QSpanBase(It first, End last)
Definition qspan.h:197
std::conjunction< is_compatible_iterator< Iterator >, std::negation< std::is_convertible< End, std::size_t > > > is_compatible_iterator_and_sentinel
Definition qspan.h:123
std::enable_if_t< is_compatible_iterator_and_sentinel< Iterator, End >::value, bool > if_compatible_iterator_and_sentinel
Definition qspan.h:149
std::enable_if_t< is_compatible_iterator< Iterator >::value, bool > if_compatible_iterator
Definition qspan.h:145
std::enable_if_t< is_compatible_range< Range >::value, bool > if_compatible_range
Definition qspan.h:153
std::conjunction< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< Iterator >::iterator_category >, is_qualification_conversion< std::remove_reference_t< q20::iter_reference_t< Iterator > >, T > > is_compatible_iterator
Definition qspan.h:111
std::conjunction< std::negation< is_qspan< Range > >, std::negation< is_std_span< Range > >, std::negation< is_std_array< Range > >, std::negation< std::is_array< q20::remove_cvref_t< Range > > >, is_compatible_range_helper< Range > > is_compatible_range
Definition qspan.h:134
Definition qspan.h:315
constexpr bool empty() const noexcept
Definition qspan.h:367
constexpr pointer data() const noexcept
Definition qspan.h:374
static constexpr std::size_t extent
Definition qspan.h:345
constexpr reverse_iterator rbegin() const noexcept
Definition qspan.h:381
constexpr reference front() const
Definition qspan.h:372
constexpr QSpan< T > sliced(size_type pos, size_type n) const
Definition qspan.h:434
constexpr QSpan< T > sliced(size_type pos) const
Definition qspan.h:433
const T * const_pointer
Definition qspan.h:338
constexpr size_type size() const noexcept
Definition qspan.h:365
const_pointer const_iterator
Definition qspan.h:342
T & reference
Definition qspan.h:339
qsizetype size_type
Definition qspan.h:335
constexpr iterator end() const noexcept
Definition qspan.h:378
constexpr const_iterator cbegin() const noexcept
Definition qspan.h:379
constexpr QSpan< T > subspan(size_type pos, size_type n) const
Definition qspan.h:428
constexpr const_iterator cend() const noexcept
Definition qspan.h:380
constexpr reverse_iterator rend() const noexcept
Definition qspan.h:382
constexpr QSpan< T, Count > last() const noexcept(subspan_always_succeeds_v< Count >)
Definition qspan.h:398
std::remove_cv_t< T > value_type
Definition qspan.h:330
T * pointer
Definition qspan.h:337
constexpr QSpan< T > last(size_type n) const
Definition qspan.h:426
constexpr const_reverse_iterator crend() const noexcept
Definition qspan.h:384
pointer iterator
Definition qspan.h:341
constexpr size_type size_bytes() const noexcept
Definition qspan.h:366
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition qspan.h:344
constexpr const_reverse_iterator crbegin() const noexcept
Definition qspan.h:383
constexpr reference operator[](size_type idx) const
Definition qspan.h:370
constexpr QSpan< T > first(size_type n) const
Definition qspan.h:425
constexpr reference back() const
Definition qspan.h:373
constexpr QSpan< T > subspan(size_type pos) const
Definition qspan.h:427
constexpr auto subspan() const noexcept(subspan_always_succeeds_v< Offset+Count >)
Definition qspan.h:421
constexpr QSpan< T, Count > first() const noexcept(subspan_always_succeeds_v< Count >)
Definition qspan.h:388
const T & const_reference
Definition qspan.h:340
qptrdiff difference_type
Definition qspan.h:336
std::reverse_iterator< iterator > reverse_iterator
Definition qspan.h:343
constexpr iterator begin() const noexcept
Definition qspan.h:377
constexpr auto subspan() const noexcept(subspan_always_succeeds_v< Offset >)
Definition qspan.h:408
bool isEmpty() const noexcept
Definition qspan.h:431
AdlTester::size_result< Range > adl_size(Range &&r)
Definition qspan.h:98
is_qspan_helper< q20::remove_cvref_t< T > > is_qspan
Definition qspan.h:56
decltype(QSpanPrivate::adl_begin(std::declval< Range & >())) iterator_t
Definition qspan.h:103
AdlTester::data_result< Range > adl_data(Range &&r)
Definition qspan.h:96
is_std_array_helper< q20::remove_cvref_t< T > > is_std_array
Definition qspan.h:72
std::is_convertible< From(*)[], To(*)[]> is_qualification_conversion
Definition qspan.h:75
q20::iter_reference_t< QSpanPrivate::iterator_t< Range > > range_reference_t
Definition qspan.h:105
AdlTester::begin_result< Range > adl_begin(Range &&r)
Definition qspan.h:94
constexpr bool is_qualification_conversion_v
Definition qspan.h:78
is_std_span_helper< q20::remove_cvref_t< T > > is_std_span
Definition qspan.h:65
Combined button and popup list for selecting options.
typename type_identity< T >::type type_identity_t
constexpr auto dynamic_extent
Definition qspan.h:26
decltype(*std::declval< Dereferencable & >()) iter_reference_t
Definition q20iterator.h:48
#define Q_IMPLICIT
#define Q_ALWAYS_INLINE
quint16 Offset
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint first
GLfloat n
GLenum array
GLenum GLenum GLsizei void GLsizei void void * span
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QSpan(It, EndOrSize) -> QSpan< std::remove_reference_t< q20::iter_reference_t< It > > >
#define MAKE_ADL_TEST(what)
Definition qspan.h:81
#define QT_BEGIN_INCLUDE_NAMESPACE
#define QT_END_INCLUDE_NAMESPACE
ptrdiff_t qptrdiff
Definition qtypes.h:164
ptrdiff_t qsizetype
Definition qtypes.h:165
QSharedPointer< T > other(t)
[5]