2 // Copyright 2013 Francisco Jerez
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
23 #ifndef CLOVER_UTIL_ALGORITHM_HPP
24 #define CLOVER_UTIL_ALGORITHM_HPP
29 #include "util/range.hpp"
30 #include "util/functional.hpp"
35 using preferred_reference_type = decltype(*std::declval<R>().begin());
39 /// Return the first element in a range.
42 detail::preferred_reference_type<R>
49 /// Return all elements in a range but the first.
55 return { std::forward<R>(r), 1, r.size() };
59 /// Return the only element in a range.
62 detail::preferred_reference_type<R>
65 throw std::out_of_range("");
71 /// Combine a variable number of ranges element-wise in a single
74 template<typename... Rs>
75 adaptor_range<zips, Rs...>
77 return map(zips(), std::forward<Rs>(rs)...);
81 /// Evaluate the elements of a range.
83 /// Useful because most of the range algorithms evaluate their
89 for (auto i = r.begin(), e = r.end(); i != e; ++i)
94 /// Apply functor \a f element-wise on a variable number of ranges
97 /// The functor \a f should take as many arguments as ranges are
100 template<typename F, typename... Rs>
102 for_each(F &&f, Rs &&... rs) {
103 eval(map(std::forward<F>(f), std::forward<Rs>(rs)...));
107 /// Copy all elements from range \a r into an output container
108 /// starting from iterator \a i.
110 template<typename R, typename I>
113 for (detail::preferred_reference_type<R> x : r)
118 /// Reduce the elements of range \a r by applying functor \a f
119 /// element by element.
121 /// \a f should take an accumulator value (which is initialized to
122 /// \a a) and an element value as arguments, and return an updated
123 /// accumulator value.
125 /// \returns The final value of the accumulator.
127 template<typename F, typename A, typename R>
129 fold(F &&f, A a, R &&r) {
130 for (detail::preferred_reference_type<R> x : r)
137 /// Return how many elements of range \a r are equal to \a x.
139 template<typename T, typename R>
140 typename std::remove_reference<R>::type::size_type
141 count(T &&x, R &&r) {
142 typename std::remove_reference<R>::type::size_type n = 0;
144 for (detail::preferred_reference_type<R> y : r) {
153 /// Return the first element in range \a r for which predicate \a f
154 /// evaluates to true.
156 template<typename F, typename R>
157 detail::preferred_reference_type<R>
159 for (detail::preferred_reference_type<R> x : r) {
164 throw std::out_of_range("");
168 /// Return true if the element-wise application of predicate \a f
169 /// on \a rs evaluates to true for all elements.
171 template<typename F, typename... Rs>
173 all_of(F &&f, Rs &&... rs) {
174 for (auto b : map(f, rs...)) {
183 /// Return true if the element-wise application of predicate \a f
184 /// on \a rs evaluates to true for any element.
186 template<typename F, typename... Rs>
188 any_of(F &&f, Rs &&... rs) {
189 for (auto b : map(f, rs...)) {
198 /// Erase elements for which predicate \a f evaluates to true from
201 template<typename F, typename R>
203 erase_if(F &&f, R &&r) {
204 auto i = r.begin(), e = r.end();
206 for (auto j = r.begin(); j != e; ++j) {