1// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef Q20ALGORITHM_H
4#define Q20ALGORITHM_H
5
6#include <QtCore/qglobal.h>
7
8#include <algorithm>
9#include <QtCore/q20functional.h>
10
11//
12// W A R N I N G
13// -------------
14//
15// This file is not part of the Qt API. Types and functions defined in this
16// file can reliably be replaced by their std counterparts, once available.
17// You may use these definitions in your own code, but be aware that we
18// will remove them once Qt depends on the C++ version that supports
19// them in namespace std. There will be NO deprecation warning, the
20// definitions will JUST go away.
21//
22// If you can't agree to these terms, don't use these definitions!
23//
24// We mean it.
25//
26
27QT_BEGIN_NAMESPACE
28
29namespace q20 {
30// like std::<algorithm> (ie. not ranged, but constexpr)
31#ifdef __cpp_lib_constexpr_algorithms
32using std::copy;
33using std::copy_if;
34using std::copy_n;
35using std::fill;
36using std::fill_n;
37using std::is_sorted_until;
38using std::is_sorted;
39using std::transform;
40#else
41template <typename InputIterator, typename OutputIterator>
42constexpr OutputIterator
43copy(InputIterator first, InputIterator last, OutputIterator dest)
44{
45 while (first != last) {
46 *dest = *first;
47 ++first;
48 ++dest;
49 }
50 return dest;
51}
52
53template <typename InputIterator, typename OutputIterator, typename UnaryPredicate>
54constexpr OutputIterator
55copy_if(InputIterator first, InputIterator last, OutputIterator dest, UnaryPredicate pred)
56{
57 while (first != last) {
58 if (pred(*first)) {
59 *dest = *first;
60 ++dest;
61 }
62 ++first;
63 }
64 return dest;
65}
66
67template <typename InputIterator, typename Size, typename OutputIterator>
68constexpr OutputIterator
69copy_n(InputIterator first, Size n, OutputIterator dest)
70{
71 while (n > Size{0}) {
72 *dest = *first;
73 ++first;
74 ++dest;
75 --n;
76 }
77 return dest;
78}
79
80template <typename ForwardIterator, typename Value>
81constexpr void
82fill(ForwardIterator first, ForwardIterator last, const Value &value)
83{
84 while (first != last) {
85 *first = value;
86 ++first;
87 }
88}
89
90template <typename OutputIterator, typename Size, typename Value>
91constexpr OutputIterator
92fill_n(OutputIterator first, Size n, const Value &value)
93{
94 while (n > Size{0}) {
95 *first = value;
96 ++first;
97 --n;
98 }
99 return first;
100}
101
102template <typename ForwardIterator, typename BinaryPredicate = std::less<>>
103constexpr ForwardIterator
104is_sorted_until(ForwardIterator first, ForwardIterator last, BinaryPredicate p = {})
105{
106 if (first == last)
107 return first;
108 auto prev = first;
109 while (++first != last) {
110 if (p(*first, *prev))
111 return first;
112 prev = first;
113 }
114 return first;
115}
116
117template <typename ForwardIterator, typename BinaryPredicate = std::less<>>
118constexpr bool is_sorted(ForwardIterator first, ForwardIterator last, BinaryPredicate p = {})
119{
120 return q20::is_sorted_until(first, last, p) == last;
121}
122
123template <typename InputIterator, typename OutputIterator, typename UnaryFunction>
124constexpr OutputIterator
125transform(InputIterator first, InputIterator last, OutputIterator dest, UnaryFunction op)
126{
127 while (first != last) {
128 *dest = op(*first);
129 ++first;
130 ++dest;
131 }
132 return dest;
133}
134
135// binary transform missing on purpose (no users)
136
137#endif
138}
139
140namespace q20::ranges {
141// like std::ranges::{any,all,none}_of, just unconstrained, so no range-overload
142#ifdef __cpp_lib_ranges
143using std::ranges::any_of;
144using std::ranges::all_of;
145using std::ranges::none_of;
146#else
147[[maybe_unused]] inline constexpr struct { // Niebloid
148 template <typename InputIterator, typename Sentinel,
149 typename Predicate, typename Projection = q20::identity>
150 constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
151 {
152 while (first != last) {
153 if (std::invoke(pred, std::invoke(proj, *first)))
154 return true;
155 ++first;
156 }
157 return false;
158 }
159} any_of;
160[[maybe_unused]] inline constexpr struct { // Niebloid
161 template <typename InputIterator, typename Sentinel,
162 typename Predicate, typename Projection = q20::identity>
163 constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
164 {
165 while (first != last) {
166 if (!std::invoke(pred, std::invoke(proj, *first)))
167 return false;
168 ++first;
169 }
170 return true;
171 }
172} all_of;
173[[maybe_unused]] inline constexpr struct { // Niebloid
174 template <typename InputIterator, typename Sentinel,
175 typename Predicate, typename Projection = q20::identity>
176 constexpr bool operator()(InputIterator first, Sentinel last, Predicate pred, Projection proj = {}) const
177 {
178 while (first != last) {
179 if (std::invoke(pred, std::invoke(proj, *first)))
180 return false;
181 ++first;
182 }
183 return true;
184 }
185} none_of;
186#endif // __cpp_lib_ranges
187} // namespace q20::ranges
188
189QT_END_NAMESPACE
190
191#endif /* Q20ALGORITHM_H */
192

source code of qtbase/src/corelib/global/q20algorithm.h