Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmultimedia_ranges_p.h
Go to the documentation of this file.
1// Copyright (C) 2025 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 QMULTIMEDIA_RANGES_P_H
5#define QMULTIMEDIA_RANGES_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/qtconfigmacros.h>
19
20#include <QtMultimedia/private/qiteratorfacade_p.h>
21
22#ifdef __cpp_lib_ranges
23# include <ranges> // IWYU pragma: export
24#endif
25
26#include <algorithm>
27#include <functional>
28#include <type_traits>
29#include <utility>
30
31QT_BEGIN_NAMESPACE
32
34
35#ifdef __cpp_lib_ranges
36
38
39using std::ranges::all_of;
40using std::ranges::any_of;
41using std::ranges::copy;
42using std::ranges::equal;
43using std::ranges::equal_range;
44using std::ranges::fill;
45using std::ranges::find;
46using std::ranges::find_if;
47using std::ranges::for_each;
48using std::ranges::lower_bound;
49using std::ranges::max;
50using std::ranges::max_element;
51using std::ranges::min;
52using std::ranges::min_element;
53using std::ranges::none_of;
54using std::ranges::sort;
55using std::ranges::stable_sort;
56using std::ranges::transform;
57using std::ranges::upper_bound;
58
59#else
60
61template <typename R>
62using range_iterator_t = decltype(std::begin(std::declval<R &>()));
63
64template <typename It>
65using iter_value_t = typename std::iterator_traits<It>::value_type;
66
67template <typename R>
69
70// Caveat: best effort, not a 1-to-1 mapping to c++20 style ranges
71
72inline constexpr auto all_of = [](auto &&range, auto predicate) {
73 return std::all_of(std::begin(range), std::end(range), std::move(predicate));
74};
75
76inline constexpr auto any_of = [](auto &&range, auto predicate) {
77 return std::any_of(std::begin(range), std::end(range), std::move(predicate));
78};
79
80inline constexpr auto none_of = [](auto &&range, auto predicate) {
81 return std::none_of(std::begin(range), std::end(range), std::move(predicate));
82};
83
84inline constexpr auto for_each = [](auto &&range, auto func) {
85 return std::for_each(std::begin(range), std::end(range), std::move(func));
86};
87
88inline constexpr auto copy = [](auto &&in, auto out) {
89 return std::copy(std::begin(in), std::end(in), std::move(out));
90};
91
92inline constexpr auto fill = [](auto &&range, const auto &value) {
93 return std::fill(std::begin(range), std::end(range), value);
94};
95
96inline constexpr auto find = [](auto &&range, const auto &value) {
97 return std::find(std::begin(range), std::end(range), value);
98};
99
100inline constexpr auto find_if = [](auto &&range, auto predicate) {
101 return std::find_if(std::begin(range), std::end(range), std::move(predicate));
102};
103
104template <typename Iterator>
106{
107 Iterator m_begin;
108 Iterator m_end;
109 constexpr Iterator begin() const { return m_begin; }
110 constexpr Iterator end() const { return m_end; }
111};
112
113namespace impl {
114
116{
117 template <typename Range, typename T, typename Comp = std::less<>>
118 auto operator()(Range &&range, const T &value, Comp comp = {}) const
119 {
120 return std::lower_bound(std::begin(range), std::end(range), value, std::move(comp));
121 }
122};
123
125{
126 template <typename Range, typename T, typename Comp = std::less<>>
127 auto operator()(Range &&range, const T &value, Comp comp = {}) const
128 {
129 return std::upper_bound(std::begin(range), std::end(range), value, std::move(comp));
130 }
131};
132
134{
135 template <typename Range, typename T, typename Comp = std::less<>>
136 auto operator()(Range &&range, const T &value, Comp comp = {}) const
137 {
138 auto [b, e] = std::equal_range(std::begin(range), std::end(range), value, std::move(comp));
139 return subrange<decltype(b)>{ b, e };
140 }
141};
142
143struct max_fn
144{
145 template <typename Range, typename Comp = std::less<>>
146 auto operator()(Range &&range, Comp comp) const
147 {
148 auto it = std::max_element(std::begin(range), std::end(range), std::move(comp));
149 return *it;
150 }
151
152 template <typename Range>
153 auto operator()(Range &&range) const
154 {
155 auto it = std::max_element(std::begin(range), std::end(range));
156 return *it;
157 }
158};
159
161{
162 template <typename Range, typename Comp = std::less<>>
163 auto operator()(Range &&range, Comp comp) const
164 {
165 return std::max_element(std::begin(range), std::end(range), std::move(comp));
166 }
167
168 template <typename Range>
169 auto operator()(Range &&range) const
170 {
171 return std::max_element(std::begin(range), std::end(range));
172 }
173};
174
175struct min_fn
176{
177 template <typename Range, typename Comp = std::less<>>
178 auto operator()(Range &&range, Comp comp) const
179 {
180 auto it = std::min_element(std::begin(range), std::end(range), std::move(comp));
181 return *it;
182 }
183
184 template <typename Range>
185 auto operator()(Range &&range) const
186 {
187 auto it = std::min_element(std::begin(range), std::end(range));
188 return *it;
189 }
190};
191
193{
194 template <typename Range, typename Comp = std::less<>>
195 auto operator()(Range &&range, Comp comp) const
196 {
197 return std::min_element(std::begin(range), std::end(range), std::move(comp));
198 }
199
200 template <typename Range>
201 auto operator()(Range &&range) const
202 {
203 return std::min_element(std::begin(range), std::end(range));
204 }
205};
206
208{
209 template <typename Range, typename Comp = std::less<>>
210 void operator()(Range &&range, Comp comp) const
211 {
212 std::sort(std::begin(range), std::end(range), std::move(comp));
213 }
214
215 template <typename Range>
216 void operator()(Range &&range) const
217 {
218 std::sort(std::begin(range), std::end(range));
219 }
220};
221
223{
224 template <typename Range, typename Comp = std::less<>>
225 void operator()(Range &&range, Comp comp) const
226 {
227 std::stable_sort(std::begin(range), std::end(range), std::move(comp));
228 }
229
230 template <typename Range>
231 void operator()(Range &&range) const
232 {
233 std::stable_sort(std::begin(range), std::end(range));
234 }
235};
236
238{
239 template <typename Range1, typename Range2, typename Pred = std::equal_to<>>
240 bool operator()(Range1 &&lhs, Range2 &&rhs, Pred pred = {}) const
241 {
242 return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs), std::end(rhs),
243 std::move(pred));
244 }
245};
246
247} // namespace impl
248
249inline constexpr auto equal = impl::equal_fn{};
250inline constexpr auto lower_bound = impl::lower_bound_fn{};
251inline constexpr auto upper_bound = impl::upper_bound_fn{};
252inline constexpr auto equal_range = impl::equal_range_fn{};
253inline constexpr auto sort = impl::sort_fn{};
254inline constexpr auto stable_sort = impl::stable_sort_fn{};
255inline constexpr auto max = impl::max_fn{};
256inline constexpr auto max_element = impl::max_element_fn{};
257inline constexpr auto min = impl::min_fn{};
258inline constexpr auto min_element = impl::min_element_fn{};
259inline constexpr auto transform = [](auto &&range, auto output, auto op) {
260 return std::transform(std::begin(range), std::end(range), std::move(output),
261 [op = std::move(op)](const auto &x) {
262 return std::invoke(op, x);
263 });
264};
265
266#endif
267
268#if __cpp_lib_ranges_contains >= 202207L
269using std::ranges::contains;
270#else
271
272inline constexpr auto contains = [](auto &&range, const auto &value) {
273 return std::find(std::begin(range), std::end(range), value) != std::end(range);
274};
275
276#endif
277
278#if __cpp_lib_ranges_to_container >= 202202L
279using std::ranges::to;
280#else
281
282namespace impl {
283
284template <typename Container>
286{
287};
288
289template <typename Container, typename Range>
290Container operator|(Range &&range, to_adaptor<Container>)
291{
292 return Container(std::begin(range), std::end(range));
293}
294
295template <template <class...> class Container>
299
300template <template <class...> class Container, class Range>
302{
303 return Container<ranges::range_value_t<Range>>(std::begin(range), std::end(range));
304}
305
306} // namespace impl
307
308template <typename Container, typename Range>
309Container to(Range &&range)
310{
311 return Container(std::begin(range), std::end(range));
312}
313
314template <typename Container>
315impl::to_adaptor<Container> to()
316{
317 return {};
318}
319
320template <template <class...> class Container>
321auto to()
322{
323 return impl::to_adaptor_template_template<Container>{};
324}
325#endif
326
327} // namespace QtMultimediaPrivate::ranges
328
330
331#ifdef __cpp_lib_ranges
332using std::views::filter;
333using std::views::keys;
334using std::views::transform;
335using std::views::values;
336#else
337
338namespace impl {
339
340template <typename Range>
342{
343 using BaseIt = decltype(std::begin(std::declval<Range &>()));
344 using KeyReference = decltype((*std::declval<BaseIt>()).first);
346
347 class iterator
348 : public IteratorFacade<iterator, KeyValue, std::input_iterator_tag, KeyReference>
349 {
350 BaseIt m_it;
351
352 public:
353 constexpr explicit iterator(BaseIt it) : m_it(std::move(it)) { }
354
355 using reference = KeyReference;
356 constexpr reference dereference() const { return (*m_it).first; }
357 constexpr void increment() { ++m_it; }
358 constexpr bool equals(const iterator &o) const { return m_it == o.m_it; }
359 };
360
361 Range &m_range;
362
363public:
364 constexpr explicit KeysView(Range &range) : m_range(range) { }
365 constexpr iterator begin() const { return iterator{ std::begin(m_range) }; }
366 constexpr iterator end() const { return iterator{ std::end(m_range) }; }
367};
368
369template <typename Range>
371{
372 using BaseIt = decltype(std::begin(std::declval<Range &>()));
373 using ValueReference = decltype((*std::declval<BaseIt>()).second);
375
376 class iterator
377 : public IteratorFacade<iterator, MappedValue, std::input_iterator_tag, ValueReference>
378 {
379 BaseIt m_it;
380
381 public:
382 constexpr explicit iterator(BaseIt it) : m_it(std::move(it)) { }
383
384 using reference = ValueReference;
385 constexpr reference dereference() const { return (*m_it).second; }
386 constexpr void increment() { ++m_it; }
387 constexpr bool equals(const iterator &o) const { return m_it == o.m_it; }
388 };
389
390 Range &m_range;
391
392public:
393 constexpr explicit ValuesView(Range &range) : m_range(range) { }
394 constexpr iterator begin() const { return iterator{ std::begin(m_range) }; }
395 constexpr iterator end() const { return iterator{ std::end(m_range) }; }
396};
397
398struct keys_tag { };
399struct values_tag { };
400
401template <typename Range>
402constexpr KeysView<const Range> operator|(const Range &range, keys_tag) { return KeysView<const Range>{ range }; }
403
404template <typename Range>
405constexpr ValuesView<const Range> operator|(const Range &range, values_tag) { return ValuesView<const Range>{ range }; }
406
407template <typename Container, typename Predicate>
409{
410 using BaseIt = decltype(std::begin(std::declval<Container &>()));
411 using ElementReference = decltype(*std::declval<BaseIt>());
413
414 class iterator
415 : public IteratorFacade<iterator, ElementValue, std::input_iterator_tag, ElementReference>
416 {
417 BaseIt m_it;
418 BaseIt m_end;
419 Predicate m_pred;
420
421 constexpr void advance()
422 {
423 while (m_it != m_end && !m_pred(*m_it))
424 ++m_it;
425 }
426
427 public:
428 using reference = ElementReference;
429
430 constexpr iterator(BaseIt it, BaseIt end, Predicate pred)
431 : m_it(std::move(it)), m_end(std::move(end)), m_pred(std::move(pred))
432 {
433 advance();
434 }
435
436 constexpr reference dereference() const { return *m_it; }
437 constexpr void increment()
438 {
439 ++m_it;
440 advance();
441 }
442 constexpr bool equals(const iterator &o) const { return m_it == o.m_it; };
443 };
444
445 Container &m_container;
446 Predicate m_pred;
447
448public:
449 constexpr FilterView(Container &container, Predicate pred)
450 : m_container(container), m_pred(std::move(pred))
451 {
452 }
453
454 constexpr iterator begin() const
455 {
456 return iterator{
457 std::begin(m_container),
458 std::end(m_container),
459 m_pred,
460 };
461 }
462
463 constexpr iterator end() const
464 {
465 return iterator{
466 std::end(m_container),
467 std::end(m_container),
468 m_pred,
469 };
470 }
471};
472
473template <typename Predicate>
475{
476 Predicate pred;
477};
478
479// operator| is in impl so ADL finds it via the FilterAdaptor type
480// Takes const Container& to allow binding both lvalues and rvalues (chained FilterViews).
481// The resulting FilterView stores a const ref, valid for the lifetime of the full expression.
482template <typename Container, typename Predicate>
483constexpr auto operator|(const Container &container, FilterAdaptor<Predicate> adaptor)
484{
485 return FilterView<const Container, Predicate>(container, std::move(adaptor.pred));
486}
487
488template <typename Range, typename Transform>
490{
491 using BaseIt = decltype(std::begin(std::declval<Range &>()));
493 decltype(std::invoke(std::declval<Transform>(), *std::declval<BaseIt>()))>>;
494
495 class iterator : public IteratorFacade<iterator, TransformedValue, std::input_iterator_tag,
496 TransformedValue>
497 {
498 BaseIt m_it;
499 Transform m_transform;
500
501 public:
502 using reference = TransformedValue;
503
504 constexpr iterator(BaseIt it, Transform transform)
505 : m_it(std::move(it)), m_transform(std::move(transform))
506 {
507 }
508
509 constexpr reference dereference() const { return std::invoke(m_transform, *m_it); }
510 constexpr void increment() { ++m_it; }
511 constexpr void decrement() { --m_it; }
512 constexpr bool equals(const iterator &o) const { return m_it == o.m_it; }
513 };
514
515 Range &m_range;
516 Transform m_transform;
517
518public:
519 constexpr TransformView(Range &range, Transform transform)
520 : m_range(range), m_transform(std::move(transform))
521 {
522 }
523
524 constexpr iterator begin() const { return iterator{ std::begin(m_range), m_transform }; }
525 constexpr iterator end() const { return iterator{ std::end(m_range), m_transform }; }
526};
527
528template <typename Transform>
530{
531 Transform transform;
532};
533
534template <typename Container, typename Transform>
535constexpr auto operator|(const Container &container, TransformAdaptor<Transform> adaptor)
536{
537 return TransformView<const Container, Transform>(container, std::move(adaptor.transform));
538}
539
540} // namespace impl
541
542template <typename Container, typename Predicate>
543constexpr auto filter(const Container &container, Predicate pred)
544{
545 return impl::FilterView<const Container, Predicate>(container, std::move(pred));
546}
547
548template <typename Predicate>
549constexpr auto filter(Predicate pred)
550{
551 return impl::FilterAdaptor<Predicate>{ std::move(pred) };
552}
553
554template <typename Container, typename Transform>
555constexpr auto transform(const Container &container, Transform t)
556{
557 return impl::TransformView<const Container, Transform>(container, std::move(t));
558}
559
560template <typename Transform>
561constexpr auto transform(Transform t)
562{
563 return impl::TransformAdaptor<Transform>{ std::move(t) };
564}
565
566inline constexpr impl::keys_tag keys{};
567inline constexpr impl::values_tag values{};
568
569#endif
570
571} // namespace QtMultimediaPrivate::views
572
573QT_END_NAMESPACE
574
575#endif // QMULTIMEDIA_RANGES_P_H
constexpr FilterView(Container &container, Predicate pred)
constexpr TransformView(Range &range, Transform transform)
Container operator|(Range &&range, to_adaptor< Container >)
auto operator|(Range &&range, to_adaptor_template_template< Container >)
typename std::iterator_traits< It >::value_type iter_value_t
impl::to_adaptor< Container > to()
decltype(std::begin(std::declval< R & >())) range_iterator_t
Container to(Range &&range)
constexpr KeysView< const Range > operator|(const Range &range, keys_tag)
constexpr auto operator|(const Container &container, TransformAdaptor< Transform > adaptor)
constexpr ValuesView< const Range > operator|(const Range &range, values_tag)
constexpr auto operator|(const Container &container, FilterAdaptor< Predicate > adaptor)
constexpr impl::values_tag values
constexpr impl::keys_tag keys
constexpr auto filter(Predicate pred)
constexpr auto transform(Transform t)
constexpr auto filter(const Container &container, Predicate pred)
constexpr auto transform(const Container &container, Transform t)
bool operator()(Range1 &&lhs, Range2 &&rhs, Pred pred={}) const
auto operator()(Range &&range, const T &value, Comp comp={}) const
auto operator()(Range &&range, const T &value, Comp comp={}) const
auto operator()(Range &&range, Comp comp) const
auto operator()(Range &&range, Comp comp) const
auto operator()(Range &&range, Comp comp) const
auto operator()(Range &&range, Comp comp) const
void operator()(Range &&range, Comp comp) const
void operator()(Range &&range, Comp comp) const
auto operator()(Range &&range, const T &value, Comp comp={}) const