coveo::linq
Implementation of .NET-like LINQ operators in C++
linq.h
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief C++ LINQ operators.
4  *
5  * This file contains the definition of all LINQ operators, as well
6  * as the entry points (e.g., <tt>coveo::linq::from()</tt>, etc.) and
7  * the chaining operator (e.g. <tt>coveo::linq::operator|()</tt>).
8  * This is the only file that needs to be included to use the library.
9  *
10  * @copyright 2016-2019, Coveo Solutions Inc.
11  * Distributed under the Apache License, Version 2.0 (see <a href="https://github.com/coveo/linq/blob/master/LICENSE">LICENSE</a>).
12  */
13 
14 /**
15  * @mainpage notitle
16  * @tableofcontents
17  * @section intro Introduction
18  *
19  * Welcome to the documentation of the <tt>coveo::linq</tt> library. This library implements
20  * .NET-like <a href="https://en.wikipedia.org/wiki/Language_Integrated_Query">LINQ</a> operators in C++.
21  * These can be chained to build powerful expressions to query, filter and transform data in any
22  * type of sequence, like arrays, containers, etc. (anything that supports <tt>std::begin()</tt>
23  * and <tt>std::end()</tt> should work).
24  *
25  * If this is your first time with the library, start at @ref linq "LINQ expressions".
26  *
27  * @section example Example
28  *
29  * Here is an example that chains many operators to produce a filtered, ordered sequence:
30  *
31  * @code
32  * #include <coveo/linq.h>
33  * #include <iostream>
34  *
35  * int main()
36  * {
37  * const int FIRST[] = { 42, 23, 66, 13, 11, 7, 24, 10 };
38  * const int SECOND[] = { 67, 22, 13, 23, 41, 66, 6, 7, 10 };
39  *
40  * using namespace coveo::linq;
41  *
42  * auto is_even = [](int i) { return i % 2 == 0; };
43  *
44  * auto seq = from(FIRST)
45  * | intersect(SECOND) // Intersect both arrays
46  * | where([](int i) { return i != 13; }) // I'm supersticious, remove 13
47  * | order_by_descending(is_even) // Place even numbers first
48  * | then_by([](int i) { return i; }); // Then sort numbers ascending
49  *
50  * std::cout << std::endl;
51  * for (auto&& elem : seq) {
52  * std::cout << elem << " ";
53  * }
54  * std::cout << std::endl;
55  * // Prints "10 66 7 23"
56  *
57  * return 0;
58  * }
59  * @endcode
60  *
61  * <tt>coveo::linq::operator|()</tt> is used to @ref linq_chaining "chain together" the various
62  * @ref linq_operators "LINQ operators", and <tt>coveo::linq::from()</tt> is used as the
63  * @ref linq_entry_points "entry point" of the expression, providing the initial sequence on
64  * which operators will be applied. The sequence is then transformed by each operator, and
65  * the result is passed to the next operator.
66  *
67  * @section install Installing / requirements
68  *
69  * The <tt>coveo::linq</tt> library is header-only. Therefore, it is not
70  * necessary to "build" it to use. Simply copy the @c lib directory with all
71  * its files to a suitable place and add it to your project's include path.
72  *
73  * The library requires C++11 support. Several compilers meet
74  * that requirements, including the following (as tested by
75  * <a href="https://travis-ci.org/coveo/linq">Continuous</a>
76  * <a href="https://ci.appveyor.com/project/clechasseur/linq/branch/master">Integration</a>):
77  *
78  * - GCC 5.4.1
79  * - Clang 3.4
80  * - Visual Studio 2015 Update 3
81  *
82  * @section help Help / bugs / etc.
83  *
84  * Need help with the library? Found a bug? Please visit the <tt>coveo::linq</tt>
85  * GitHub project page at:
86  *
87  * &nbsp;&nbsp;&nbsp;&nbsp;https://github.com/coveo/linq
88  *
89  * There, you can file issues with questions or problems.
90  *
91  * @copyright 2016-2019, Coveo Solutions Inc.
92  * Distributed under the Apache License, Version 2.0 (see <a href="https://github.com/coveo/linq/blob/master/LICENSE">LICENSE</a>).
93  */
94 
95 /**
96  * @defgroup linq LINQ expressions
97  *
98  * LINQ expressions are comprised of three distinct parts: an @ref linq_entry_points "entry point",
99  * one or more @ref linq_operators "operators" and a glue operator to @ref linq_chaining "chain"
100  * those elements together. The entry point provides the initial sequence on which to operate and
101  * each LINQ operator in turn applies a change to that sequence - be it sorting, filtering, etc.
102  *
103  * Here is an example with all elements. Here, we filter a sequence of numbers to only keep those
104  * above 20, then we order them by numerical value.
105  *
106  * @code
107  * const int NUMBERS[] = { 42, 23, 11, 66, 7 };
108  *
109  * using namespace coveo::linq;
110  * auto seq = from(NUMBERS)
111  * | where([](int i) { return i >= 20; })
112  * | order_by([](int i) { return i; });
113  * // seq contains 23, 42, 66
114  * @endcode
115  *
116  * <tt>coveo::linq::from()</tt> is the usual entry point for a LINQ expression, but there are a
117  * few others. <tt>coveo::linq::operator|()</tt> is used to chain the LINQ operators together.
118  * As for LINQ operators, there are too many of them to list them here. For more information, see:
119  *
120  * - @ref linq_entry_points
121  * - @ref linq_chaining
122  * - @ref linq_operators
123  */
124 
125 /**
126  * @ingroup linq
127  * @defgroup linq_entry_points LINQ expression entry points
128  * @brief Functions to start a LINQ expression.
129  *
130  * An "entry point" is a function that provides the initial sequence on which to apply LINQ operators.
131  * It also provides a nice look to the expression, a bit like a database query.
132  *
133  * The usual entry point for a LINQ expression is <tt>coveo::linq::from()</tt>, which simply returns
134  * the sequence passed in. Other entry points generate a sequence for use in the expression.
135  */
136 
137 /**
138  * @ingroup linq
139  * @defgroup linq_chaining LINQ operator chaining
140  * @brief How to chain LINQ operators into an expression.
141  *
142  * In order to create powerful LINQ expressions, operators need to be chained together so as to be
143  * applied in a specific order. To do this, <tt>coveo::linq::operator|()</tt> has been overloaded.
144  * Every @ref linq_operators "LINQ operator" returns a function object that is applied on the
145  * current sequence by <tt>coveo::linq::operator|()</tt>. By aligning the instances of @c | in the
146  * code, LINQ expressions are easy to read:
147  *
148  * @code
149  * using namespace coveo::linq;
150  * auto seq = from(some_sequence)
151  * | linq_op_1(...)
152  * | linq_op_2(...)
153  * | ...;
154  * @endcode
155  */
156 
157 /**
158  * @ingroup linq
159  * @defgroup linq_operators LINQ operators
160  * @brief Information and reference of LINQ operators.
161  *
162  * A <em>LINQ operator</em> is designed to accept a sequence as input, perform some specific task with it
163  * and return a result, which is usually (but not necessarily) another sequence. For example, a LINQ operator
164  * might filter the elements of a sequence to remove unwanted ones, or it could concatenate the sequence with
165  * another. Some LINQ operators are inspired by database operations, like <tt>coveo::linq::join()</tt>, but
166  * not all of them have an equivalent in the database world.
167  *
168  * Some LINQ operators are identified as @b terminal. This means that they return a result that is not a sequence,
169  * but a single value. Because of this, they can only appear at the end of a LINQ expression, since no other
170  * operator can be chained after them.
171  *
172  * In the <tt>coveo::linq</tt> library, LINQ operators are implemented as functions that return a
173  * <em>function object</em> implementing the operator logic. The function object is then @e applied
174  * to the sequence by <tt>coveo::linq::operator|()</tt>. For more information on this and on how to
175  * develop custom LINQ operators, see @ref linq_custom_operators.
176  *
177  * The <tt>coveo::linq</tt> library includes many different operators for various needs. Most of them
178  * are inspired by a corresponding operator in the .NET library, although usage is often different.
179  * For a list of operators, see @ref linq_operators_list.
180  */
181 
182 /**
183  * @ingroup linq_operators
184  * @defgroup linq_operators_list List of built-in LINQ operators
185  * @brief Reference for all built-in LINQ operators.
186  *
187  * This page lists all LINQ operators implemented in the <tt>coveo::linq</tt> library.
188  * They are listed alphabetically and grouped by purpose.
189  */
190 
191 /**
192  * @ingroup linq_operators
193  * @defgroup linq_custom_operators Implementing custom LINQ operators
194  * @brief How to design and implement your own LINQ operators.
195  *
196  * One of the features of the <tt>coveo::linq</tt> library is that LINQ operators are
197  * implemented as <em>function objects</em> to be applied to a sequence, instead of
198  * member functions (of <tt>coveo::enumerable</tt> for instance.) This makes it easy
199  * to extend the library by implementing new operators.
200  *
201  * To make it easy to apply LINQ operators, the library defines, for each operator, a
202  * corresponding function that simply returns the <em>function object</em>. Then,
203  * <tt>coveo::linq::operator|()</tt> is used to @e apply the LINQ operator to a sequence.
204  * What this means internally is that <tt>operator|()</tt> calls the operator's function
205  * object's <tt>operator()()</tt> member function, passing it the sequence to apply it to.
206  * The operator's function object must then perform its work and return either a new
207  * sequence or perhaps a single value (for a terminal operator).
208  *
209  * Here is a real-world example of this. Let's say we wanted to implement a new LINQ
210  * operator named @c step that steps through a sequence by specific increments. First,
211  * we declare the shell of our function object that implements the operator, along with
212  * an <tt>operator()()</tt> so that the operator can be applied to a sequence:
213  *
214  * @code
215  * template<typename = void>
216  * class step_impl
217  * {
218  * private:
219  * std::size_t n_;
220  *
221  * public:
222  * explicit step_impl(std::size_t n) : n_(n) { }
223  *
224  * template<typename Seq>
225  * auto operator()(Seq&& seq) {
226  * // TODO
227  * }
228  * };
229  * @endcode
230  *
231  * Note that the sequence's type is not specified in the class template itself - when the
232  * operator's function object will be created, we won't know the type of sequence yet.
233  * Instead, it is specified as a template argument to <tt>operator()()</tt> itself. Also
234  * note that the function object's constructor must receive all parameters it needs to
235  * work (except for the sequence of course). In our case, we receive the number of steps
236  * to use for each invocation.
237  *
238  * Because our operator must step through elements of the sequence it is applied to, it needs
239  * to return a new sequence. Furthermore, that sequence must wrap the source sequence to be
240  * able to iterate its elements. One way to do this without implementing complex sequence
241  * logic is by using <tt>coveo::enumerable</tt>. This sequence wrapper's only requirement is
242  * that we implement a <em>next delegate</em>: a function that, when called, returns a pointer
243  * to the next element in the sequence, or @c nullptr when done. <tt>coveo::enumerable</tt>
244  * is used extensively in the <tt>coveo::linq</tt> library to implement LINQ operators.
245  *
246  * Let's add a skeleton for a next delegate to our example:
247  *
248  * @code
249  * template<typename = void>
250  * class step_impl
251  * {
252  * private:
253  * template<typename Seq>
254  * class next_impl
255  * {
256  * public:
257  * explicit next_impl(Seq&& seq, std::site_t n) {
258  * // TODO
259  * }
260  *
261  * auto operator()() {
262  * // TODO
263  * }
264  * };
265  *
266  * private:
267  * std::size_t n_;
268  *
269  * public:
270  * explicit step_impl(std::size_t n) : n_(n) { }
271  *
272  * template<typename Seq>
273  * auto operator()(Seq&& seq)
274  * -> coveo::enumerable<typename coveo::seq_traits<Seq>::value_type>
275  * {
276  * return next_impl<Seq>(std::forward<Seq>(seq), n_);
277  * }
278  * };
279  * @endcode
280  *
281  * Note the use of <tt>coveo::seq_traits</tt> to produce a sequence of the same type
282  * of elements as the source sequence. Along with <tt>coveo::seq_element_traits</tt>,
283  * these can be used to simplify detection of sequence types in LINQ operator implementations.
284  *
285  * <tt>coveo::enumerable</tt>'s implementation will @e copy the next delegate every time it
286  * is needed - in its copy/move constructors / assignment operators, but also when an iterator
287  * is fetched. This is done so that the state of the enumeration can be kept in the next delegate
288  * and copied as well. Because of this however, objects to be shared among delegates must be
289  * kept in shared memory as well - using <tt>std::shared_ptr</tt> for instance.
290  *
291  * Let's add storage for our sequence in our example's next delegate:
292  *
293  * @code
294  * template<typename = void>
295  * class step_impl
296  * {
297  * private:
298  * template<typename Seq>
299  * class next_impl
300  * {
301  * private:
302  * using iterator_type = typename coveo::seq_traits<Seq>::iterator_type;
303  *
304  * struct internals {
305  * Seq seq_;
306  * iterator_type end_;
307  * std::size_t n_;
308  *
309  * internals(Seq&& seq, std::size_t n)
310  * : seq_(std::forward<Seq>(seq)),
311  * end_(std::end(seq_)),
312  * n_(n) { }
313  * internals(const internals&) = delete;
314  * internals& operator=(const internals&) = delete;
315  * };
316  * using internals_sp = std::shared_ptr<internals>;
317  *
318  * internals_sp spint_;
319  * iterator_type it_;
320  * public:
321  * explicit next_impl(Seq&& seq, std::size_t n)
322  * : spint_(std::make_shared<internals>(std::forward<Seq>(seq), n)),
323  * it_(std::begin(spint_->seq_)) { }
324  *
325  * auto operator()() {
326  * // TODO
327  * }
328  * };
329  *
330  * private:
331  * std::size_t n_;
332  *
333  * public:
334  * explicit step_impl(std::size_t n) : n_(n) { }
335  *
336  * template<typename Seq>
337  * auto operator()(Seq&& seq)
338  * -> coveo::enumerable<typename coveo::seq_traits<Seq>::value_type>
339  * {
340  * return next_impl<Seq>(std::forward<Seq>(seq), n_);
341  * }
342  * };
343  * @endcode
344  *
345  * The @c internals class is used to keep all data that is to be shared among next delegates, including
346  * the sequence we're wrapping. This allows us to avoid copying the sequence for every delegate copy.
347  * The @c internals are kept in a <tt>std::shared_ptr</tt>.
348  *
349  * Also note that we keep an @c end iterator in the @c internals object, but we keep another iterator
350  * in the next delegate directly. This is the @b state of the enumeration: the iterator points to the
351  * next element we'll be returning. This iterator is initialized at @c begin initially.
352  *
353  * Now, all that is left is to implement the operator logic itself: iterating over the sequence, stepping
354  * through elements by a specific increment.
355  *
356  * @code
357  * template<typename = void>
358  * class step_impl
359  * {
360  * private:
361  * template<typename Seq>
362  * class next_impl
363  * {
364  * private:
365  * using iterator_type = typename coveo::seq_traits<Seq>::iterator_type;
366  *
367  * struct internals {
368  * Seq seq_;
369  * iterator_type end_;
370  * std::size_t n_;
371  *
372  * internals(Seq&& seq, std::size_t n)
373  * : seq_(std::forward<Seq>(seq)),
374  * end_(std::end(seq_)),
375  * n_(n) { }
376  * internals(const internals&) = delete;
377  * internals& operator=(const internals&) = delete;
378  * };
379  * using internals_sp = std::shared_ptr<internals>;
380  *
381  * internals_sp spint_;
382  * iterator_type it_;
383  * public:
384  * explicit next_impl(Seq&& seq, std::size_t n)
385  * : spint_(std::make_shared<internals>(std::forward<Seq>(seq), n)),
386  * it_(std::begin(spint_->seq_)) { }
387  *
388  * auto operator()() -> typename coveo::seq_traits<Seq>::pointer {
389  * typename coveo::seq_traits<Seq>::pointer pobj = nullptr;
390  * if (it_ != spint_->end_) {
391  * // Return this element.
392  * typename coveo::seq_traits<Seq>::reference robj = *it_;
393  * pobj = std::addressof(robj);
394  *
395  * // Move to next element by stepping as appropriate.
396  * for (std::size_t i = 0; it_ != spint_->end_ && i < spint_->n_; ++i, ++it_) {
397  * }
398  * }
399  * return pobj;
400  * }
401  * };
402  *
403  * private:
404  * std::size_t n_;
405  *
406  * public:
407  * explicit step_impl(std::size_t n) : n_(n) { }
408  *
409  * template<typename Seq>
410  * auto operator()(Seq&& seq)
411  * -> coveo::enumerable<typename coveo::seq_traits<Seq>::value_type>
412  * {
413  * return next_impl<Seq>(std::forward<Seq>(seq), n_);
414  * }
415  * };
416  *
417  * template<typename = void>
418  * auto step(std::size_t n) -> step_impl<> {
419  * return step_impl<>(n);
420  * }
421  * @endcode
422  *
423  * Note that we also added a "helper function" that returns our operator's function object's implementation.
424  * This function will be the one used to invoke our LINQ operator:
425  *
426  * @code
427  * const int NUMS[] = { 42, 23, 66, 11, 7, 67 };
428  *
429  * using namespace coveo::linq;
430  * auto seq = from(NUMS)
431  * | step(2);
432  * // seq == { 42, 66, 7 };
433  * @endcode
434  *
435  * Implementing a terminal operator is even easier, because there's no need to provide a sequence implementation.
436  * Let's say we want to implement a @c prod operator that calculates the product of all sequence elements.
437  * Like the <tt>coveo::linq::sum()</tt> operator, it could be done by using a <em>numerical function</em> to
438  * get a numerical value for each sequence element. It could be done like this:
439  *
440  * @code
441  * template<typename F>
442  * class prod_impl
443  * {
444  * private:
445  * const F& num_f_;
446  *
447  * public:
448  * explicit prod_impl(const F& num_f) : num_f_(num_f) { }
449  *
450  * template<typename Seq>
451  * auto operator()(Seq&& seq) -> typename std::decay<decltype(num_f_(*std::begin(seq)))>::type {
452  * auto it = std::begin(seq);
453  * auto end = std::end(seq);
454  * if (it == end) {
455  * coveo::linq::throw_linq_empty_sequence();
456  * }
457  * auto product = num_f_(*it);
458  * for (++it; it != end; ++it) {
459  * product *= num_f_(*it);
460  * }
461  * return product;
462  * }
463  * };
464  *
465  * template<typename F>
466  * auto prod(const F& num_f) -> prod_impl<F> {
467  * return prod_impl<F>(num_f);
468  * }
469  * @endcode
470  *
471  * Now, using the operator is as easy as using <tt>coveo::linq::sum()</tt>:
472  *
473  * @code
474  * const int NUMS[] = { 42, 23, 66 };
475  *
476  * using namespace coveo::linq;
477  * auto product = from(NUMS)
478  * | prod([](int i) { return i; });
479  * // product == 63756
480  * @endcode
481  *
482  * For more examples on how to implement LINQ operators, the easiest way is probably to have
483  * a look at the implementation of the operators included in the <tt>coveo::linq</tt> library
484  * itself. While the helper functions are documented @ref linq_operators_list "here", it is
485  * possible to look at the internal implementations in the file @ref coveo/linq/detail/linq_detail.h :
486  *
487  * @include coveo/linq/detail/linq_detail.h
488  */
489 
490 #ifndef COVEO_LINQ_H
491 #define COVEO_LINQ_H
492 
493 #include "coveo/linq/exception.h"
494 
495 #include <coveo/enumerable.h>
496 #include <coveo/linq/detail/linq_detail.h>
497 
498 #include <algorithm>
499 #include <cstddef>
500 #include <functional>
501 #include <iterator>
502 #include <memory>
503 #include <utility>
504 
505 namespace coveo {
506 namespace linq {
507 
508 /**
509  * @ingroup linq_entry_points
510  * @brief Standard LINQ expression entry point.
511  * @headerfile linq.h <coveo/linq/linq.h>
512  *
513  * Standard entry point for a LINQ expression. Specifies the initial
514  * sequence on which the first operator will be applied. After this,
515  * use <tt>coveo::linq::operator|()</tt> to chain LINQ operators and apply
516  * them in a specific order (see @ref linq_chaining "chaining").
517  *
518  * Use like this:
519  *
520  * @code
521  * using namespace coveo::linq;
522  * auto result = from(some_sequence)
523  * | linq_operator(...)
524  * | ...;
525  * @endcode
526  */
527 template<typename Seq>
528 auto from(Seq&& seq) -> decltype(std::forward<Seq>(seq)) {
529  return std::forward<Seq>(seq);
530 }
531 
532 /**
533  * @ingroup linq_entry_points
534  * @brief LINQ expression entry point from iterators.
535  * @headerfile linq.h <coveo/linq/linq.h>
536  *
537  * Entry point for a LINQ expression that produces a sequence
538  * of elements delimited by two iterators. After this, use
539  * <tt>coveo::linq::operator|()</tt> to chain LINQ operators and apply
540  * them in a specific order (see @ref linq_chaining "chaining").
541  *
542  * Use like this:
543  *
544  * @code
545  * using namespace coveo::linq;
546  * auto result = from_range(something.begin(), something.end())
547  * | linq_operator(...)
548  * | ...;
549  * @endcode
550  *
551  * @see coveo::enumerate_range()
552  */
553 template<typename It>
554 auto from_range(It ibeg, It iend)
555  -> decltype(enumerate_range(std::move(ibeg), std::move(iend)))
556 {
557  return enumerate_range(std::move(ibeg), std::move(iend));
558 }
559 
560 /**
561  * @ingroup linq_entry_points
562  * @brief LINQ expression entry point from range of numbers.
563  * @headerfile linq.h <coveo/linq/linq.h>
564  *
565  * Entry point for a LINQ expression that produces a sequence
566  * of incrementing numbers from a starting point. After this, use
567  * <tt>coveo::linq::operator|()</tt> to chain LINQ operators and apply
568  * them in a specific order (see @ref linq_chaining "chaining").
569  *
570  * Use like this:
571  *
572  * @code
573  * using namespace coveo::linq;
574  * auto result = from_int_range(1, 10) // 1, 2, 3...
575  * | linq_operator(...)
576  * | ...;
577  * @endcode
578  */
579 template<typename IntT>
581  -> coveo::enumerable<const typename std::decay<IntT>::type>
582 {
583  std::vector<typename std::decay<IntT>::type> vvalues;
584  vvalues.reserve(count);
585  while (count-- > 0) {
586  vvalues.push_back(first++);
587  }
588  return enumerate_container(std::move(vvalues));
589 }
590 
591 /**
592  * @ingroup linq_entry_points
593  * @brief LINQ expression entry point from a repeated value.
594  * @headerfile linq.h <coveo/linq/linq.h>
595  *
596  * Entry point for a LINQ expression that produces a sequence
597  * created by repeating a given value multiple times.. After this, use
598  * <tt>coveo::linq::operator|()</tt> to chain LINQ operators and apply
599  * them in a specific order (see @ref linq_chaining "chaining").
600  *
601  * Use like this:
602  *
603  * @code
604  * using namespace coveo::linq;
605  * auto result = from_repeated(std::string("Life"), 7) // "Life", "Life", "Life"...
606  * | linq_operator(...)
607  * | ...;
608  * @endcode
609  */
610 template<typename T>
611 auto from_repeated(const T& value, std::size_t count)
612  -> coveo::enumerable<const typename std::decay<T>::type>
613 {
614  std::vector<typename std::decay<T>::type> vvalues;
615  vvalues.reserve(count);
616  while (count-- > 0) {
617  vvalues.push_back(value);
618  }
619  return enumerate_container(std::move(vvalues));
620 }
621 
622 /**
623  * @ingroup linq_chaining
624  * @brief Applies LINQ operators and allows chaining.
625  * @headerfile linq.h <coveo/linq/linq.h>
626  *
627  * Applies a given LINQ operator to the current sequence.
628  * Can be used multiple times to chain many operators in a specific order.
629  *
630  * Use like this:
631  *
632  * @code
633  * using namespace coveo::linq;
634  * auto result = from(some_sequence)
635  * | linq_op_1(...)
636  * | linq_op_2(...);
637  * @endcode
638  */
639 template<typename Seq, typename Op>
640 auto operator|(Seq&& seq, Op&& op) -> decltype(std::forward<Op>(op)(std::forward<Seq>(seq))) {
641  return std::forward<Op>(op)(std::forward<Seq>(seq));
642 }
643 
644 /**
645  * @ingroup linq_operators_list
646  * @defgroup linq_op_aggregate aggregate
647  * @brief Aggregates values in a sequence to produce a single value.
648  *
649  * The @c aggregate operator, as its name implies, can be used to @e aggregate all values
650  * in a sequence into a single value. To achieve this, it needs an <em>aggregation function</em>
651  * that will be called repeatedly to add each element in the sequence to the aggregate.
652  *
653  * This is a @b terminal operator.
654  *
655  * <b>.NET equivalent:</b> Aggregate
656  */
657 
658 /**
659  * @ingroup linq_op_aggregate
660  * @brief Aggregates values using an aggregation function.
661  *
662  * Aggregates all elements in a sequence by repeatedly calling an <em>aggregation function</em>.
663  * The function receives two parameters: the current aggregate value, and the sequence element
664  * to add. The function must then add the element to the aggregate and return a new aggregate
665  * value. On the first call, the aggregate value is the first sequence element.
666  *
667  * Does not work on empty sequences.
668  *
669  * Use like this:
670  *
671  * @code
672  * const int NUMS[] = { 42, 23, 66 };
673  *
674  * using namespace coveo::linq;
675  * auto agg = from(NUMS)
676  * | aggregate([](int so_far, int i) { return so_far + i; });
677  * // agg == 131
678  * @endcode
679  *
680  * @param agg_f Aggregation function.
681  * @return (Once applied) Final aggregate value.
682  * @exception coveo::linq::empty_sequence The sequence contains no elements.
683  */
684 template<typename F>
685 auto aggregate(const F& agg_f)
686  -> detail::aggregate_impl_1<F>
687 {
688  return detail::aggregate_impl_1<F>(agg_f);
689 }
690 
691 /**
692  * @ingroup linq_op_aggregate
693  * @brief Aggregates values using an aggregation function, starting with a seed.
694  *
695  * Aggregates all elements in a sequence by repeatedly calling an <em>aggregation function</em>.
696  * The function receives two parameters: the current aggregate value, and the sequence element
697  * to add. The function must then add the element to the aggregate and return a new aggregate
698  * value. On the first call, the aggregate value is equal to the provided @c seed.
699  *
700  * Use like this:
701  *
702  * @code
703  * const int NUMS[] = { 42, 23, 66 };
704  *
705  * using namespace coveo::linq;
706  * auto agg = from(NUMS)
707  * | aggregate(11,
708  * [](int so_far, int i) { return so_far + i; });
709  * // agg == 142
710  * @endcode
711  *
712  * @param seed Initial aggregate value.
713  * @param agg_f Aggregation function.
714  * @return (Once applied) Final aggregate value.
715  */
716 template<typename Acc, typename F>
717 auto aggregate(const Acc& seed, const F& agg_f)
718  -> detail::aggregate_impl_2<Acc, F>
719 {
720  return detail::aggregate_impl_2<Acc, F>(seed, agg_f);
721 }
722 
723 /**
724  * @ingroup linq_op_aggregate
725  * @brief Aggregates values using aggregation function, seed and result selector.
726  *
727  * Aggregates all elements in a sequence by repeatedly calling an <em>aggregation function</em>.
728  * The function receives two parameters: the current aggregate value, and the sequence element
729  * to add. The function must then add the element to the aggregate and return a new aggregate
730  * value. On the first call, the aggregate value is equal to the provided @c seed. Once the
731  * final aggregate value is computed, it is passed to a <em>result selector</em> to produce
732  * a final value to return.
733  *
734  * Use like this:
735  *
736  * @code
737  * const int NUMS[] = { 42, 23, 66 };
738  *
739  * using namespace coveo::linq;
740  * auto agg = from(NUMS)
741  * | aggregate(11,
742  * [](int so_far, int i) { return so_far + i; },
743  * [](int so_far) { return so_far / 2; });
744  * // agg == 71
745  * @endcode
746  *
747  * @param seed Initial aggregate value.
748  * @param agg_f Aggregation function.
749  * @param result_f Function used to produce final result from aggregate.
750  * @return (Once applied) Result returned by @c result_f.
751  */
752 template<typename Acc, typename F, typename RF>
753 auto aggregate(const Acc& seed, const F& agg_f, const RF& result_f)
754  -> detail::aggregate_impl_3<Acc, F, RF>
755 {
756  return detail::aggregate_impl_3<Acc, F, RF>(seed, agg_f, result_f);
757 }
758 
759 /**
760  * @ingroup linq_operators_list
761  * @defgroup linq_op_all all
762  * @brief Checks if all elements in a sequence satisfy a predicate.
763  *
764  * The @c all operator scans a sequence and validates that all its elements
765  * satisfy a given @e predicate.
766  *
767  * This is a @b terminal operator.
768  *
769  * <b>.NET equivalent:</b> All
770  */
771 
772 /**
773  * @ingroup linq_op_all
774  * @brief Checks elements in a sequence against a predicate.
775  *
776  * Scans a sequence and calls a @e predicate with each element. The predicate
777  * must return @c true if the element satisfies the predicate. The final result
778  * will indicate if all elements satisfy the predicate.
779  *
780  * Works on empty sequences (returns @c true in such a case).
781  *
782  * Use like this:
783  *
784  * @code
785  * const int NUMS = { 42, 23, 66 };
786  *
787  * using namespace coveo::linq;
788  * bool all_big = from(NUMS)
789  * | all([](int i) { return i >= 10; });
790  * bool all_odd = from(NUMS)
791  * | all([](int i) { return i % 2 != 0; });
792  * // all_big == true
793  * // all_odd == false
794  * @endcode
795  *
796  * @param pred Predicate to satisfy.
797  * @return (Once applied) @c true if all elements in sequence satisfy @c pred.
798  */
799 template<typename Pred>
800 auto all(const Pred& pred)
801  -> detail::all_impl<Pred>
802 {
803  return detail::all_impl<Pred>(pred);
804 }
805 
806 /**
807  * @ingroup linq_operators_list
808  * @defgroup linq_op_any any
809  * @brief Checks if a sequence has elements.
810  *
811  * The @c any operator checks if a sequence has elements, or if it has elements
812  * that satisfy a given @e predicate.
813  *
814  * This is a @b terminal operator.
815  *
816  * <b>.NET equivalent:</b> Any
817  */
818 
819 /**
820  * @ingroup linq_op_any
821  * @brief Checks for any element.
822  *
823  * Checks if a sequence has elements.
824  *
825  * Use like this:
826  *
827  * @code
828  * const std::vector<int> ONE = { 42, 23, 66 };
829  * const std::vector<int> TWO;
830  *
831  * using namespace coveo::linq;
832  * bool one_any = from(ONE)
833  * | any();
834  * bool two_any = from(TWO)
835  * | any();
836  * // one_any == true
837  * // two_any == false
838  * @endcode
839  *
840  * @return (Once applied) @c true if sequence has at least one element.
841  */
842 template<typename = void>
843 auto any()
844  -> detail::any_impl_0<>
845 {
846  return detail::any_impl_0<>();
847 }
848 
849 /**
850  * @ingroup linq_op_any
851  * @brief Checks for any element that satisfy a predicate.
852  *
853  * Checks if a sequence has at least one element that satisfy a @e predicate.
854  * The predicate is called with each element and must return @c true if the
855  * element satisfy the predicate. The final result indicates if there's at least
856  * one element that satisfy the predicate.
857  *
858  * Works on empty sequences (returns @c false in such a case).
859  *
860  * Use like this:
861  *
862  * @code
863  * const int NUMS = { 42, 23, 66 };
864  *
865  * using namespace coveo::linq;
866  * bool any_big = from(NUMS)
867  * | any([](int i) { return i >= 90; });
868  * bool any_odd = from(NUMS)
869  * | any([](int i) { return i % 2 != 0; });
870  * // any_big == false
871  * // any_odd == true
872  * @endcode
873  *
874  * @param pred Predicate to satisfy.
875  * @return (Once applied) @c true if at least one element in sequence satisfies @c pred.
876  */
877 template<typename Pred>
878 auto any(const Pred& pred)
879  -> detail::any_impl_1<Pred>
880 {
881  return detail::any_impl_1<Pred>(pred);
882 }
883 
884 /**
885  * @ingroup linq_operators_list
886  * @defgroup linq_op_average average
887  * @brief Computes average of a sequence of values.
888  *
889  * The @c average operator computes the average of all values in a sequence. To achieve this,
890  * it needs a <em>numerical function</em> to extract a numeric value from each sequence element.
891  *
892  * This is a @b terminal operator.
893  *
894  * <b>.NET equivalent:</b> Average
895  */
896 
897 /**
898  * @ingroup linq_op_average
899  * @brief Computes average using numerical function.
900  *
901  * Computes the average of all elements in a sequence by repeatedly calling a <em>numerical function</em>.
902  * The function receives an element as parameter and must return a numerical value for the element.
903  * The final result is the average of all such numerical values.
904  *
905  * Does not work on empty sequences.
906  *
907  * Use like this:
908  *
909  * @code
910  * const std::vector<std::string> STRS = { "42", "23", "66" };
911  *
912  * using namespace coveo::linq;
913  * auto avg = from(STRS)
914  * | average([](auto&& s) { return std::stoi(s); });
915  * // avg == 43
916  * @endcode
917  *
918  * @param num_f Function to get numerical value for each element.
919  * @return (Once applied) Average of all extracted numerical values.
920  * @exception coveo::linq::empty_sequence The sequence contains no elements.
921  */
922 template<typename F>
923 auto average(const F& num_f)
924  -> detail::average_impl<F>
925 {
926  return detail::average_impl<F>(num_f);
927 }
928 
929 /**
930  * @ingroup linq_operators_list
931  * @defgroup linq_op_cast cast
932  * @brief Casts sequence elements to another type.
933  *
934  * The @c cast operator modifies a sequence by casting all its element to another type.
935  *
936  * <b>.NET equivalent:</b> Cast
937  */
938 
939 /**
940  * @ingroup linq_op_cast
941  * @brief Casts sequence elements to another type.
942  *
943  * Casts each element in a sequence to another type and returns a new sequence
944  * of all such modified elements. The elements are cast using @c static_cast.
945  *
946  * Use like this:
947  *
948  * @code
949  * const int NUMS[] = { 42, 23, 66 };
950  *
951  * using namespace coveo::linq;
952  * auto dbls = from(NUMS)
953  * | cast<double>();
954  * // dbls == { 42.0, 23.0, 66.0 }
955  * @endcode
956  *
957  * @tparam U New type to cast elements to.
958  * @return (Once applied) Sequence of cast elements.
959  */
960 template<typename U>
961 auto cast()
962  -> detail::select_impl<detail::indexless_selector_proxy<detail::cast_selector<U>>>
963 {
964  return detail::select_impl<detail::indexless_selector_proxy<detail::cast_selector<U>>>(
965  detail::indexless_selector_proxy<detail::cast_selector<U>>(detail::cast_selector<U>()));
966 }
967 
968 /**
969  * @ingroup linq_operators_list
970  * @defgroup linq_op_concat concat
971  * @brief Concatenate two sequences.
972  *
973  * The @c concat operator concatenates two sequences, producing a new sequence
974  * containing all elements from both source sequences.
975  *
976  * <b>.NET equivalent:</b> Concat
977  */
978 
979 /**
980  * @ingroup linq_op_concat
981  * @brief Concatenates two sequences.
982  *
983  * Concatenates two sequences, producing a sequence that contains all elements
984  * from both source sequences.
985  *
986  * For this to work, both source sequences must contain compatible elements.
987  *
988  * The resulting sequence's elements will be @c const if at least one source
989  * sequence's elements are @c const.
990  *
991  * Use like this:
992  *
993  * @code
994  * const int ONE[] = { 42, 23, 66 };
995  * const int TWO[] = { 67, 11, 7 };
996  *
997  * using namespace coveo::linq;
998  * auto seq = from(ONE)
999  * | concat(TWO);
1000  * // seq == { 42, 23, 66, 67, 11, 7 }
1001  * @endcode
1002  *
1003  * @param seq2 Second sequence to concatenate.
1004  * @return (Once applied) Concatenation of both sequences.
1005  */
1006 template<typename Seq2>
1007 auto concat(Seq2&& seq2)
1008  -> detail::concat_impl<Seq2>
1009 {
1010  return detail::concat_impl<Seq2>(std::forward<Seq2>(seq2));
1011 }
1012 
1013 /**
1014  * @ingroup linq_operators_list
1015  * @defgroup linq_op_contains contains
1016  * @brief Looks for an element in a sequence.
1017  *
1018  * The @c contains operator determines if a sequence contains a specific element.
1019  *
1020  * This is a @b terminal operator.
1021  *
1022  * <b>.NET equivalent:</b> Contains
1023  */
1024 
1025 /**
1026  * @ingroup linq_op_contains
1027  * @brief Look for element in a sequence.
1028  *
1029  * Scans a sequence, looking for the provided element. Elements are compared
1030  * using <tt>operator==()</tt>.
1031  *
1032  * Use like this:
1033  *
1034  * @code
1035  * const int NUMS[] = { 42, 23, 66 };
1036  *
1037  * using namespace coveo::linq;
1038  * auto has_42 = from(NUMS)
1039  * | contains(42);
1040  * auto has_67 = from(NUMS)
1041  * | contains(67);
1042  * // has_42 == true
1043  * // has_67 == false
1044  * @endcode
1045  *
1046  * @param obj Element to look for.
1047  * @return (Once applied) @c true if @c obj was found in sequence.
1048  */
1049 template<typename T>
1050 auto contains(const T& obj)
1051  -> detail::contains_impl_1<T>
1052 {
1053  return detail::contains_impl_1<T>(obj);
1054 }
1055 
1056 /**
1057  * @ingroup linq_op_contains
1058  * @brief Look for element in a sequence using a predicate.
1059  *
1060  * Scans a sequence, looking for the provided element. Elements are compared
1061  * using the provided predicate.
1062  *
1063  * Use like this:
1064  *
1065  * @code
1066  * const int NUMS[] = { 42, 23, 66 };
1067  *
1068  * auto fuzzy_equal = [](int i, int j) { return std::abs(i - j) <= 2; };
1069  *
1070  * using namespace coveo::linq;
1071  * auto has_67 = from(NUMS)
1072  * | contains(67, fuzzy_equal);
1073  * auto has_11 = from(NUMS)
1074  * | contains(11, fuzzy_equal);
1075  * // has_67 == true
1076  * // has_11 == false
1077  * @endcode
1078  *
1079  * @param obj Element to look for.
1080  * @param pred Predicate used to compare the elements. Always receives
1081  * @c obj as its second argument.
1082  * @return (Once applied) @c true if @c obj was found in sequence.
1083  */
1084 template<typename T, typename Pred>
1085 auto contains(const T& obj, const Pred& pred)
1086  -> detail::contains_impl_2<T, Pred>
1087 {
1088  return detail::contains_impl_2<T, Pred>(obj, pred);
1089 }
1090 
1091 /**
1092  * @ingroup linq_operators_list
1093  * @defgroup linq_op_count count
1094  * @brief Counts elements in a sequence.
1095  *
1096  * The @c count operator computes the number of elements in a sequence,
1097  * or the number of elements satisfying a given predicate.
1098  *
1099  * This is a @b terminal operator.
1100  *
1101  * <b>.NET equivalent:</b> Count
1102  */
1103 
1104 /**
1105  * @ingroup linq_op_count
1106  * @brief Counts elements in sequence.
1107  *
1108  * Computes the number of elements in a sequence.
1109  *
1110  * Use like this:
1111  *
1112  * @code
1113  * const int NUMS[] = { 42, 23, 66 };
1114  *
1115  * using namespace coveo::linq;
1116  * auto num = from(NUMS)
1117  * | count();
1118  * // num == 3
1119  * @endcode
1120  *
1121  * @return (Once applied) Number of elements in sequence.
1122  */
1123 template<typename = void>
1124 auto count()
1125  -> detail::count_impl_0<>
1126 {
1127  return detail::count_impl_0<>();
1128 }
1129 
1130 /**
1131  * @ingroup linq_op_count
1132  * @brief Counts elements in sequence satisfying a predicate.
1133  *
1134  * Computes the number of elements in a sequence that satisfy the given predicate.
1135  *
1136  * Use like this:
1137  *
1138  * @code
1139  * const int NUMS[] = { 42, 23, 66 };
1140  *
1141  * using namespace coveo::linq;
1142  * auto num = from(NUMS)
1143  * | count([](int i) { return i % 2 == 0; });
1144  * // num == 2
1145  * @endcode
1146  *
1147  * @param pred Predicate to satisfy.
1148  * @return (Once applied) Number of elements in sequence for which
1149  * @c pred has returned @c true.
1150  */
1151 template<typename Pred>
1152 auto count(const Pred& pred)
1153  -> detail::count_impl_1<Pred>
1154 {
1155  return detail::count_impl_1<Pred>(pred);
1156 }
1157 
1158 /**
1159  * @ingroup linq_operators_list
1160  * @defgroup linq_op_def_empty default_if_empty
1161  * @brief Ensures a sequence has at least one element.
1162  *
1163  * The @c default_if_empty operator either returns the source sequence or,
1164  * if that sequence is empty, a new sequence with a single, default element.
1165  *
1166  * <b>.NET equivalent:</b> DefaultIfEmpty
1167  */
1168 
1169 /**
1170  * @ingroup linq_op_def_empty
1171  * @brief Ensures sequence has at least one element.
1172  *
1173  * Either returns the source sequence or, if that sequence is empty,
1174  * a new sequence containing a single, default element.
1175  *
1176  * Use like this:
1177  *
1178  * @code
1179  * const std::vector<int> THREE = { 42, 23, 66 };
1180  * const std::vector<int> EMPTY;
1181  *
1182  * using namespace coveo::linq;
1183  * auto seq1 = from(THREE)
1184  * | default_if_empty();
1185  * auto seq2 = from(EMPTY)
1186  * | default_if_empty();
1187  * // seq1 == { 42, 23, 66 }
1188  * // seq2 == { 0 }
1189  * @endcode
1190  *
1191  * @return (Once applied) Source sequence, or sequence with
1192  * single, default element.
1193  */
1194 template<typename = void>
1195 auto default_if_empty()
1196  -> detail::default_if_empty_impl_0<>
1197 {
1198  return detail::default_if_empty_impl_0<>();
1199 }
1200 
1201 /**
1202  * @ingroup linq_op_def_empty
1203  * @brief Ensures sequence has at least one element, specifying said element.
1204  *
1205  * Either returns the source sequence or, if that sequence is empty,
1206  * a new sequence containing the provided default element.
1207  *
1208  * Use like this:
1209  *
1210  * @code
1211  * const std::vector<int> THREE = { 42, 23, 66 };
1212  * const std::vector<int> EMPTY;
1213  *
1214  * using namespace coveo::linq;
1215  * auto seq1 = from(THREE)
1216  * | default_if_empty(11);
1217  * auto seq2 = from(EMPTY)
1218  * | default_if_empty(11);
1219  * // seq1 == { 42, 23, 66 }
1220  * // seq2 == { 11 }
1221  * @endcode
1222  *
1223  * @param obj Default element to use if sequence is empty.
1224  * @return (Once applied) Source sequence, or sequence with
1225  * single element @c obj.
1226  */
1227 template<typename T>
1228 auto default_if_empty(const T& obj)
1229  -> detail::default_if_empty_impl_1<T>
1230 {
1231  return detail::default_if_empty_impl_1<T>(obj);
1232 }
1233 
1234 /**
1235  * @ingroup linq_operators_list
1236  * @defgroup linq_op_distinct distinct
1237  * @brief Filters out duplicate elements in a sequence.
1238  *
1239  * The @c distinct operator filters out duplicate elements in a sequence.
1240  * Unique elements are returned in the same order they appear in the source sequence.
1241  *
1242  * <b>.NET equivalent:</b> Distinct
1243  */
1244 
1245 /**
1246  * @ingroup linq_op_distinct
1247  * @brief Filters out duplicate elements in sequence.
1248  *
1249  * Filters out duplicate elements in a sequence, returning the unique
1250  * elements in the same order they appear in the source sequence.
1251  *
1252  * To filter out duplicates, elements are sorted using <tt>operator&lt;()</tt>.
1253  *
1254  * Use like this:
1255  *
1256  * @code
1257  * const int NUMS[] = { 42, 23, 11, 66, 11, 42, 7, 66, 67 };
1258  *
1259  * using namespace coveo::linq;
1260  * auto seq = from(NUMS)
1261  * | distinct();
1262  * // seq = { 42, 23, 11, 66, 7, 67 }
1263  * @endcode
1264  *
1265  * @return (Once applied) Sequence containing all unique elements
1266  * from source sequence.
1267  */
1268 template<typename = void>
1269 auto distinct()
1270  -> detail::distinct_impl<detail::less<>>
1271 {
1272  return detail::distinct_impl<detail::less<>>(detail::less<>());
1273 }
1274 
1275 /**
1276  * @ingroup linq_op_distinct
1277  * @brief Filters out duplicate elements in sequence using predicate.
1278  *
1279  * Filters out duplicate elements in a sequence, returning the unique
1280  * elements in the same order they appear in the source sequence.
1281  *
1282  * To filter out duplicates, the provided predicate is used to sort
1283  * the elements. The predicate must provide a strict ordering of the
1284  * elements, like <tt>std::less</tt>.
1285  *
1286  * Use like this:
1287  *
1288  * @code
1289  * const int NUMS[] = { 42, 23, 11, 66, 11, 42, 7, 66, 67 };
1290  *
1291  * using namespace coveo::linq;
1292  * auto seq = from(NUMS)
1293  * | distinct([](int i, int j) { return i > j; });
1294  * // seq = { 42, 23, 11, 66, 7, 67 }
1295  * @endcode
1296  *
1297  * @param pred Predicate used to order the elements in order to
1298  * remove the duplicates.
1299  * @return (Once applied) Sequence containing all unique elements
1300  * from source sequence.
1301  */
1302 template<typename Pred>
1303 auto distinct(Pred&& pred)
1304  -> detail::distinct_impl<Pred>
1305 {
1306  return detail::distinct_impl<Pred>(std::forward<Pred>(pred));
1307 }
1308 
1309 /**
1310  * @ingroup linq_operators_list
1311  * @defgroup linq_op_elem_at element_at
1312  * @brief Returns nth element in a sequence.
1313  *
1314  * The @c element_at operator returns the nth element in the sequence.
1315  * If the sequence does not have enough elements, an exception is thrown.
1316  *
1317  * This is a @b terminal operator.
1318  *
1319  * <b>.NET equivalent:</b> ElementAt
1320  */
1321 
1322 /**
1323  * @ingroup linq_op_elem_at
1324  * @brief Returns nth element in sequence.
1325  *
1326  * Returns the <tt>n</tt>th element in a sequence. If the sequence
1327  * does not have enough elements, <tt>coveo::linq::out_of_range</tt>
1328  * is thrown.
1329  *
1330  * Use like this:
1331  *
1332  * @code
1333  * const int NUMS[] = { 42, 23, 66 };
1334  *
1335  * using namespace coveo::linq;
1336  * auto second = from(NUMS)
1337  * | element_at(1);
1338  * // second == 23
1339  * // This throws an exception:
1340  * // auto fourth = from(NUMS)
1341  * // | element_at(3);
1342  * @endcode
1343  *
1344  * @param n 0-based index of element to return.
1345  * @return (Once applied) <tt>n</tt>th element in sequence.
1346  * @exception coveo::linq::out_of_range The sequence does not have enough elements.
1347  */
1348 template<typename = void>
1349 auto element_at(std::size_t n)
1350  -> detail::element_at_impl<>
1351 {
1352  return detail::element_at_impl<>(n);
1353 }
1354 
1355 /**
1356  * @ingroup linq_operators_list
1357  * @defgroup linq_op_elem_at_or_def element_at_or_default
1358  * @brief Returns nth element in a sequence, or a default value.
1359  *
1360  * The @c element_at operator returns the nth element in the sequence.
1361  * If the sequence does not have enough elements, a default value is returned instead.
1362  *
1363  * This is a @b terminal operator.
1364  *
1365  * <b>.NET equivalent:</b> ElementAtOrDefault
1366  */
1367 
1368 /**
1369  * @ingroup linq_op_elem_at_or_def
1370  * @brief Returns nth element in sequence or default value.
1371  *
1372  * Returns the <tt>n</tt>th element in a sequence. If the sequence
1373  * does not have enough elements, a <em>default-initialized</em>
1374  * value is returned instead.
1375  *
1376  * Use like this:
1377  *
1378  * @code
1379  * const int NUMS[] = { 42, 23, 66 };
1380  *
1381  * using namespace coveo::linq;
1382  * auto second = from(NUMS)
1383  * | element_at(1);
1384  * auto fourth = from(NUMS)
1385  * | element_at(3);
1386  * // second == 23
1387  * // fourth == 0
1388  * @endcode
1389  *
1390  * @param n 0-based index of element to return.
1391  * @return (Once applied) <tt>n</tt>th element in sequence or,
1392  * if sequence does not have enough elements, a default value.
1393  */
1394 template<typename = void>
1396  -> detail::element_at_or_default_impl<>
1397 {
1398  return detail::element_at_or_default_impl<>(n);
1399 }
1400 
1401 /**
1402  * @ingroup linq_operators_list
1403  * @defgroup linq_op_except except
1404  * @brief Performs a set difference between two sequences.
1405  *
1406  * The @c except operator returns all elements in the first sequence
1407  * that are not also found in the second sequence (essentially a set
1408  * difference). The elements are returned in the order that they appear
1409  * in the first sequence.
1410  *
1411  * <b>.NET equivalent:</b> Except
1412  */
1413 
1414 /**
1415  * @ingroup linq_op_except
1416  * @brief Performs set difference between two sequences.
1417  *
1418  * Returns a sequence containing all elements from the first source sequence
1419  * that are not also in the second source sequence (essentially a set difference).
1420  * Elements are returned in the order that they appear in the first sequence.
1421  *
1422  * To filter out elements, elements are sorted using <tt>operator&lt;()</tt>.
1423  *
1424  * Use like this:
1425  *
1426  * @code
1427  * const int YES[] = { 42, 23, 66, 11, 7, 67 };
1428  * const int NO[] = { 10, 7, 60, 42, 43, 50 };
1429  *
1430  * using namespace coveo::linq;
1431  * auto seq = from(YES)
1432  * | except(NO);
1433  * // seq = { 23, 66, 11, 67 }
1434  * @endcode
1435  *
1436  * @param seq2 Second source sequence, containing the elements
1437  * to filter out.
1438  * @return (Once applied) Sequence containing elements from first
1439  * source sequence that are not in @c seq2.
1440  */
1441 template<typename Seq2>
1442 auto except(Seq2&& seq2)
1443  -> detail::except_impl<Seq2, detail::less<>>
1444 {
1445  return detail::except_impl<Seq2, detail::less<>>(std::forward<Seq2>(seq2), detail::less<>());
1446 }
1447 
1448 /**
1449  * @ingroup linq_op_except
1450  * @brief Performs set difference between two sequences using predicate.
1451  *
1452  * Returns a sequence containing all elements from the first source sequence
1453  * that are not also in the second source sequence (essentially a set difference).
1454  * Elements are returned in the order that they appear in the first sequence.
1455  *
1456  * To filter out elements, the provided predicate is used to sort the elements.
1457  * The predicate must provide a strict ordering of the elements, like <tt>std::less</tt>.
1458  *
1459  * Use like this:
1460  *
1461  * @code
1462  * const int YES[] = { 42, 23, 66, 11, 7, 67 };
1463  * const int NO[] = { 10, 7, 60, 42, 43, 50 };
1464  *
1465  * using namespace coveo::linq;
1466  * auto seq = from(YES)
1467  * | except(NO, [](int i, int j) { return i > j; });
1468  * // seq = { 23, 66, 11, 67 }
1469  * @endcode
1470  *
1471  * @param seq2 Second source sequence, containing the elements
1472  * to filter out.
1473  * @param pred Predicate used to order elements to filter out.
1474  * @return (Once applied) Sequence containing elements from first
1475  * source sequence that are not in @c seq2.
1476  */
1477 template<typename Seq2, typename Pred>
1478 auto except(Seq2&& seq2, Pred&& pred)
1479  -> detail::except_impl<Seq2, Pred>
1480 {
1481  return detail::except_impl<Seq2, Pred>(std::forward<Seq2>(seq2), std::forward<Pred>(pred));
1482 }
1483 
1484 /**
1485  * @ingroup linq_operators_list
1486  * @defgroup linq_op_first first
1487  * @brief Returns first element in a sequence.
1488  *
1489  * The @c first operator returns the first element in a sequence,
1490  * or the first element to satisfy a predicate. If the sequence does
1491  * not have such an element, an exception is thrown.
1492  *
1493  * This is a @b terminal operator.
1494  *
1495  * <b>.NET equivalent:</b> First
1496  */
1497 
1498 /**
1499  * @ingroup linq_op_first
1500  * @brief Returns first element in sequence.
1501  *
1502  * Returns the first element in a sequence. If the sequence
1503  * does not have elements, <tt>coveo::linq::empty_sequence</tt>
1504  * is thrown.
1505  *
1506  * Use like this:
1507  *
1508  * @code
1509  * const std::vector<int> YES = { 42, 23, 66 };
1510  * const std::vector<int> NAY;
1511  *
1512  * using namespace coveo::linq;
1513  * auto fir1 = from(YES)
1514  * | first();
1515  * // fir1 == 42
1516  * // This throws an exception:
1517  * // auto fir2 = from(NAY)
1518  * // | first();
1519  * @endcode
1520  *
1521  * @return (Once applied) First element in sequence.
1522  * @exception coveo::linq::empty_sequence The sequence does not have elements.
1523  */
1524 template<typename = void>
1525 auto first()
1526  -> detail::first_impl_0<>
1527 {
1528  return detail::first_impl_0<>();
1529 }
1530 
1531 /**
1532  * @ingroup linq_op_first
1533  * @brief Returns first element in sequence that satisfy predicate.
1534  *
1535  * Returns the first element in a sequence for which the given
1536  * predicate returns @c true. If the sequence does not have elements,
1537  * <tt>coveo::linq::empty_sequence</tt> is thrown; if the sequence does
1538  * not contain an element that satisfy the predicate,
1539  * <tt>coveo::linq::out_of_range</tt> is thrown.
1540  *
1541  * Use like this:
1542  *
1543  * @code
1544  * const int NUMS[] = { 42, 23, 66 };
1545  *
1546  * using namespace coveo::linq;
1547  * auto odd = from(NUMS)
1548  * | first([](int i) { return i % 2 != 0; });
1549  * // odd == 23
1550  * // This throws an exception:
1551  * // auto big = from(NUMS)
1552  * // | first([](int i) { return i >= 90; });
1553  * @endcode
1554  *
1555  * @param pred Predicate to satisfy.
1556  * @return (Once applied) First element in sequence for which @c pred returns @c true.
1557  * @exception coveo::linq::empty_sequence The sequence does not have elements.
1558  * @exception coveo::linq::out_of_range The sequence has no element that satisfy @c pred.
1559  */
1560 template<typename Pred>
1561 auto first(const Pred& pred)
1562  -> detail::first_impl_1<Pred>
1563 {
1564  return detail::first_impl_1<Pred>(pred);
1565 }
1566 
1567 /**
1568  * @ingroup linq_operators_list
1569  * @defgroup linq_op_first_or_def first_or_default
1570  * @brief Returns first element in a sequence, or a default value.
1571  *
1572  * The @c first_or_default operator returns the first element in a sequence,
1573  * or the first element to satisfy a predicate. If the sequence does
1574  * not have such an element, a default value is returned.
1575  *
1576  * This is a @b terminal operator.
1577  *
1578  * <b>.NET equivalent:</b> FirstOrDefault
1579  */
1580 
1581 /**
1582  * @ingroup linq_op_first_or_def
1583  * @brief Returns first element in sequence, or default value.
1584  *
1585  * Returns the first element in a sequence. If the sequence
1586  * does not have elements, a <em>default-initialized</em>
1587  * value is returned instead.
1588  *
1589  * Use like this:
1590  *
1591  * @code
1592  * const std::vector<int> YES = { 42, 23, 66 };
1593  * const std::vector<int> NAY;
1594  *
1595  * using namespace coveo::linq;
1596  * auto fir1 = from(YES)
1597  * | first();
1598  * auto fir2 = from(NAY)
1599  * | first();
1600  * // fir1 == 42
1601  * // fir2 == 0
1602  * @endcode
1603  *
1604  * @return (Once applied) First element in sequence, or a default value
1605  * if sequence does not have elements.
1606  */
1607 template<typename = void>
1608 auto first_or_default()
1609  -> detail::first_or_default_impl_0<>
1610 {
1611  return detail::first_or_default_impl_0<>();
1612 }
1613 
1614 /**
1615  * @ingroup linq_op_first_or_def
1616  * @brief Returns first element in sequence that satisfy predicate, or default value.
1617  *
1618  * Returns the first element in a sequence for which the given
1619  * predicate returns @c true. If the sequence does not have elements
1620  * or does not contain an element that satisfy the predicate, a
1621  * <em>default-initialized</em> value is returned instead.
1622  *
1623  * Use like this:
1624  *
1625  * @code
1626  * const int NUMS[] = { 42, 23, 66 };
1627  *
1628  * using namespace coveo::linq;
1629  * auto odd = from(NUMS)
1630  * | first([](int i) { return i % 2 != 0; });
1631  * auto big = from(NUMS)
1632  * | first([](int i) { return i >= 90; });
1633  * // odd == 23
1634  * // big == 0
1635  * @endcode
1636  *
1637  * @param pred Predicate to satisfy.
1638  * @return (Once applied) First element in sequence for which @c pred returns @c true
1639  * or, if no such element exists in sequence, a default value.
1640  */
1641 template<typename Pred>
1642 auto first_or_default(const Pred& pred)
1643  -> detail::first_or_default_impl_1<Pred>
1644 {
1645  return detail::first_or_default_impl_1<Pred>(pred);
1646 }
1647 
1648 /**
1649  * @ingroup linq_operators_list
1650  * @defgroup linq_op_group_by group_by / group_values_by / group_by_and_fold / group_values_by_and_fold
1651  * @brief Groups elements in a sequence according to their keys.
1652  *
1653  * The @c group_by operator (and its siblings) group elements in a sequence according to their keys.
1654  * Keys are extracted from elements using a <em>key selector</em>. Variants of the operator can also
1655  * extract values from elements using a <em>value selector</em>, or modify the resulting sequence using
1656  * a <em>result selector</em>.
1657  *
1658  * <b>.NET equivalent:</b> GroupBy
1659  */
1660 
1661 /**
1662  * @ingroup linq_op_group_by
1663  * @brief Groups elements in sequence according to their keys.
1664  *
1665  * Scans the input sequence and, for each element, fetches a key using
1666  * the provided <em>key selector</em>. Then, creates groups of elements
1667  * that have a common key. The result is a sequence of <tt>pair</tt>s
1668  * whose @c first element is a key and whose @c second element is a sequence
1669  * of elements matching that key. The groups are returned in ascending order
1670  * of key, as determined by <tt>operator&lt;()</tt>.
1671  *
1672  * Use like this:
1673  *
1674  * @code
1675  * const std::vector<std::pair<int, std::string>> DATA = {
1676  * { 42, "Life" },
1677  * { 23, "Hangar" },
1678  * { 42, "Universe" },
1679  * { 66, "Route" },
1680  * { 23, "Jeep" },
1681  * };
1682  *
1683  * using namespace coveo::linq;
1684  * auto groups = from(DATA)
1685  * | group_by([](std::pair<int, std::string> p) { return p.first; });
1686  * auto it = std::begin(groups);
1687  * auto group1 = *it++;
1688  * auto group2 = *it++;
1689  * auto group3 = *it++;
1690  * // group1.first == 23, group1.second == { { 23, "Hangar" }, { 23, "Jeep" } }
1691  * // group2.first == 42, group2.second == { { 42, "Life" }, { 42, "Universe" } }
1692  * // group3.first == 66, group3.second == { { 66, "Route" } }
1693  * // it == std::end(groups)
1694  * @endcode
1695  *
1696  * @param key_sel Key selector, used to extract a key for a sequence element.
1697  * @return (Once applied) Sequence of <tt>pair</tt>s whose @c first element is a
1698  * key and whose @c second element is a sequence of matching elements.
1699  */
1700 template<typename KeySelector>
1702  -> detail::group_by_impl<KeySelector,
1703  detail::identity<>,
1704  detail::pair_of<>,
1705  detail::less<>>
1706 {
1707  return detail::group_by_impl<KeySelector,
1708  detail::identity<>,
1709  detail::pair_of<>,
1710  detail::less<>>(std::forward<KeySelector>(key_sel),
1711  detail::identity<>(),
1712  detail::pair_of<>(),
1713  detail::less<>());
1714 }
1715 
1716 /**
1717  * @ingroup linq_op_group_by
1718  * @brief Groups elements in sequence according to their keys using predicate.
1719  *
1720  * Scans the input sequence and, for each element, fetches a key using
1721  * the provided <em>key selector</em>. Then, creates groups of elements
1722  * that have a common key. The result is a sequence of <tt>pair</tt>s
1723  * whose @c first element is a key and whose @c second element is a sequence
1724  * of elements matching that key. The groups are returned in order of key,
1725  * as determined by the provided predicate. The predicate must provide a
1726  * strict ordering of the keys, like <tt>std::less</tt>.
1727  *
1728  * Use like this:
1729  *
1730  * @code
1731  * const std::vector<std::pair<int, std::string>> DATA = {
1732  * { 42, "Life" },
1733  * { 23, "Hangar" },
1734  * { 42, "Universe" },
1735  * { 66, "Route" },
1736  * { 23, "Jeep" },
1737  * };
1738  *
1739  * using namespace coveo::linq;
1740  * auto groups = from(DATA)
1741  * | group_by([](std::pair<int, std::string> p) { return p.first; },
1742  * [](int i, int j) { return i > j; });
1743  * auto it = std::begin(groups);
1744  * auto group1 = *it++;
1745  * auto group2 = *it++;
1746  * auto group3 = *it++;
1747  * // group1.first == 66, group1.second == { { 66, "Route" } }
1748  * // group2.first == 42, group2.second == { { 42, "Life" }, { 42, "Universe" } }
1749  * // group3.first == 23, group3.second == { { 23, "Hangar" }, { 23, "Jeep" } }
1750  * // it == std::end(groups)
1751  * @endcode
1752  *
1753  * @param key_sel Key selector, used to extract a key for a sequence element.
1754  * @param pred Predicate used to compare the keys.
1755  * @return (Once applied) Sequence of <tt>pair</tt>s whose @c first element is a
1756  * key and whose @c second element is a sequence of matching elements.
1757  */
1758 template<typename KeySelector,
1759  typename Pred>
1761  Pred&& pred)
1762  -> detail::group_by_impl<KeySelector,
1763  detail::identity<>,
1764  detail::pair_of<>,
1765  Pred>
1766 {
1767  return detail::group_by_impl<KeySelector,
1768  detail::identity<>,
1769  detail::pair_of<>,
1770  Pred>(std::forward<KeySelector>(key_sel),
1771  detail::identity<>(),
1772  detail::pair_of<>(),
1773  std::forward<Pred>(pred));
1774 }
1775 
1776 /**
1777  * @ingroup linq_op_group_by
1778  * @brief Groups values in sequence according to their keys.
1779  *
1780  * Scans the input sequence and, for each element, fetches a key using
1781  * the provided <em>key selector</em> and a value using the provided
1782  * <em>value selector</em>. Then, creates groups of values that have
1783  * a common key. The result is a sequence of <tt>pair</tt>s whose @c first
1784  * element is a key and whose @c second element is a sequence of values
1785  * matching that key. The groups are returned in ascending order of key,
1786  * as determined by <tt>operator&lt;()</tt>.
1787  *
1788  * Use like this:
1789  *
1790  * @code
1791  * const std::vector<std::pair<int, std::string>> DATA = {
1792  * { 42, "Life" },
1793  * { 23, "Hangar" },
1794  * { 42, "Universe" },
1795  * { 66, "Route" },
1796  * { 23, "Jeep" },
1797  * };
1798  *
1799  * using namespace coveo::linq;
1800  * auto groups = from(DATA)
1801  * | group_values_by([](std::pair<int, std::string> p) { return p.first; },
1802  * [](std::pair<int, std::string> p) { return p.second; });
1803  * auto it = std::begin(groups);
1804  * auto group1 = *it++;
1805  * auto group2 = *it++;
1806  * auto group3 = *it++;
1807  * // group1.first == 23, group1.second == { "Hangar", "Jeep" }
1808  * // group2.first == 42, group2.second == { "Life", "Universe" }
1809  * // group3.first == 66, group3.second == { "Route" }
1810  * // it == std::end(groups)
1811  * @endcode
1812  *
1813  * @param key_sel Key selector, used to extract a key for a sequence element.
1814  * @param value_sel Value selector, used to extract a value for a sequence element.
1815  * @return (Once applied) Sequence of <tt>pair</tt>s whose @c first element is a
1816  * key and whose @c second element is a sequence of matching values.
1817  */
1818 template<typename KeySelector,
1819  typename ValueSelector>
1822  -> detail::group_by_impl<KeySelector,
1823  ValueSelector,
1824  detail::pair_of<>,
1825  detail::less<>>
1826 {
1827  return detail::group_by_impl<KeySelector,
1828  ValueSelector,
1829  detail::pair_of<>,
1830  detail::less<>>(std::forward<KeySelector>(key_sel),
1831  std::forward<ValueSelector>(value_sel),
1832  detail::pair_of<>(),
1833  detail::less<>());
1834 }
1835 
1836 /**
1837  * @ingroup linq_op_group_by
1838  * @brief Groups values in sequence according to their keys using predicate.
1839  *
1840  * Scans the input sequence and, for each element, fetches a key using
1841  * the provided <em>key selector</em> and a value using the provided
1842  * <em>value selector</em>. Then, creates groups of values that have
1843  * a common key. The result is a sequence of <tt>pair</tt>s whose @c first
1844  * element is a key and whose @c second element is a sequence of values
1845  * matching that key. The groups are returned in order of key, as determined
1846  * by the provided predicate. The predicate must provide a strict ordering
1847  * of the keys, like <tt>std::less</tt>.
1848  *
1849  * Use like this:
1850  *
1851  * @code
1852  * const std::vector<std::pair<int, std::string>> DATA = {
1853  * { 42, "Life" },
1854  * { 23, "Hangar" },
1855  * { 42, "Universe" },
1856  * { 66, "Route" },
1857  * { 23, "Jeep" },
1858  * };
1859  *
1860  * using namespace coveo::linq;
1861  * auto groups = from(DATA)
1862  * | group_values_by([](std::pair<int, std::string> p) { return p.first; },
1863  * [](std::pair<int, std::string> p) { return p.second; },
1864  * [](int i, int j) { return i > j; });
1865  * auto it = std::begin(groups);
1866  * auto group1 = *it++;
1867  * auto group2 = *it++;
1868  * auto group3 = *it++;
1869  * // group1.first == 66, group1.second == { "Route" }
1870  * // group2.first == 42, group2.second == { "Life", "Universe" }
1871  * // group3.first == 23, group3.second == { "Hangar", "Jeep" }
1872  * // it == std::end(groups)
1873  * @endcode
1874  *
1875  * @param key_sel Key selector, used to extract a key for a sequence element.
1876  * @param value_sel Value selector, used to extract a value for a sequence element.
1877  * @param pred Predicate used to compare the keys.
1878  * @return (Once applied) Sequence of <tt>pair</tt>s whose @c first element is a
1879  * key and whose @c second element is a sequence of matching values.
1880  */
1881 template<typename KeySelector,
1882  typename ValueSelector,
1883  typename Pred>
1886  Pred&& pred)
1887  -> detail::group_by_impl<KeySelector,
1888  ValueSelector,
1889  detail::pair_of<>,
1890  Pred>
1891 {
1892  return detail::group_by_impl<KeySelector,
1893  ValueSelector,
1894  detail::pair_of<>,
1895  Pred>(std::forward<KeySelector>(key_sel),
1896  std::forward<ValueSelector>(value_sel),
1897  detail::pair_of<>(),
1898  std::forward<Pred>(pred));
1899 }
1900 
1901 /**
1902  * @ingroup linq_op_group_by
1903  * @brief Groups elements in sequence according to their keys then folds the results.
1904  *
1905  * Scans the input sequence and, for each element, fetches a key using
1906  * the provided <em>key selector</em>. Then, creates groups of elements
1907  * that have a common key and uses the provided <em>result selector</em>
1908  * to convert the groups. The result selector is called with two arguments:
1909  * a key, and a sequence of elements matching that key. The final result is
1910  * a sequence of the values returned by the result selector. The result
1911  * selector is called in ascending order of key, as determined by
1912  * <tt>operator&lt;()</tt>.
1913  *
1914  * Use like this:
1915  *
1916  * @code
1917  * const std::vector<std::pair<int, std::string>> DATA = {
1918  * { 42, "Life" },
1919  * { 23, "Hangar" },
1920  * { 42, "Universe" },
1921  * { 66, "Route" },
1922  * { 23, "Jeep" },
1923  * };
1924  *
1925  * using namespace coveo::linq;
1926  * auto res = from(DATA)
1927  * | group_by_and_fold([](std::pair<int, std::string> p) { return p.first; },
1928  * [](int k, coveo::enumerable<const std::pair<int, std::string>> e) { k + return e.size(); });
1929  * // res == { 25, 44, 67 }
1930  * @endcode
1931  *
1932  * @param key_sel Key selector, used to extract a key for a sequence element.
1933  * @param result_sel Result selector, used to fold groups into final results.
1934  * @return (Once applied) Sequence of values returned by @c result_sel.
1935  */
1936 template<typename KeySelector,
1937  typename ResultSelector>
1940  -> detail::group_by_impl<KeySelector,
1941  detail::identity<>,
1942  ResultSelector,
1943  detail::less<>>
1944 {
1945  return detail::group_by_impl<KeySelector,
1946  detail::identity<>,
1947  ResultSelector,
1948  detail::less<>>(std::forward<KeySelector>(key_sel),
1949  detail::identity<>(),
1950  std::forward<ResultSelector>(result_sel),
1951  detail::less<>());
1952 }
1953 
1954 /**
1955  * @ingroup linq_op_group_by
1956  * @brief Groups elements in sequence according to their keys using predicate, then folds the results.
1957  *
1958  * Scans the input sequence and, for each element, fetches a key using
1959  * the provided <em>key selector</em>. Then, creates groups of elements
1960  * that have a common key and uses the provided <em>result selector</em>
1961  * to convert the groups. The result selector is called with two arguments:
1962  * a key, and a sequence of elements matching that key. The final result is
1963  * a sequence of the values returned by the result selector. The result
1964  * selector is called in order of key, as determined by the provided
1965  * predicate. The predicate must provide a strict ordering of the keys,
1966  * like <tt>std::less</tt>.
1967  *
1968  * Use like this:
1969  *
1970  * @code
1971  * const std::vector<std::pair<int, std::string>> DATA = {
1972  * { 42, "Life" },
1973  * { 23, "Hangar" },
1974  * { 42, "Universe" },
1975  * { 66, "Route" },
1976  * { 23, "Jeep" },
1977  * };
1978  *
1979  * using namespace coveo::linq;
1980  * auto res = from(DATA)
1981  * | group_by_and_fold([](std::pair<int, std::string> p) { return p.first; },
1982  * [](int k, coveo::enumerable<const std::pair<int, std::string>> e) { k + return e.size(); },
1983  * [](int i, int j) { return i > j; });
1984  * // res == { 67, 44, 25 }
1985  * @endcode
1986  *
1987  * @param key_sel Key selector, used to extract a key for a sequence element.
1988  * @param result_sel Result selector, used to fold groups into final results.
1989  * @param pred Predicate used to compare the keys.
1990  * @return (Once applied) Sequence of values returned by @c result_sel.
1991  */
1992 template<typename KeySelector,
1993  typename ResultSelector,
1994  typename Pred>
1997  Pred&& pred)
1998  -> detail::group_by_impl<KeySelector,
1999  detail::identity<>,
2000  ResultSelector,
2001  Pred>
2002 {
2003  return detail::group_by_impl<KeySelector,
2004  detail::identity<>,
2005  ResultSelector,
2006  Pred>(std::forward<KeySelector>(key_sel),
2007  detail::identity<>(),
2008  std::forward<ResultSelector>(result_sel),
2009  std::forward<Pred>(pred));
2010 }
2011 
2012 /**
2013  * @ingroup linq_op_group_by
2014  * @brief Groups values in sequence according to their keys then folds the results.
2015  *
2016  * Scans the input sequence and, for each element, fetches a key using
2017  * the provided <em>key selector</em> and a value using the provided
2018  * <em>value selector</em>. Then, creates groups of values that have
2019  * a common key and uses the provided <em>result selector</em> to convert
2020  * the groups. The result selector is called with two arguments: a key,
2021  * and a sequence of values matching that key. The final result is a
2022  * sequence of the values returned by the result selector. The result
2023  * selector is called in ascending order of key, as determined by
2024  * <tt>operator&lt;()</tt>.
2025  *
2026  * Use like this:
2027  *
2028  * @code
2029  * const std::vector<std::pair<int, std::string>> DATA = {
2030  * { 42, "Life" },
2031  * { 23, "Hangar" },
2032  * { 42, "Universe" },
2033  * { 66, "Route" },
2034  * { 23, "Jeep" },
2035  * };
2036  *
2037  * using namespace coveo::linq;
2038  * auto res = from(DATA)
2039  * | group_values_by_and_fold([](std::pair<int, std::string> p) { return p.first; },
2040  * [](std::pair<int, std::string> p) { return p.second; },
2041  * [](int k, coveo::enumerable<const std::string> e) { k + return e.begin()->size(); });
2042  * // res == { 29, 46, 71 }
2043  * @endcode
2044  *
2045  * @param key_sel Key selector, used to extract a key for a sequence element.
2046  * @param value_sel Value selector, used to extract a value for a sequence element.
2047  * @param result_sel Result selector, used to fold groups into final results.
2048  * @return (Once applied) Sequence of values returned by @c result_sel.
2049  */
2050 template<typename KeySelector,
2051  typename ValueSelector,
2052  typename ResultSelector>
2056  -> detail::group_by_impl<KeySelector,
2057  ValueSelector,
2058  ResultSelector,
2059  detail::less<>>
2060 {
2061  return detail::group_by_impl<KeySelector,
2062  ValueSelector,
2063  ResultSelector,
2064  detail::less<>>(std::forward<KeySelector>(key_sel),
2065  std::forward<ValueSelector>(value_sel),
2066  std::forward<ResultSelector>(result_sel),
2067  detail::less<>());
2068 }
2069 
2070 /**
2071  * @ingroup linq_op_group_by
2072  * @brief Groups values in sequence according to their keys using predicate, then folds the results.
2073  *
2074  * Scans the input sequence and, for each element, fetches a key using
2075  * the provided <em>key selector</em> and a value using the provided
2076  * <em>value selector</em>. Then, creates groups of values that have
2077  * a common key and uses the provided <em>result selector</em> to convert
2078  * the groups. The result selector is called with two arguments: a key,
2079  * and a sequence of values matching that key. The final result is a
2080  * sequence of the values returned by the result selector. The result
2081  * selector is called in order of key, as determined by the provided
2082  * predicate. The predicate must provide a strict ordering of the keys,
2083  * like <tt>std::less</tt>.
2084  *
2085  * Use like this:
2086  *
2087  * @code
2088  * const std::vector<std::pair<int, std::string>> DATA = {
2089  * { 42, "Life" },
2090  * { 23, "Hangar" },
2091  * { 42, "Universe" },
2092  * { 66, "Route" },
2093  * { 23, "Jeep" },
2094  * };
2095  *
2096  * using namespace coveo::linq;
2097  * auto res = from(DATA)
2098  * | group_values_by_and_fold([](std::pair<int, std::string> p) { return p.first; },
2099  * [](std::pair<int, std::string> p) { return p.second; },
2100  * [](int k, coveo::enumerable<const std::string> e) { k + return e.begin()->size(); },
2101  * [](int i, int j) { return i > j; });
2102  * // res == { 71, 46, 29 }
2103  * @endcode
2104  *
2105  * @param key_sel Key selector, used to extract a key for a sequence element.
2106  * @param value_sel Value selector, used to extract a value for a sequence element.
2107  * @param result_sel Result selector, used to fold groups into final results.
2108  * @param pred Predicate used to compare the keys.
2109  * @return (Once applied) Sequence of values returned by @c result_sel.
2110  */
2111 template<typename KeySelector,
2112  typename ValueSelector,
2113  typename ResultSelector,
2114  typename Pred>
2118  Pred&& pred)
2119  -> detail::group_by_impl<KeySelector,
2120  ValueSelector,
2121  ResultSelector,
2122  Pred>
2123 {
2124  return detail::group_by_impl<KeySelector,
2125  ValueSelector,
2126  ResultSelector,
2127  Pred>(std::forward<KeySelector>(key_sel),
2128  std::forward<ValueSelector>(value_sel),
2129  std::forward<ResultSelector>(result_sel),
2130  std::forward<Pred>(pred));
2131 }
2132 
2133 /**
2134  * @ingroup linq_operators_list
2135  * @defgroup linq_op_group_join group_join
2136  * @brief Joins and groups elements in two sequences according to their keys.
2137  *
2138  * The @c group_join operator scans two sequences: an <em>outer sequence</em> and an
2139  * <em>inner sequence</em>. For each element in the sequences, it extracts a key using
2140  * some <em>key selectors</em>. Then, it creates groups of elements from the inner sequence
2141  * and joins them to elements in the outer sequence with matching keys. Finally, a
2142  * <em>result selector</em> is used to fold the groups into the final results.
2143  *
2144  * <b>.NET equivalent:</b> GroupJoin
2145  */
2146 
2147 /**
2148  * @ingroup linq_op_group_join
2149  * @brief Joins and groups elements in two sequences according to their keys.
2150  *
2151  * Extracts keys for the elements of an <em>outer sequence</em> (the one on which
2152  * this operator is applied, e.g. the one passed to <tt>coveo::linq::from()</tt>)
2153  * and the provided <em>inner sequence</em> using the provided <em>key selectors</em>.
2154  * Next, creates groups of elements from the inner sequence with keys matching that
2155  * of the elements in the outer sequence. Finally, the provided <em>result selector</em>
2156  * is used to convert the groups into the final results. The result selector is called
2157  * with two arguments: an element from the outer sequence and a group of elements from
2158  * the inner sequence that share the same key.
2159  *
2160  * In order to match the keys, they are compared using <tt>operator&lt;()</tt>.
2161  *
2162  * Use like this:
2163  *
2164  * @code
2165  * using person_data = std::pair<int, std::string>;
2166  * using person_messages = std::pair<int, std::string>;
2167  *
2168  * const std::vector<person_data> PERSONS = {
2169  * { 1, "John Doe" },
2170  * { 2, "Jane Smith" },
2171  * };
2172  * const std::vector<person_messages> MESSAGES = {
2173  * { 1, "This is a test message" },
2174  * { 2, "Hello Jane!" },
2175  * { 1, "Doctors hate him!" },
2176  * { 1, "Welcome to the company" },
2177  * { 2, "Todo before we leave for vacation" },
2178  * };
2179  *
2180  * using namespace coveo::linq;
2181  * auto seq = from(PERSONS)
2182  * | group_join(MESSAGES,
2183  * [](const person_data& pd) { return pd.first; },
2184  * [](const person_messages& pm) { return pm.first; }
2185  * [](const person_data& pd, const coveo::enumerable<const person_messages>& e) {
2186  * std::string res = pd.second + ": ";
2187  * for (auto&& pm : e) {
2188  * res += pm.second + ", ";
2189  * }
2190  * return res;
2191  * });
2192  * // seq == {
2193  * // "John Doe: This is a test message, Doctors hate him!, Welcome to the company, ",
2194  * // "Jane Smith: Hello Jane!, Todo before we leave for vacation, "
2195  * // }
2196  * @endcode
2197  *
2198  * @param inner_seq Inner sequence to scan to create groups.
2199  * @param outer_key_sel Selector to get keys for elements in the outer sequence.
2200  * @param inner_key_sel Selector to get keys for elements in the inner sequence.
2201  * @param result_sel Result selector used to produce final results.
2202  * @return (Once applied) Sequence of values returned by @c result_sel.
2203  */
2204 template<typename InnerSeq,
2205  typename OuterKeySelector,
2206  typename InnerKeySelector,
2207  typename ResultSelector>
2212  -> detail::group_join_impl<InnerSeq,
2213  OuterKeySelector,
2214  InnerKeySelector,
2215  ResultSelector,
2216  detail::less<>>
2217 {
2218  return detail::group_join_impl<InnerSeq,
2219  OuterKeySelector,
2220  InnerKeySelector,
2221  ResultSelector,
2222  detail::less<>>(std::forward<InnerSeq>(inner_seq),
2223  std::forward<OuterKeySelector>(outer_key_sel),
2224  std::forward<InnerKeySelector>(inner_key_sel),
2225  std::forward<ResultSelector>(result_sel),
2226  detail::less<>());
2227 }
2228 
2229 /**
2230  * @ingroup linq_op_group_join
2231  * @brief Joins and groups elements in two sequences according to their keys using predicate.
2232  *
2233  * Extracts keys for the elements of an <em>outer sequence</em> (the one on which
2234  * this operator is applied, e.g. the one passed to <tt>coveo::linq::from()</tt>)
2235  * and the provided <em>inner sequence</em> using the provided <em>key selectors</em>.
2236  * Next, creates groups of elements from the inner sequence with keys matching that
2237  * of the elements in the outer sequence. Finally, the provided <em>result selector</em>
2238  * is used to convert the groups into the final results. The result selector is called
2239  * with two arguments: an element from the outer sequence and a group of elements from
2240  * the inner sequence that share the same key.
2241  *
2242  * In order to match the keys, they are compared using the provided predicate. The
2243  * predicate must provide a strict ordering of the keys, like <tt>std::less</tt>.
2244  *
2245  * Use like this:
2246  *
2247  * @code
2248  * using person_data = std::pair<int, std::string>;
2249  * using person_messages = std::pair<int, std::string>;
2250  *
2251  * const std::vector<person_data> PERSONS = {
2252  * { 1, "John Doe" },
2253  * { 2, "Jane Smith" },
2254  * };
2255  * const std::vector<person_messages> MESSAGES = {
2256  * { 1, "This is a test message" },
2257  * { 2, "Hello Jane!" },
2258  * { 1, "Doctors hate him!" },
2259  * { 1, "Welcome to the company" },
2260  * { 2, "Todo before we leave for vacation" },
2261  * };
2262  *
2263  * using namespace coveo::linq;
2264  * auto seq = from(PERSONS)
2265  * | group_join(MESSAGES,
2266  * [](const person_data& pd) { return pd.first; },
2267  * [](const person_messages& pm) { return pm.first; }
2268  * [](const person_data& pd, const coveo::enumerable<const person_messages>& e) {
2269  * std::string res = pd.second + ": ";
2270  * for (auto&& pm : e) {
2271  * res += pm.second + ", ";
2272  * }
2273  * return res;
2274  * },
2275  * [](int i, int j) { return i > j; });
2276  * // seq == {
2277  * // "John Doe: This is a test message, Doctors hate him!, Welcome to the company, ",
2278  * // "Jane Smith: Hello Jane!, Todo before we leave for vacation, "
2279  * // }
2280  * @endcode
2281  *
2282  * @param inner_seq Inner sequence to scan to create groups.
2283  * @param outer_key_sel Selector to get keys for elements in the outer sequence.
2284  * @param inner_key_sel Selector to get keys for elements in the inner sequence.
2285  * @param result_sel Result selector used to produce final results.
2286  * @param pred Predicate used to compare keys.
2287  * @return (Once applied) Sequence of values returned by @c result_sel.
2288  */
2289 template<typename InnerSeq,
2290  typename OuterKeySelector,
2291  typename InnerKeySelector,
2292  typename ResultSelector,
2293  typename Pred>
2298  Pred&& pred)
2299  -> detail::group_join_impl<InnerSeq,
2300  OuterKeySelector,
2301  InnerKeySelector,
2302  ResultSelector,
2303  Pred>
2304 {
2305  return detail::group_join_impl<InnerSeq,
2306  OuterKeySelector,
2307  InnerKeySelector,
2308  ResultSelector,
2309  Pred>(std::forward<InnerSeq>(inner_seq),
2310  std::forward<OuterKeySelector>(outer_key_sel),
2311  std::forward<InnerKeySelector>(inner_key_sel),
2312  std::forward<ResultSelector>(result_sel),
2313  std::forward<Pred>(pred));
2314 }
2315 
2316 /**
2317  * @ingroup linq_operators_list
2318  * @defgroup linq_op_intersect intersect
2319  * @brief Performs a set intersection of two sequences.
2320  *
2321  * The @c intersect operator returns all elements in the first sequence
2322  * that are also found in the second sequence (essentially a set intersection).
2323  * The elements are returned in the order that they appear in the first sequence.
2324  *
2325  * <b>.NET equivalent:</b> Intersect
2326  */
2327 
2328 /**
2329  * @ingroup linq_op_intersect
2330  * @brief Performs set intersection of two sequences.
2331  *
2332  * Returns a sequence containing all elements from the first source sequence
2333  * that are also in the second source sequence (essentially a set intersection).
2334  * Elements are returned in the order that they appear in the first sequence.
2335  *
2336  * Elements are found using <tt>operator&lt;()</tt> to compare them.
2337  *
2338  * Use like this:
2339  *
2340  * @code
2341  * const int ONE[] = { 42, 23, 66, 11, 7, 67 };
2342  * const int TWO[] = { 10, 7, 60, 42, 43, 23 };
2343  *
2344  * using namespace coveo::linq;
2345  * auto seq = from(ONE)
2346  * | intersect(TWO);
2347  * // seq = { 42, 23, 7 }
2348  * @endcode
2349  *
2350  * @param seq2 Second source sequence.
2351  * @return (Once applied) Sequence containing elements from first
2352  * source sequence that are also in @c seq2.
2353  */
2354 template<typename Seq2>
2355 auto intersect(Seq2&& seq2)
2356  -> detail::intersect_impl<Seq2, detail::less<>>
2357 {
2358  return detail::intersect_impl<Seq2, detail::less<>>(std::forward<Seq2>(seq2),
2359  detail::less<>());
2360 }
2361 
2362 /**
2363  * @ingroup linq_op_intersect
2364  * @brief Performs set intersection of two sequences using predicate.
2365  *
2366  * Returns a sequence containing all elements from the first source sequence
2367  * that are also in the second source sequence (essentially a set intersection).
2368  * Elements are returned in the order that they appear in the first sequence.
2369  *
2370  * Elements are found using the provided predicate to compare them. The predicate
2371  * must provide a strict ordering of the elements, like <tt>std::less</tt>.
2372  *
2373  * Use like this:
2374  *
2375  * @code
2376  * const int ONE[] = { 42, 23, 66, 11, 7, 67 };
2377  * const int TWO[] = { 10, 7, 60, 42, 43, 23 };
2378  *
2379  * using namespace coveo::linq;
2380  * auto seq = from(ONE)
2381  * | intersect(TWO, [](int i, int j) { return i > j; });
2382  * // seq = { 42, 23, 7 }
2383  * @endcode
2384  *
2385  * @param seq2 Second source sequence.
2386  * @param pred Predicate used to compare the elements.
2387  * @return (Once applied) Sequence containing elements from first
2388  * source sequence that are also in @c seq2.
2389  */
2390 template<typename Seq2, typename Pred>
2391 auto intersect(Seq2&& seq2, Pred&& pred)
2392  -> detail::intersect_impl<Seq2, Pred>
2393 {
2394  return detail::intersect_impl<Seq2, Pred>(std::forward<Seq2>(seq2),
2395  std::forward<Pred>(pred));
2396 }
2397 
2398 /**
2399  * @ingroup linq_operators_list
2400  * @defgroup linq_op_join join
2401  * @brief Joins elements in two sequences according to their keys.
2402  *
2403  * The @c join operator scans two sequences: an <em>outer sequence</em> and an
2404  * <em>inner sequence</em>. For each element in the sequences, it extracts a key using
2405  * some <em>key selectors</em>. Then, it joins elements from the inner sequence to
2406  * elements in the outer sequence with matching keys. Finally, a <em>result selector</em>
2407  * is used to fold the elements into the final results. (This operator is similar to
2408  * a database JOIN.)
2409  *
2410  * <b>.NET equivalent:</b> Join
2411  */
2412 
2413 /**
2414  * @ingroup linq_op_join
2415  * @brief Joins elements in two sequences according to their keys.
2416  *
2417  * Extracts keys for the elements of an <em>outer sequence</em> (the one on which
2418  * this operator is applied, e.g. the one passed to <tt>coveo::linq::from()</tt>)
2419  * and the provided <em>inner sequence</em> using the provided <em>key selectors</em>.
2420  * Next, joins elements from the inner sequence with elements in the outer sequence
2421  * with matching keys. Finally, the provided <em>result selector</em> is used to convert
2422  * the elements into the final results. The result selector is called with two arguments:
2423  * an element from the outer sequence and an element from the inner sequence that share
2424  * the same key.
2425  *
2426  * In order to match the keys, they are compared using <tt>operator&lt;()</tt>.
2427  *
2428  * Use like this:
2429  *
2430  * @code
2431  * using person_data = std::pair<int, std::string>;
2432  * using person_messages = std::pair<int, std::string>;
2433  *
2434  * const std::vector<person_data> PERSONS = {
2435  * { 1, "John Doe" },
2436  * { 2, "Jane Smith" },
2437  * };
2438  * const std::vector<person_messages> MESSAGES = {
2439  * { 1, "This is a test message" },
2440  * { 2, "Hello Jane!" },
2441  * { 1, "Doctors hate him!" },
2442  * { 1, "Welcome to the company" },
2443  * { 2, "Todo before we leave for vacation" },
2444  * };
2445  *
2446  * using namespace coveo::linq;
2447  * auto seq = from(PERSONS)
2448  * | join(MESSAGES,
2449  * [](const person_data& pd) { return pd.first; },
2450  * [](const person_messages& pm) { return pm.first; }
2451  * [](const person_data& pd, const person_messages& pm) {
2452  * return pd.second + ": " + pm.second;
2453  * });
2454  * // seq == {
2455  * // "John Doe: This is a test message",
2456  * // "John Doe: Doctors hate him!",
2457  * // "John Doe: Welcome to the company",
2458  * // "Jane Smith: Hello Jane!",
2459  * // "Jane Smith: Todo before we leave for vacation"
2460  * // }
2461  * @endcode
2462  *
2463  * @param inner_seq Inner sequence to scan.
2464  * @param outer_key_sel Selector to get keys for elements in the outer sequence.
2465  * @param inner_key_sel Selector to get keys for elements in the inner sequence.
2466  * @param result_sel Result selector used to produce final results.
2467  * @return (Once applied) Sequence of values returned by @c result_sel.
2468  */
2469 template<typename InnerSeq,
2470  typename OuterKeySelector,
2471  typename InnerKeySelector,
2472  typename ResultSelector>
2473 auto join(InnerSeq&& inner_seq,
2477  -> detail::join_impl<InnerSeq,
2478  OuterKeySelector,
2479  InnerKeySelector,
2480  ResultSelector,
2481  detail::less<>>
2482 {
2483  return detail::join_impl<InnerSeq,
2484  OuterKeySelector,
2485  InnerKeySelector,
2486  ResultSelector,
2487  detail::less<>>(std::forward<InnerSeq>(inner_seq),
2488  std::forward<OuterKeySelector>(outer_key_sel),
2489  std::forward<InnerKeySelector>(inner_key_sel),
2490  std::forward<ResultSelector>(result_sel),
2491  detail::less<>());
2492 }
2493 
2494 /**
2495  * @ingroup linq_op_join
2496  * @brief Joins elements in two sequences according to their keys using predicate.
2497  *
2498  * Extracts keys for the elements of an <em>outer sequence</em> (the one on which
2499  * this operator is applied, e.g. the one passed to <tt>coveo::linq::from()</tt>)
2500  * and the provided <em>inner sequence</em> using the provided <em>key selectors</em>.
2501  * Next, joins elements from the inner sequence with elements in the outer sequence
2502  * with matching keys. Finally, the provided <em>result selector</em> is used to convert
2503  * the elements into the final results. The result selector is called with two arguments:
2504  * an element from the outer sequence and an element from the inner sequence that share
2505  * the same key.
2506  *
2507  * In order to match the keys, they are compared using the provided predicate. The
2508  * predicate must provide a strict ordering of the keys, like <tt>std::less</tt>.
2509  *
2510  * Use like this:
2511  *
2512  * @code
2513  * using person_data = std::pair<int, std::string>;
2514  * using person_messages = std::pair<int, std::string>;
2515  *
2516  * const std::vector<person_data> PERSONS = {
2517  * { 1, "John Doe" },
2518  * { 2, "Jane Smith" },
2519  * };
2520  * const std::vector<person_messages> MESSAGES = {
2521  * { 1, "This is a test message" },
2522  * { 2, "Hello Jane!" },
2523  * { 1, "Doctors hate him!" },
2524  * { 1, "Welcome to the company" },
2525  * { 2, "Todo before we leave for vacation" },
2526  * };
2527  *
2528  * using namespace coveo::linq;
2529  * auto seq = from(PERSONS)
2530  * | join(MESSAGES,
2531  * [](const person_data& pd) { return pd.first; },
2532  * [](const person_messages& pm) { return pm.first; }
2533  * [](const person_data& pd, const person_messages& pm) {
2534  * return pd.second + ": " + pm.second;
2535  * },
2536  * [](int i, int j) { return i > j; });
2537  * // seq == {
2538  * // "John Doe: This is a test message",
2539  * // "John Doe: Doctors hate him!",
2540  * // "John Doe: Welcome to the company",
2541  * // "Jane Smith: Hello Jane!",
2542  * // "Jane Smith: Todo before we leave for vacation"
2543  * // }
2544  * @endcode
2545  *
2546  * @param inner_seq Inner sequence to scan.
2547  * @param outer_key_sel Selector to get keys for elements in the outer sequence.
2548  * @param inner_key_sel Selector to get keys for elements in the inner sequence.
2549  * @param result_sel Result selector used to produce final results.
2550  * @param pred Predicate used to compare the keys.
2551  * @return (Once applied) Sequence of values returned by @c result_sel.
2552  */
2553 template<typename InnerSeq,
2554  typename OuterKeySelector,
2555  typename InnerKeySelector,
2556  typename ResultSelector,
2557  typename Pred>
2558 auto join(InnerSeq&& inner_seq,
2562  Pred&& pred)
2563  -> detail::join_impl<InnerSeq,
2564  OuterKeySelector,
2565  InnerKeySelector,
2566  ResultSelector,
2567  Pred>
2568 {
2569  return detail::join_impl<InnerSeq,
2570  OuterKeySelector,
2571  InnerKeySelector,
2572  ResultSelector,
2573  Pred>(std::forward<InnerSeq>(inner_seq),
2574  std::forward<OuterKeySelector>(outer_key_sel),
2575  std::forward<InnerKeySelector>(inner_key_sel),
2576  std::forward<ResultSelector>(result_sel),
2577  std::forward<Pred>(pred));
2578 }
2579 
2580 /**
2581  * @ingroup linq_operators_list
2582  * @defgroup linq_op_last last
2583  * @brief Returns last element in a sequence.
2584  *
2585  * The @c last operator returns the last element in a sequence,
2586  * or the last element to satisfy a predicate. If the sequence does
2587  * not have such an element, an exception is thrown.
2588  *
2589  * This is a @b terminal operator.
2590  *
2591  * <b>.NET equivalent:</b> Last
2592  */
2593 
2594 /**
2595  * @ingroup linq_op_last
2596  * @brief Returns last element in sequence.
2597  *
2598  * Returns the last element in a sequence. If the sequence
2599  * does not have elements, <tt>coveo::linq::empty_sequence</tt>
2600  * is thrown.
2601  *
2602  * Use like this:
2603  *
2604  * @code
2605  * const std::vector<int> YES = { 42, 23, 66 };
2606  * const std::vector<int> NAY;
2607  *
2608  * using namespace coveo::linq;
2609  * auto las1 = from(YES)
2610  * | last();
2611  * // las1 == 66
2612  * // This throws an exception:
2613  * // auto las2 = from(NAY)
2614  * // | last();
2615  * @endcode
2616  *
2617  * @return (Once applied) Last element in sequence.
2618  * @exception coveo::linq::empty_sequence The sequence does not have elements.
2619  */
2620 template<typename = void>
2621 auto last()
2622  -> detail::last_impl_0<>
2623 {
2624  return detail::last_impl_0<>();
2625 }
2626 
2627 /**
2628  * @ingroup linq_op_last
2629  * @brief Returns last element in sequence that satisfy predicate.
2630  *
2631  * Returns the last element in a sequence for which the given
2632  * predicate returns @c true. If the sequence does not have elements,
2633  * <tt>coveo::linq::empty_sequence</tt> is thrown; if the sequence does
2634  * not contain an element that satisfy the predicate,
2635  * <tt>coveo::linq::out_of_range</tt> is thrown.
2636  *
2637  * Use like this:
2638  *
2639  * @code
2640  * const int NUMS[] = { 42, 23, 66 };
2641  *
2642  * using namespace coveo::linq;
2643  * auto even = from(NUMS)
2644  * | last([](int i) { return i % 2 == 0; });
2645  * // even == 66
2646  * // This throws an exception:
2647  * // auto big = from(NUMS)
2648  * // | last([](int i) { return i >= 90; });
2649  * @endcode
2650  *
2651  * @param pred Predicate to satisfy.
2652  * @return (Once applied) Last element in sequence for which @c pred returns @c true.
2653  * @exception coveo::linq::empty_sequence The sequence does not have elements.
2654  * @exception coveo::linq::out_of_range The sequence has no element that satisfy @c pred.
2655  */
2656 template<typename Pred>
2657 auto last(const Pred& pred)
2658  -> detail::last_impl_1<Pred>
2659 {
2660  return detail::last_impl_1<Pred>(pred);
2661 }
2662 
2663 /**
2664  * @ingroup linq_operators_list
2665  * @defgroup linq_op_last_or_def last_or_default
2666  * @brief Returns last element in a sequence, or a default value.
2667  *
2668  * The @c last_or_default operator returns the last element in a sequence,
2669  * or the last element to satisfy a predicate. If the sequence does
2670  * not have such an element, a default value is returned.
2671  *
2672  * This is a @b terminal operator.
2673  *
2674  * <b>.NET equivalent:</b> LastOrDefault
2675  */
2676 
2677 /**
2678  * @ingroup linq_op_last_or_def
2679  * @brief Returns last element in sequence, or default value.
2680  *
2681  * Returns the last element in a sequence. If the sequence
2682  * does not have elements, a <em>default-initialized</em>
2683  * value is returned instead.
2684  *
2685  * Use like this:
2686  *
2687  * @code
2688  * const std::vector<int> YES = { 42, 23, 66 };
2689  * const std::vector<int> NAY;
2690  *
2691  * using namespace coveo::linq;
2692  * auto las1 = from(YES)
2693  * | last();
2694  * auto las2 = from(NAY)
2695  * | last();
2696  * // las1 == 66
2697  * // las2 == 0
2698  * @endcode
2699  *
2700  * @return (Once applied) Last element in sequence, or a default value
2701  * if sequence does not have elements.
2702  */
2703 template<typename = void>
2704 auto last_or_default()
2705  -> detail::last_or_default_impl_0<>
2706 {
2707  return detail::last_or_default_impl_0<>();
2708 }
2709 
2710 /**
2711  * @ingroup linq_op_last_or_def
2712  * @brief Returns last element in sequence that satisfy predicate, or default value.
2713  *
2714  * Returns the last element in a sequence for which the given
2715  * predicate returns @c true. If the sequence does not have elements
2716  * or does not contain an element that satisfy the predicate, a
2717  * <em>default-initialized</em> value is returned instead.
2718  *
2719  * Use like this:
2720  *
2721  * @code
2722  * const int NUMS[] = { 42, 23, 66 };
2723  *
2724  * using namespace coveo::linq;
2725  * auto even = from(NUMS)
2726  * | last([](int i) { return i % 2 == 0; });
2727  * auto big = from(NUMS)
2728  * | last([](int i) { return i >= 90; });
2729  * // even == 66
2730  * // big == 0
2731  * @endcode
2732  *
2733  * @param pred Predicate to satisfy.
2734  * @return (Once applied) Last element in sequence for which @c pred returns @c true
2735  * or, if no such element exists in sequence, a default value.
2736  */
2737 template<typename Pred>
2738 auto last_or_default(const Pred& pred)
2739  -> detail::last_or_default_impl_1<Pred>
2740 {
2741  return detail::last_or_default_impl_1<Pred>(pred);
2742 }
2743 
2744 /**
2745  * @ingroup linq_operators_list
2746  * @defgroup linq_op_max max
2747  * @brief Returns maximum element in a sequence.
2748  *
2749  * The @c max operator returns the maximum element in a sequence. If the
2750  * sequence does not have elements, an exception is thrown.
2751  *
2752  * This is a @b terminal operator.
2753  *
2754  * <b>.NET equivalent:</b> Max
2755  */
2756 
2757 /**
2758  * @ingroup linq_op_max
2759  * @brief Returns maximum element in sequence.
2760  *
2761  * Returns the maximum element in a sequence. If the sequence
2762  * does not have elements, <tt>coveo::linq::empty_sequence</tt>
2763  * is thrown.
2764  *
2765  * Use like this:
2766  *
2767  * @code
2768  * const std::vector<int> YES = { 42, 23, 66, 11, 7 };
2769  * const std::vector<int> NAY;
2770  *
2771  * using namespace coveo::linq;
2772  * auto max1 = from(YES)
2773  * | max();
2774  * // max1 == 66
2775  * // This throws an exception:
2776  * // auto max2 = from(NAY)
2777  * // | max();
2778  * @endcode
2779  *
2780  * @return (Once applied) Maximum element in sequence.
2781  * @exception coveo::linq::empty_sequence The sequence does not have elements.
2782  */
2783 template<typename = void>
2784 auto max()
2785  -> detail::max_impl_0<>
2786 {
2787  return detail::max_impl_0<>();
2788 }
2789 
2790 /**
2791  * @ingroup linq_op_max
2792  * @brief Returns maximum projected value in sequence.
2793  *
2794  * Returns the maximum value in a sequence by projecting each element
2795  * to a different value using the provided <em>selector</em>. If the
2796  * sequence does not have elements, <tt>coveo::linq::empty_sequence</tt>
2797  * is thrown.
2798  *
2799  * Use like this:
2800  *
2801  * @code
2802  * const std::vector<int> YES = { 42, 23, 66, 11, 7 };
2803  * const std::vector<int> NAY;
2804  *
2805  * using namespace coveo::linq;
2806  * auto max1 = from(YES)
2807  * | max([](int i) { return -i; });
2808  * // max1 == -7
2809  * // This throws an exception:
2810  * // auto max2 = from(NAY)
2811  * // | max([](int i) { return -i; });
2812  * @endcode
2813  *
2814  * @param sel Selector called to project each element into a different value.
2815  * @return (Once applied) Maximum projected value in sequence.
2816  * @exception coveo::linq::empty_sequence The sequence does not have elements.
2817  */
2818 template<typename Selector>
2819 auto max(const Selector& sel)
2820  -> detail::max_impl_1<Selector>
2821 {
2822  return detail::max_impl_1<Selector>(sel);
2823 }
2824 
2825 /**
2826  * @ingroup linq_operators_list
2827  * @defgroup linq_op_min min
2828  * @brief Returns minimum element in a sequence.
2829  *
2830  * The @c min operator returns the minimum element in a sequence. If the
2831  * sequence does not have elements, an exception is thrown.
2832  *
2833  * This is a @b terminal operator.
2834  *
2835  * <b>.NET equivalent:</b> Min
2836  */
2837 
2838 /**
2839  * @ingroup linq_op_min
2840  * @brief Returns minimum element in sequence.
2841  *
2842  * Returns the minimum element in a sequence. If the sequence
2843  * does not have elements, <tt>coveo::linq::empty_sequence</tt>
2844  * is thrown.
2845  *
2846  * Use like this:
2847  *
2848  * @code
2849  * const std::vector<int> YES = { 42, 23, 66, 11, 7 };
2850  * const std::vector<int> NAY;
2851  *
2852  * using namespace coveo::linq;
2853  * auto min1 = from(YES)
2854  * | min();
2855  * // min1 == 7
2856  * // This throws an exception:
2857  * // auto min2 = from(NAY)
2858  * // | min();
2859  * @endcode
2860  *
2861  * @return (Once applied) Minimum element in sequence.
2862  * @exception coveo::linq::empty_sequence The sequence does not have elements.
2863  */
2864 template<typename = void>
2865 auto min()
2866  -> detail::min_impl_0<>
2867 {
2868  return detail::min_impl_0<>();
2869 }
2870 
2871 /**
2872  * @ingroup linq_op_min
2873  * @brief Returns minimum projected value in sequence.
2874  *
2875  * Returns the minimum value in a sequence by projecting each element
2876  * to a different value using the provided <em>selector</em>. If the
2877  * sequence does not have elements, <tt>coveo::linq::empty_sequence</tt>
2878  * is thrown.
2879  *
2880  * Use like this:
2881  *
2882  * @code
2883  * const std::vector<int> YES = { 42, 23, 66, 11, 7 };
2884  * const std::vector<int> NAY;
2885  *
2886  * using namespace coveo::linq;
2887  * auto min1 = from(YES)
2888  * | min([](int i) { return -i; });
2889  * // min1 == -66
2890  * // This throws an exception:
2891  * // auto min2 = from(NAY)
2892  * // | min([](int i) { return -i; });
2893  * @endcode
2894  *
2895  * @param sel Selector called to project each element into a different value.
2896  * @return (Once applied) Minimum projected value in sequence.
2897  * @exception coveo::linq::empty_sequence The sequence does not have elements.
2898  */
2899 template<typename Selector>
2900 auto min(const Selector& sel)
2901  -> detail::min_impl_1<Selector>
2902 {
2903  return detail::min_impl_1<Selector>(sel);
2904 }
2905 
2906 /**
2907  * @ingroup linq_operators_list
2908  * @defgroup linq_op_none none
2909  * @brief Checks if no element in a sequence satisfy a predicate.
2910  *
2911  * The @c none operator scans a sequence and validates that none of its elements
2912  * satisfy a given @e predicate.
2913  *
2914  * This is a @b terminal operator.
2915  *
2916  * <b>.NET equivalent:</b> <em>n/a</em>
2917  */
2918 
2919 /**
2920  * @ingroup linq_op_none
2921  * @brief Checks elements in a sequence against a predicate.
2922  *
2923  * Scans a sequence and calls a @e predicate with each element. The predicate
2924  * must return @c true if the element satisfies the predicate. The final result
2925  * will indicate if no elements satisfy the predicate.
2926  *
2927  * Works on empty sequences (returns @c true in such a case).
2928  *
2929  * Use like this:
2930  *
2931  * @code
2932  * const int NUMS = { 42, 23, 66 };
2933  *
2934  * using namespace coveo::linq;
2935  * bool no_big = from(NUMS)
2936  * | none([](int i) { return i >= 90; });
2937  * bool no_odd = from(NUMS)
2938  * | none([](int i) { return i % 2 != 0; });
2939  * // no_big == true
2940  * // no_odd == false
2941  * @endcode
2942  *
2943  * @param pred Predicate to satisfy.
2944  * @return (Once applied) @c true if no element in sequence satisfy @c pred.
2945  */
2946 template<typename Pred>
2947 auto none(const Pred& pred)
2948  -> detail::none_impl<Pred>
2949 {
2950  return detail::none_impl<Pred>(pred);
2951 }
2952 
2953 /**
2954  * @ingroup linq_operators_list
2955  * @defgroup linq_op_order_by order_by / order_by_descending / then_by / then_by_descending
2956  * @brief Orders elements in a sequence.
2957  *
2958  * The @c order_by operator (and its siblings) extract keys from each element in a sequence,
2959  * then orders those elements according to those keys. Depending on the operator used, the
2960  * ordering will be ascending or descending. If multiple operators are chained (using
2961  * <tt>coveo::linq::then_by()</tt>), elements will be ordered according to the first key
2962  * extracted and elements with equivalent keys will be further ordered by the other keys.
2963  *
2964  * <b>.NET equivalent:</b> OrderBy / OrderByDescending / ThenBy / ThenByDescending
2965  */
2966 
2967 /**
2968  * @ingroup linq_op_order_by
2969  * @brief Orders elements in sequence by ascending key.
2970  *
2971  * For each element in the input sequence, extracts a key using the
2972  * provided <em>key selector</em>. Then, returns a sequence containing
2973  * the same elements, ordered according to the keys in ascending order.
2974  *
2975  * Keys are compared using <tt>operator&lt;()</tt>.
2976  *
2977  * Use like this:
2978  *
2979  * @code
2980  * using coord = std::tuple<int, int, int>;
2981  * const std::vector<coord> COORDS = {
2982  * { 10, 2, -4 },
2983  * { 2, 20, 8 },
2984  * { -1, 1, 12 },
2985  * { 14, 29, 1 },
2986  * { 3, 3, 3 },
2987  * };
2988  *
2989  * using namespace coveo::linq;
2990  * auto seq = from(COORDS)
2991  * | order_by([](const coord& c) { return c.x; });
2992  * // seq == {
2993  * // { -1, 1, 12 },
2994  * // { 2, 20, 8 },
2995  * // { 3, 3, 3 },
2996  * // { 10, 2, -4 },
2997  * // { 14, 29, 1 }
2998  * // }
2999  * @endcode
3000  *
3001  * @param key_sel Key selector, used to extract a key for a sequence element.
3002  * @return (Once applied) Sequence of elements ordered by ascending key.
3003  */
3004 template<typename KeySelector>
3006  -> detail::order_by_impl<detail::order_by_comparator<KeySelector, detail::less<>, false>>
3007 {
3008  typedef detail::order_by_comparator<KeySelector, detail::less<>, false> comparator;
3009  return detail::order_by_impl<comparator>(detail::make_unique<comparator>(std::forward<KeySelector>(key_sel), detail::less<>()));
3010 }
3011 
3012 /**
3013  * @ingroup linq_op_order_by
3014  * @brief Orders elements in sequence by ascending key using predicate.
3015  *
3016  * For each element in the input sequence, extracts a key using the
3017  * provided <em>key selector</em>. Then, returns a sequence containing
3018  * the same elements, ordered according to the keys in ascending order.
3019  *
3020  * Keys are compared using the provided predicate. The predicate must
3021  * provide a strict ordering of the keys, like <tt>std::less</tt>.
3022  *
3023  * Use like this:
3024  *
3025  * @code
3026  * using coord = std::tuple<int, int, int>;
3027  * const std::vector<coord> COORDS = {
3028  * { 10, 2, -4 },
3029  * { 2, 20, 8 },
3030  * { -1, 1, 12 },
3031  * { 14, 29, 1 },
3032  * { 3, 3, 3 },
3033  * };
3034  *
3035  * using namespace coveo::linq;
3036  * auto seq = from(COORDS)
3037  * | order_by([](const coord& c) { return c.x; },
3038  * [](int i, int j) { return i < j; });
3039  * // seq == {
3040  * // { -1, 1, 12 },
3041  * // { 2, 20, 8 },
3042  * // { 3, 3, 3 },
3043  * // { 10, 2, -4 },
3044  * // { 14, 29, 1 }
3045  * // }
3046  * @endcode
3047  *
3048  * @param key_sel Key selector, used to extract a key for a sequence element.
3049  * @param pred Predicate used to compare the keys.
3050  * @return (Once applied) Sequence of elements ordered by ascending key.
3051  */
3052 template<typename KeySelector, typename Pred>
3054  -> detail::order_by_impl<detail::order_by_comparator<KeySelector, Pred, false>>
3055 {
3056  typedef detail::order_by_comparator<KeySelector, Pred, false> comparator;
3057  return detail::order_by_impl<comparator>(detail::make_unique<comparator>(std::forward<KeySelector>(key_sel), std::forward<Pred>(pred)));
3058 }
3059 
3060 /**
3061  * @ingroup linq_op_order_by
3062  * @brief Orders elements in sequence by descending key.
3063  *
3064  * For each element in the input sequence, extracts a key using the
3065  * provided <em>key selector</em>. Then, returns a sequence containing
3066  * the same elements, ordered according to the keys in descending order.
3067  *
3068  * Keys are compared using <tt>operator&lt;()</tt>, but the result is reversed
3069  * to produce descending order.
3070  *
3071  * Use like this:
3072  *
3073  * @code
3074  * using coord = std::tuple<int, int, int>;
3075  * const std::vector<coord> COORDS = {
3076  * { 10, 2, -4 },
3077  * { 2, 20, 8 },
3078  * { -1, 1, 12 },
3079  * { 14, 29, 1 },
3080  * { 3, 3, 3 },
3081  * };
3082  *
3083  * using namespace coveo::linq;
3084  * auto seq = from(COORDS)
3085  * | order_by_descending([](const coord& c) { return c.x; });
3086  * // seq == {
3087  * // { 14, 29, 1 }
3088  * // { 10, 2, -4 },
3089  * // { 3, 3, 3 },
3090  * // { 2, 20, 8 },
3091  * // { -1, 1, 12 },
3092  * // }
3093  * @endcode
3094  *
3095  * @param key_sel Key selector, used to extract a key for a sequence element.
3096  * @return (Once applied) Sequence of elements ordered by descending key.
3097  */
3098 template<typename KeySelector>
3100  -> detail::order_by_impl<detail::order_by_comparator<KeySelector, detail::less<>, true>>
3101 {
3102  typedef detail::order_by_comparator<KeySelector, detail::less<>, true> comparator;
3103  return detail::order_by_impl<comparator>(detail::make_unique<comparator>(std::forward<KeySelector>(key_sel), detail::less<>()));
3104 }
3105 
3106 /**
3107  * @ingroup linq_op_order_by
3108  * @brief Orders elements in sequence by descending key using predicate.
3109  *
3110  * For each element in the input sequence, extracts a key using the
3111  * provided <em>key selector</em>. Then, returns a sequence containing
3112  * the same elements, ordered according to the keys in descending order.
3113  *
3114  * Keys are compared using the provided predicate, but the result is reversed
3115  * to produce descending order. The predicate must provide a strict ordering
3116  * of the keys, like <tt>std::less</tt>.
3117  *
3118  * Use like this:
3119  *
3120  * @code
3121  * using coord = std::tuple<int, int, int>;
3122  * const std::vector<coord> COORDS = {
3123  * { 10, 2, -4 },
3124  * { 2, 20, 8 },
3125  * { -1, 1, 12 },
3126  * { 14, 29, 1 },
3127  * { 3, 3, 3 },
3128  * };
3129  *
3130  * using namespace coveo::linq;
3131  * auto seq = from(COORDS)
3132  * | order_by_descending([](const coord& c) { return c.x; },
3133  * [](int i, int j) { return i < j; });
3134  * // seq == {
3135  * // { 14, 29, 1 }
3136  * // { 10, 2, -4 },
3137  * // { 3, 3, 3 },
3138  * // { 2, 20, 8 },
3139  * // { -1, 1, 12 },
3140  * // }
3141  * @endcode
3142  *
3143  * @param key_sel Key selector, used to extract a key for a sequence element.
3144  * @param pred Predicate used to compare the keys.
3145  * @return (Once applied) Sequence of elements ordered by descending key.
3146  */
3147 template<typename KeySelector, typename Pred>
3149  -> detail::order_by_impl<detail::order_by_comparator<KeySelector, Pred, true>>
3150 {
3151  typedef detail::order_by_comparator<KeySelector, Pred, true> comparator;
3152  return detail::order_by_impl<comparator>(detail::make_unique<comparator>(std::forward<KeySelector>(key_sel), std::forward<Pred>(pred)));
3153 }
3154 
3155 /**
3156  * @ingroup linq_op_order_by
3157  * @brief Further orders elements in sequence by ascending key.
3158  *
3159  * Further orders a sequence previously ordered via <tt>coveo::linq::order_by()</tt>
3160  * or similar operator. Elements that were previously considered equivalent will
3161  * be further ordered by ascending order of keys as extracted by the provided
3162  * <em>key selector</em>.
3163  *
3164  * Keys are compared using <tt>operator&lt;()</tt>.
3165  *
3166  * Use like this:
3167  *
3168  * @code
3169  * using coord = std::tuple<int, int, int>;
3170  * const std::vector<coord> COORDS = {
3171  * { 2, 2, -4 },
3172  * { 2, 20, 8 },
3173  * { -1, 1, 12 },
3174  * { 3, 29, 1 },
3175  * { 3, 3, 3 },
3176  * };
3177  *
3178  * using namespace coveo::linq;
3179  * auto seq = from(COORDS)
3180  * | order_by([](const coord& c) { return c.x; })
3181  * | then_by([](const coord& c) { return c.y; });
3182  * // seq == {
3183  * // { -1, 1, 12 },
3184  * // { 2, 2, -4 },
3185  * // { 2, 20, 8 },
3186  * // { 3, 3, 3 },
3187  * // { 3, 29, 1 }
3188  * // }
3189  * @endcode
3190  *
3191  * @param key_sel Key selector, used to extract a key for a sequence element.
3192  * @return (Once applied) Sequence of elements further ordered by ascending key.
3193  */
3194 template<typename KeySelector>
3195 auto then_by(KeySelector&& key_sel)
3196  -> decltype(order_by(std::forward<KeySelector>(key_sel)))
3197 {
3198  return order_by(std::forward<KeySelector>(key_sel));
3199 }
3200 
3201 /**
3202  * @ingroup linq_op_order_by
3203  * @brief Further orders elements in sequence by ascending key using predicate.
3204  *
3205  * Further orders a sequence previously ordered via <tt>coveo::linq::order_by()</tt>
3206  * or similar operator. Elements that were previously considered equivalent will
3207  * be further ordered by ascending order of keys as extracted by the provided
3208  * <em>key selector</em>.
3209  *
3210  * Keys are compared using the provided predicate. The predicate must
3211  * provide a strict ordering of the keys, like <tt>std::less</tt>.
3212  *
3213  * Use like this:
3214  *
3215  * @code
3216  * using coord = std::tuple<int, int, int>;
3217  * const std::vector<coord> COORDS = {
3218  * { 2, 2, -4 },
3219  * { 2, 20, 8 },
3220  * { -1, 1, 12 },
3221  * { 3, 29, 1 },
3222  * { 3, 3, 3 },
3223  * };
3224  *
3225  * using namespace coveo::linq;
3226  * auto seq = from(COORDS)
3227  * | order_by([](const coord& c) { return c.x; },
3228  * [](int i, int j) { return i < j; })
3229  * | then_by([](const coord& c) { return c.y; },
3230  * [](int i, int j) { return i < j; });
3231  * // seq == {
3232  * // { -1, 1, 12 },
3233  * // { 2, 2, -4 },
3234  * // { 2, 20, 8 },
3235  * // { 3, 3, 3 },
3236  * // { 3, 29, 1 }
3237  * // }
3238  * @endcode
3239  *
3240  * @param key_sel Key selector, used to extract a key for a sequence element.
3241  * @param pred Predicate used to compare the keys.
3242  * @return (Once applied) Sequence of elements further ordered by ascending key.
3243  */
3244 template<typename KeySelector, typename Pred>
3245 auto then_by(KeySelector&& key_sel, Pred&& pred)
3246  -> decltype(order_by(std::forward<KeySelector>(key_sel), std::forward<Pred>(pred)))
3247 {
3248  return order_by(std::forward<KeySelector>(key_sel), std::forward<Pred>(pred));
3249 }
3250 
3251 /**
3252  * @ingroup linq_op_order_by
3253  * @brief Further orders elements in sequence by descending key.
3254  *
3255  * Further orders a sequence previously ordered via <tt>coveo::linq::order_by()</tt>
3256  * or similar operator. Elements that were previously considered equivalent will
3257  * be further ordered by descending order of keys as extracted by the provided
3258  * <em>key selector</em>.
3259  *
3260  * Keys are compared using <tt>operator&lt;()</tt>, but the result is reversed
3261  * to produce descending order.
3262  *
3263  * Use like this:
3264  *
3265  * @code
3266  * using coord = std::tuple<int, int, int>;
3267  * const std::vector<coord> COORDS = {
3268  * { 2, 2, -4 },
3269  * { 2, 20, 8 },
3270  * { -1, 1, 12 },
3271  * { 3, 29, 1 },
3272  * { 3, 3, 3 },
3273  * };
3274  *
3275  * using namespace coveo::linq;
3276  * auto seq = from(COORDS)
3277  * | order_by([](const coord& c) { return c.x; })
3278  * | then_by_descending([](const coord& c) { return c.y; });
3279  * // seq == {
3280  * // { -1, 1, 12 },
3281  * // { 2, 20, 8 },
3282  * // { 2, 2, -4 },
3283  * // { 3, 29, 1 }
3284  * // { 3, 3, 3 },
3285  * // }
3286  * @endcode
3287  *
3288  * @param key_sel Key selector, used to extract a key for a sequence element.
3289  * @return (Once applied) Sequence of elements further ordered by descending key.
3290  */
3291 template<typename KeySelector>
3293  -> decltype(order_by_descending(std::forward<KeySelector>(key_sel)))
3294 {
3295  return order_by_descending(std::forward<KeySelector>(key_sel));
3296 }
3297 
3298 /**
3299  * @ingroup linq_op_order_by
3300  * @brief Further orders elements in sequence by descending key using predicate.
3301  *
3302  * Further orders a sequence previously ordered via <tt>coveo::linq::order_by()</tt>
3303  * or similar operator. Elements that were previously considered equivalent will
3304  * be further ordered by descending order of keys as extracted by the provided
3305  * <em>key selector</em>.
3306  *
3307  * Keys are compared using the provided predicate, but the result is reversed
3308  * to produce descending order. The predicate must provide a strict ordering
3309  * of the keys, like <tt>std::less</tt>.
3310  *
3311  * Use like this:
3312  *
3313  * @code
3314  * using coord = std::tuple<int, int, int>;
3315  * const std::vector<coord> COORDS = {
3316  * { 2, 2, -4 },
3317  * { 2, 20, 8 },
3318  * { -1, 1, 12 },
3319  * { 3, 29, 1 },
3320  * { 3, 3, 3 },
3321  * };
3322  *
3323  * using namespace coveo::linq;
3324  * auto seq = from(COORDS)
3325  * | order_by([](const coord& c) { return c.x; },
3326  * [](int i, int j) { return i < j; })
3327  * | then_by_descending([](const coord& c) { return c.y; },
3328  * [](int i, int j) { return i < j; });
3329  * // seq == {
3330  * // { -1, 1, 12 },
3331  * // { 2, 20, 8 },
3332  * // { 2, 2, -4 },
3333  * // { 3, 29, 1 }
3334  * // { 3, 3, 3 },
3335  * // }
3336  * @endcode
3337  *
3338  * @param key_sel Key selector, used to extract a key for a sequence element.
3339  * @param pred Predicate used to compare the keys.
3340  * @return (Once applied) Sequence of elements further ordered by descending key.
3341  */
3342 template<typename KeySelector, typename Pred>
3344  -> decltype(order_by_descending(std::forward<KeySelector>(key_sel), std::forward<Pred>(pred)))
3345 {
3346  return order_by_descending(std::forward<KeySelector>(key_sel), std::forward<Pred>(pred));
3347 }
3348 
3349 /**
3350  * @ingroup linq_operators_list
3351  * @defgroup linq_op_reverse reverse
3352  * @brief Reverses elements in a sequence.
3353  *
3354  * The @c reverse operator, as its name implies, scans a sequence a produces a new
3355  * sequence in which the elements are reversed.
3356  *
3357  * <b>.NET equivalent:</b> Reverse
3358  */
3359 
3360 /**
3361  * @ingroup linq_op_reverse
3362  * @brief Reverses elements in sequence.
3363  *
3364  * Produces a new sequence in which elements in the source sequence
3365  * are in reverse order.
3366  *
3367  * Use like this:
3368  *
3369  * @code
3370  * const std::vector<int> NUMS = { 42, 23, 66, 11, 7 };
3371  *
3372  * using namespace coveo::linq;
3373  * auto seq = from(NUMS)
3374  * | reverse();
3375  * // seq == { 7, 11, 66, 23, 42 }
3376  * @endcode
3377  *
3378  * @return (Once applied) Sequence of elements in reverse order.
3379  */
3380 template<typename = void>
3381 auto reverse()
3382  -> detail::reverse_impl<>
3383 {
3384  return detail::reverse_impl<>();
3385 }
3386 
3387 /**
3388  * @ingroup linq_operators_list
3389  * @defgroup linq_op_select select / select_with_index / select_many / select_many_with_index
3390  * @brief Projects elements in a sequence into another form.
3391  *
3392  * The @c select operator scans a sequence and projects each of its element into another
3393  * form using a <em>selector</em>, returning a sequence of the results. A little similar
3394  * to <tt>std::transform()</tt>.
3395  *
3396  * <b>.NET equivalent:</b> Select / SelectMany
3397  */
3398 
3399 /**
3400  * @ingroup linq_op_select
3401  * @brief Projects elements in sequence into another form.
3402  *
3403  * Produces a new sequence by projecting each element in the source
3404  * sequence into another form, a little like <tt>std::transform()</tt>.
3405  *
3406  * Use like this:
3407  *
3408  * @code
3409  * const std::vector<std::string> STRS = {
3410  * "Life, the Universe and Everything",
3411  * "Hangar",
3412  * "Route",
3413  * };
3414  *
3415  * using namespace coveo::linq;
3416  * auto seq = from(STRS)
3417  * | select([](const std::string& s) { return s.size(); });
3418  * // seq == { 33, 6, 5 }
3419  * @endcode
3420  *
3421  * @param sel Selector used to project each element in source sequence
3422  * into another form.
3423  * @return (Once applied) Sequence of projected values.
3424  */
3425 template<typename Selector>
3426 auto select(Selector&& sel)
3427  -> detail::select_impl<detail::indexless_selector_proxy<Selector>>
3428 {
3429  return detail::select_impl<detail::indexless_selector_proxy<Selector>>(
3430  detail::indexless_selector_proxy<Selector>(std::forward<Selector>(sel)));
3431 }
3432 
3433 /**
3434  * @ingroup linq_op_select
3435  * @brief Projects elements in sequence into another form using element index.
3436  *
3437  * Produces a new sequence by projecting each element in the source
3438  * sequence into another form, a little like <tt>std::transform()</tt>.
3439  * The selector receives, as second argument, the index of the element
3440  * in the source sequence.
3441  *
3442  * Use like this:
3443  *
3444  * @code
3445  * const std::vector<std::string> STRS = {
3446  * "Life, the Universe and Everything",
3447  * "Hangar",
3448  * "Route",
3449  * };
3450  *
3451  * using namespace coveo::linq;
3452  * auto seq = from(STRS)
3453  * | select_with_index([](const std::string& s, std::size_t i) { return s.size() * (i + 1); });
3454  * // seq == { 33, 12, 15 }
3455  * @endcode
3456  *
3457  * @param sel Selector used to project each element in source sequence
3458  * into another form. Receives index of element as second argument.
3459  * @return (Once applied) Sequence of projected values.
3460  */
3461 template<typename Selector>
3463  -> detail::select_impl<Selector>
3464 {
3465  return detail::select_impl<Selector>(std::forward<Selector>(sel));
3466 }
3467 
3468 /**
3469  * @ingroup linq_op_select
3470  * @brief Projects elements in sequence into many values and flattens them.
3471  *
3472  * Produces a new sequence by projecting each element in the source
3473  * sequence into a sequence of new values, then flattens all those sequences.
3474  *
3475  * Use like this:
3476  *
3477  * @code
3478  * const std::vector<std::string> STRS = {
3479  * "Life, the Universe and Everything",
3480  * "Hangar",
3481  * "Route",
3482  * };
3483  *
3484  * using namespace coveo::linq;
3485  * auto seq = from(STRS)
3486  * | select_many([](const std::string& s) {
3487  * return std::vector<std::size_t>{
3488  * s.size(),
3489  * static_cast<std::size_t>(s.front() - 'A'),
3490  * };
3491  * });
3492  * // seq == { 33, 11, 6, 7, 5, 17 }
3493  * @endcode
3494  *
3495  * @param sel Selector used to project each element in source sequence
3496  * into a sequence of values.
3497  * @return (Once applied) Sequence of flattened projected values.
3498  */
3499 template<typename Selector>
3500 auto select_many(Selector&& sel)
3501  -> detail::select_many_impl<detail::indexless_selector_proxy<Selector>>
3502 {
3503  return detail::select_many_impl<detail::indexless_selector_proxy<Selector>>(
3504  detail::indexless_selector_proxy<Selector>(std::forward<Selector>(sel)));
3505 }
3506 
3507 /**
3508  * @ingroup linq_op_select
3509  * @brief Projects elements in sequence into many values using element index and flattens them.
3510  *
3511  * Produces a new sequence by projecting each element in the source
3512  * sequence into a sequence of new values, then flattens all those sequences.
3513  * The selector receives, as second argument, the index of the element
3514  * in the source sequence.
3515  *
3516  * Use like this:
3517  *
3518  * @code
3519  * const std::vector<std::string> STRS = {
3520  * "Life, the Universe and Everything",
3521  * "Hangar",
3522  * "Route",
3523  * };
3524  *
3525  * using namespace coveo::linq;
3526  * auto seq = from(STRS)
3527  * | select_many_with_index([](const std::string& s, std::size_t i) {
3528  * return std::vector<std::size_t>{
3529  * s.size(),
3530  * static_cast<std::size_t>(s.front() - 'A'),
3531  * i + 1,
3532  * };
3533  * });
3534  * // seq == { 33, 11, 1, 6, 7, 2, 5, 17, 3 }
3535  * @endcode
3536  *
3537  * @param sel Selector used to project each element in source sequence
3538  * into a sequence of values. Receives index of element as
3539  * second argument.
3540  * @return (Once applied) Sequence of flattened projected values.
3541  */
3542 template<typename Selector>
3544  -> detail::select_many_impl<Selector>
3545 {
3546  return detail::select_many_impl<Selector>(std::forward<Selector>(sel));
3547 }
3548 
3549 /**
3550  * @ingroup linq_operators_list
3551  * @defgroup linq_op_seq_equal sequence_equal
3552  * @brief Compares two sequences.
3553  *
3554  * The @c sequence_equal operator compares two sequences and validates
3555  * that they contain the same elements.
3556  *
3557  * This is a @b terminal operator.
3558  *
3559  * <b>.NET equivalent:</b> SequenceEqual
3560  */
3561 
3562 /**
3563  * @ingroup linq_op_seq_equal
3564  * @brief Compares elements in two sequences.
3565  *
3566  * Scans two sequences and compares each corresponding element using
3567  * <tt>operator==()</tt>. Returns @c true if the two sequences contain
3568  * the same elements in the same order.
3569  *
3570  * Use like this:
3571  *
3572  * @code
3573  * const int NUMS1 = { 42, 23, 66 };
3574  * const std::vector<int> NUMS2 = { 42, 23, 66 };
3575  * const std::vector<int> NUMS3 = { 67, 11, 7 };
3576  *
3577  * using namespace coveo::linq;
3578  * bool one_and_two = from(NUMS1)
3579  * | sequence_equal(NUMS2);
3580  * bool one_and_three = from(NUMS1)
3581  * | sequence_equal(NUMS3);
3582  * // one_and_two == true
3583  * // one_and_three == false
3584  * @endcode
3585  *
3586  * @param seq2 Second sequence to compare. The first sequence is the one on
3587  * which the operator will be applied (e.g., the sequence passed
3588  * to <tt>coveo::linq::from()</tt>).
3589  * @return (Once applied) @c true both sequences contain the same elements
3590  * in the same order.
3591  */
3592 template<typename Seq2>
3593 auto sequence_equal(const Seq2& seq2)
3594  -> detail::sequence_equal_impl_1<Seq2>
3595 {
3596  return detail::sequence_equal_impl_1<Seq2>(seq2);
3597 }
3598 
3599 /**
3600  * @ingroup linq_op_seq_equal
3601  * @brief Compares elements in two sequences using predicate.
3602  *
3603  * Scans two sequences and compares each corresponding element using
3604  * the provided predicate. Returns @c true if the two sequences contain
3605  * the same elements in the same order.
3606  *
3607  * Use like this:
3608  *
3609  * @code
3610  * const int NUMS1 = { 42, 23, 66 };
3611  * const std::vector<int> NUMS2 = { 41, 24, 67 };
3612  * const std::vector<int> NUMS3 = { 30, 30, 90 };
3613  *
3614  * auto fuzzy_equal = [](int i, int j) { return std::abs(i - j) <= 2; };
3615  *
3616  * using namespace coveo::linq;
3617  * bool one_and_two = from(NUMS1)
3618  * | sequence_equal(NUMS2, fuzzy_equal);
3619  * bool one_and_three = from(NUMS1)
3620  * | sequence_equal(NUMS3, fuzzy_equal);
3621  * // one_and_two == true
3622  * // one_and_three == false
3623  * @endcode
3624  *
3625  * @param seq2 Second sequence to compare. The first sequence is the one on
3626  * which the operator will be applied (e.g., the sequence passed
3627  * to <tt>coveo::linq::from()</tt>).
3628  * @param pred Predicate used to compare the elements.
3629  * @return (Once applied) @c true both sequences contain the same elements
3630  * in the same order.
3631  */
3632 template<typename Seq2, typename Pred>
3633 auto sequence_equal(const Seq2& seq2, const Pred& pred)
3634  -> detail::sequence_equal_impl_2<Seq2, Pred>
3635 {
3636  return detail::sequence_equal_impl_2<Seq2, Pred>(seq2, pred);
3637 }
3638 
3639 /**
3640  * @ingroup linq_operators_list
3641  * @defgroup linq_op_single single
3642  * @brief Returns the only element in a sequence.
3643  *
3644  * The @c single operator returns the only element in a sequence,
3645  * or the only element to satisfy a predicate. If the sequence does
3646  * not have such an element or has more than one of them, an exception
3647  * is thrown.
3648  *
3649  * This is a @b terminal operator.
3650  *
3651  * <b>.NET equivalent:</b> Single
3652  */
3653 
3654 /**
3655  * @ingroup linq_op_single
3656  * @brief Returns only element in sequence.
3657  *
3658  * Returns the only element in a sequence. If the sequence
3659  * does not have elements or has more than one element, an
3660  * exception is thrown.
3661  *
3662  * Use like this:
3663  *
3664  * @code
3665  * const std::vector<int> YES = { 42 };
3666  * const std::vector<int> NAY1;
3667  * const std::vector<int> NAY2 = { 42, 23, 66 };
3668  *
3669  * using namespace coveo::linq;
3670  * auto val1 = from(YES)
3671  * | single();
3672  * // val1 == 42
3673  * // This throws an exception:
3674  * // auto val2 = from(NAY1)
3675  * // | single();
3676  * // This also throws an exception:
3677  * // auto val3 = from(NAY2)
3678  * // | single();
3679  * @endcode
3680  *
3681  * @return (Once applied) Only element in sequence.
3682  * @exception coveo::linq::empty_sequence The sequence does not have elements.
3683  * @exception coveo::linq::out_of_range The sequence has more than one element.
3684  */
3685 template<typename = void>
3686 auto single()
3687  -> detail::single_impl_0<>
3688 {
3689  return detail::single_impl_0<>();
3690 }
3691 
3692 /**
3693  * @ingroup linq_op_single
3694  * @brief Returns only element in sequence satisfying predicate.
3695  *
3696  * Returns the only element in a sequence that satisfy the given
3697  * predicate. If no element in the sequence or if more than one
3698  * element in the sequence satisfy the predicate, an exception
3699  * is thrown.
3700  *
3701  * Use like this:
3702  *
3703  * @code
3704  * const std::vector<int> YES = { 42, 23, 66 };
3705  * const std::vector<int> NAY1 = { 67, 11, 7 };
3706  * const std::vector<int> NAY2 = { 42, 24, 66 };
3707  *
3708  * auto is_odd = [](int i) { return i % 2 != 0; };
3709  *
3710  * using namespace coveo::linq;
3711  * auto val1 = from(YES)
3712  * | single(is_odd);
3713  * // val1 == 23
3714  * // This throws an exception:
3715  * // auto val2 = from(NAY1)
3716  * // | single(is_odd);
3717  * // This also throws an exception:
3718  * // auto val3 = from(NAY2)
3719  * // | single(is_odd);
3720  * @endcode
3721  *
3722  * @param pred Predicate to satisfy.
3723  * @return (Once applied) Only element in sequence for which @c pred returned @c true.
3724  * @exception coveo::linq::empty_sequence The sequence does not have elements.
3725  * @exception coveo::linq::out_of_range No element satisfy @c pred, or more than one
3726  * element satisfy @c pred.
3727  */
3728 template<typename Pred>
3729 auto single(const Pred& pred)
3730  -> detail::single_impl_1<Pred>
3731 {
3732  return detail::single_impl_1<Pred>(pred);
3733 }
3734 
3735 /**
3736  * @ingroup linq_operators_list
3737  * @defgroup linq_op_single_or_def single_or_default
3738  * @brief Returns the only element in a sequence, or a default value.
3739  *
3740  * The @c single_or_default operator returns the only element in a sequence,
3741  * or the only element to satisfy a predicate. If the sequence does not have
3742  * such an element or has more than one of them, a default value is returned
3743  * instead.
3744  *
3745  * This is a @b terminal operator.
3746  *
3747  * <b>.NET equivalent:</b> SingleOrDefault
3748  */
3749 
3750 /**
3751  * @ingroup linq_op_single_or_def
3752  * @brief Returns only element in sequence, or default value.
3753  *
3754  * Returns the only element in a sequence. If the sequence
3755  * does not have elements or has more than one element, a
3756  * <em>default-initialized</em> value is returned instead.
3757  *
3758  * Use like this:
3759  *
3760  * @code
3761  * const std::vector<int> YES = { 42 };
3762  * const std::vector<int> NAY1;
3763  * const std::vector<int> NAY2 = { 42, 23, 66 };
3764  *
3765  * using namespace coveo::linq;
3766  * auto val1 = from(YES)
3767  * | single_or_default();
3768  * auto val2 = from(NAY1)
3769  * | single_or_default();
3770  * auto val3 = from(NAY2)
3771  * | single_or_default();
3772  * // val1 == 42
3773  * // val2 == 0
3774  * // val3 == 0
3775  * @endcode
3776  *
3777  * @return (Once applied) Only element in sequence, or default value
3778  * if sequence does not have elements or if it has more than
3779  * one element.
3780  */
3781 template<typename = void>
3782 auto single_or_default()
3783  -> detail::single_or_default_impl_0<>
3784 {
3785  return detail::single_or_default_impl_0<>();
3786 }
3787 
3788 /**
3789  * @ingroup linq_op_single_or_def
3790  * @brief Returns only element in sequence satisfying predicate, or default value.
3791  *
3792  * Returns the only element in a sequence that satisfy the given
3793  * predicate. If no element in the sequence or if more than one
3794  * element in the sequence satisfy the predicate, a
3795  * <em>default-initialized</em> value is returned instead.
3796  *
3797  * Use like this:
3798  *
3799  * @code
3800  * const std::vector<int> YES = { 42, 23, 66 };
3801  * const std::vector<int> NAY1 = { 67, 11, 7 };
3802  * const std::vector<int> NAY2 = { 42, 24, 66 };
3803  *
3804  * auto is_odd = [](int i) { return i % 2 != 0; };
3805  *
3806  * using namespace coveo::linq;
3807  * auto val1 = from(YES)
3808  * | single_or_default(is_odd);
3809  * auto val2 = from(NAY1)
3810  * | single_or_default(is_odd);
3811  * auto val3 = from(NAY2)
3812  * | single_or_default(is_odd);
3813  * // val1 == 23
3814  * // val2 == 0
3815  * // val3 == 0
3816  * @endcode
3817  *
3818  * @param pred Predicate to satisfy.
3819  * @return (Once applied) Only element in sequence for which @c pred returned @c true,
3820  * or a default value if either no element satisfy @c pred or more than one
3821  * element satisfy @c pred.
3822  */
3823 template<typename Pred>
3824 auto single_or_default(const Pred& pred)
3825  -> detail::single_or_default_impl_1<Pred>
3826 {
3827  return detail::single_or_default_impl_1<Pred>(pred);
3828 }
3829 
3830 /**
3831  * @ingroup linq_operators_list
3832  * @defgroup linq_op_skip skip / skip_while / skip_while_with_index
3833  * @brief Skips the first elements in a sequence.
3834  *
3835  * The @c skip operator (and its siblings) skip the first elements in a
3836  * sequence, either by skipping a certain number or using a predicate.
3837  *
3838  * <b>.NET equivalent:</b> Skip / SkipWhile
3839  */
3840 
3841 /**
3842  * @ingroup linq_op_skip
3843  * @brief Skips the first N elements in sequence.
3844  *
3845  * Given a source sequence, returns a new sequence that skips
3846  * the first @c n elements of the source sequence. If the source
3847  * sequence contains less than @c n elements, returns an empty
3848  * sequence.
3849  *
3850  * Use like this:
3851  *
3852  * @code
3853  * const int NUMS = { 42, 23, 66, 11, 7 };
3854  *
3855  * using namespace coveo::linq;
3856  * auto seq = from(NUMS)
3857  * | skip(3);
3858  * // seq == { 11, 7 }
3859  * @endcode
3860  *
3861  * @param n Number of elements to skip.
3862  * @return (Once applied) New sequence skipping the first @c n
3863  * elements of source sequence.
3864  */
3865 template<typename = void>
3866 auto skip(std::size_t n)
3867  -> detail::skip_impl<detail::skip_n_pred<>>
3868 {
3869  return detail::skip_impl<detail::skip_n_pred<>>(detail::skip_n_pred<>(n), n);
3870 }
3871 
3872 /**
3873  * @ingroup linq_op_skip
3874  * @brief Skips the first elements in sequence satisfying predicate.
3875  *
3876  * Given a source sequence, returns a new sequence that skips
3877  * the first elements of the source sequence that satisfy the
3878  * provided predicate. If the source sequence contains only
3879  * elements that satisfy the predicate, returns an empty sequence.
3880  *
3881  * Use like this:
3882  *
3883  * @code
3884  * const int NUMS = { 42, 23, 66, 11, 7 };
3885  *
3886  * using namespace coveo::linq;
3887  * auto seq = from(NUMS)
3888  * | skip_while([](int i) { return i < 60; });
3889  * // seq == { 66, 11, 7 }
3890  * @endcode
3891  *
3892  * @param pred Predicate used to skip elements.
3893  * @return (Once applied) New sequence skipping the first
3894  * elements of source sequence satisfying @c pred.
3895  */
3896 template<typename Pred>
3897 auto skip_while(Pred&& pred)
3898  -> detail::skip_impl<detail::indexless_selector_proxy<Pred>>
3899 {
3900  return detail::skip_impl<detail::indexless_selector_proxy<Pred>>(detail::indexless_selector_proxy<Pred>(std::forward<Pred>(pred)),
3901  static_cast<std::size_t>(-1));
3902 }
3903 
3904 /**
3905  * @ingroup linq_op_skip
3906  * @brief Skips the first elements in sequence satisfying predicate using element index.
3907  *
3908  * Given a source sequence, returns a new sequence that skips
3909  * the first elements of the source sequence that satisfy the
3910  * provided predicate. If the source sequence contains only
3911  * elements that satisfy the predicate, returns an empty sequence.
3912  *
3913  * The predicate is called with two parameters every time: an
3914  * element from the source sequence, and its position in the sequence.
3915  *
3916  * Use like this:
3917  *
3918  * @code
3919  * const int NUMS = { 42, 23, 66, 11, 7 };
3920  *
3921  * using namespace coveo::linq;
3922  * auto seq = from(NUMS)
3923  * | skip_while_with_index([](int i, std::size_t idx) { return i < 90 && idx < 3; });
3924  * // seq == { 11, 7 }
3925  * @endcode
3926  *
3927  * @param pred Predicate used to skip elements.
3928  * @return (Once applied) New sequence skipping the first
3929  * elements of source sequence satisfying @c pred.
3930  */
3931 template<typename Pred>
3933  -> detail::skip_impl<Pred>
3934 {
3935  return detail::skip_impl<Pred>(std::forward<Pred>(pred),
3936  static_cast<std::size_t>(-1));
3937 }
3938 
3939 /**
3940  * @ingroup linq_operators_list
3941  * @defgroup linq_op_sum sum
3942  * @brief Computes sum of a sequence of values.
3943  *
3944  * The @c sum operator computes the sum of all values in a sequence. To achieve this,
3945  * it needs a <em>numerical function</em> to extract a numeric value from each sequence element.
3946  *
3947  * This is a @b terminal operator.
3948  *
3949  * <b>.NET equivalent:</b> Sum
3950  */
3951 
3952 /**
3953  * @ingroup linq_op_sum
3954  * @brief Computes sum using numerical function.
3955  *
3956  * Computes the sum of all elements in a sequence by repeatedly calling a <em>numerical function</em>.
3957  * The function receives an element as parameter and must return a numerical value for the element.
3958  * The final result is the sum of all such numerical values.
3959  *
3960  * Does not work on empty sequences.
3961  *
3962  * Use like this:
3963  *
3964  * @code
3965  * const std::vector<std::string> STRS = { "42", "23", "66" };
3966  *
3967  * using namespace coveo::linq;
3968  * auto tot = from(STRS)
3969  * | sum([](auto&& s) { return std::stoi(s); });
3970  * // tot == 131
3971  * @endcode
3972  *
3973  * @param num_f Function to get numerical value for each element.
3974  * @return (Once applied) Sum of all extracted numerical values.
3975  * @exception coveo::linq::empty_sequence The sequence contains no elements.
3976  */
3977 template<typename F>
3978 auto sum(const F& num_f)
3979  -> detail::sum_impl<F>
3980 {
3981  return detail::sum_impl<F>(num_f);
3982 }
3983 
3984 /**
3985  * @ingroup linq_operators_list
3986  * @defgroup linq_op_take take / take_while / take_while_with_index
3987  * @brief Keeps only the first elements in a sequence.
3988  *
3989  * The @c take operator (and its siblings) keep only the first elements in
3990  * a sequence, either by taking a certain number or using a predicate.
3991  *
3992  * <b>.NET equivalent:</b> Take / TakeWhile
3993  */
3994 
3995 /**
3996  * @ingroup linq_op_take
3997  * @brief Keeps the first N elements in sequence.
3998  *
3999  * Given a source sequence, returns a new sequence that contains
4000  * only the first @c n elements of the source sequence. If the
4001  * source sequence contains less than @c n elements, returns as
4002  * many elements as possible.
4003  *
4004  * Use like this:
4005  *
4006  * @code
4007  * const int NUMS = { 42, 23, 66, 11, 7 };
4008  *
4009  * using namespace coveo::linq;
4010  * auto seq = from(NUMS)
4011  * | take(3);
4012  * // seq == { 42, 23, 66 }
4013  * @endcode
4014  *
4015  * @param n Number of elements to take.
4016  * @return (Once applied) New sequence containing the first @c n
4017  * elements of source sequence.
4018  */
4019 template<typename = void>
4020 auto take(std::size_t n)
4021  -> detail::take_impl<detail::skip_n_pred<>>
4022 {
4023  return detail::take_impl<detail::skip_n_pred<>>(detail::skip_n_pred<>(n), n);
4024 }
4025 
4026 /**
4027  * @ingroup linq_op_take
4028  * @brief Keeps the first elements in sequence satisfying predicate.
4029  *
4030  * Given a source sequence, returns a new sequence that contains
4031  * only the first elements of the source sequence that satisfy the
4032  * provided predicate. If the source sequence contains no element
4033  * that satisfy the predicate, returns an empty sequence.
4034  *
4035  * Use like this:
4036  *
4037  * @code
4038  * const int NUMS = { 42, 23, 66, 11, 7 };
4039  *
4040  * using namespace coveo::linq;
4041  * auto seq = from(NUMS)
4042  * | take_while([](int i) { return i > 20; });
4043  * // seq == { 42, 23, 66 }
4044  * @endcode
4045  *
4046  * @param pred Predicate used to take elements.
4047  * @return (Once applied) New sequence containing the first
4048  * elements of source sequence satisfying @c pred.
4049  */
4050 template<typename Pred>
4051 auto take_while(Pred&& pred)
4052  -> detail::take_impl<detail::indexless_selector_proxy<Pred>>
4053 {
4054  return detail::take_impl<detail::indexless_selector_proxy<Pred>>(detail::indexless_selector_proxy<Pred>(std::forward<Pred>(pred)),
4055  static_cast<std::size_t>(-1));
4056 }
4057 
4058 /**
4059  * @ingroup linq_op_take
4060  * @brief Keeps the first elements in sequence satisfying predicate using element index.
4061  *
4062  * Given a source sequence, returns a new sequence that contains
4063  * only the first elements of the source sequence that satisfy the
4064  * provided predicate. If the source sequence contains no element
4065  * that satisfy the predicate, returns an empty sequence.
4066  *
4067  * The predicate is called with two parameters every time: an
4068  * element from the source sequence, and its position in the sequence.
4069  *
4070  * Use like this:
4071  *
4072  * @code
4073  * const int NUMS = { 42, 23, 66, 11, 7 };
4074  *
4075  * using namespace coveo::linq;
4076  * auto seq = from(NUMS)
4077  * | take_while_with_index([](int i, std::size_t idx) { return i > 20 || idx < 4; });
4078  * // seq == { 42, 23, 66, 11 }
4079  * @endcode
4080  *
4081  * @param pred Predicate used to take elements.
4082  * @return (Once applied) New sequence containing the first
4083  * elements of source sequence satisfying @c pred.
4084  */
4085 template<typename Pred>
4087  -> detail::take_impl<Pred>
4088 {
4089  return detail::take_impl<Pred>(std::forward<Pred>(pred),
4090  static_cast<std::size_t>(-1));
4091 }
4092 
4093 /**
4094  * @ingroup linq_operators_list
4095  * @defgroup linq_op_to to / to_vector / to_associative / to_map
4096  * @brief Converts a sequence into another container type.
4097  *
4098  * The @c to operator (and its siblings) converts a sequence into
4099  * another type of container.
4100  *
4101  * This is a terminal operator if the resulting container is not
4102  * in itself a valid sequence.
4103  *
4104  * <b>.NET equivalent:</b> ToArray / ToDictionary / ToList / ToLookup
4105  */
4106 
4107 /**
4108  * @ingroup linq_op_to
4109  * @brief Converts sequence into another container.
4110  *
4111  * Given a source sequence, returns a new container of the provided type
4112  * that contains the source sequence's elements.
4113  *
4114  * Use like this:
4115  *
4116  * @code
4117  * const int NUMS = { 42, 23, 66, 11, 7 };
4118  *
4119  * using namespace coveo::linq;
4120  * auto lst = from(NUMS)
4121  * | to<std::list<int>>();
4122  * // lst == std::list<int>{ 42, 23, 66, 11, 7 }
4123  * @endcode
4124  *
4125  * @tparam Container Type of container to convert to.
4126  * @return (Once applied) Object of type @c Container
4127  * storing the same elements as source sequence.
4128  */
4129 template<typename Container>
4130 auto to()
4131  -> detail::to_impl<Container>
4132 {
4133  return detail::to_impl<Container>();
4134 }
4135 
4136 /**
4137  * @ingroup linq_op_to
4138  * @brief Converts sequence into <tt>std::vector</tt>.
4139  *
4140  * Given a source sequence, returns a new <tt>std::vector</tt> that
4141  * contains the source sequence's elements. The vector's element type
4142  * is auto-detected from the source sequence.
4143  *
4144  * Use like this:
4145  *
4146  * @code
4147  * const int NUMS = { 42, 23, 66, 11, 7 };
4148  *
4149  * using namespace coveo::linq;
4150  * auto vec = from(NUMS)
4151  * | to_vector();
4152  * // vec == std::vector<int>{ 42, 23, 66, 11, 7 }
4153  * @endcode
4154  *
4155  * @return (Once applied) <tt>std::vector</tt> storing the same
4156  * elements as source sequence.
4157  */
4158 template<typename = void>
4159 auto to_vector()
4160  -> detail::to_vector_impl<>
4161 {
4162  return detail::to_vector_impl<>();
4163 }
4164 
4165 /**
4166  * @ingroup linq_op_to
4167  * @brief Converts sequence into associative container using key selector.
4168  *
4169  * Given a source sequence, returns a new associative container of the
4170  * provided type that maps each element's key, as extracted by the provided
4171  * <em>key selector</em>, to the corresponding element.
4172  *
4173  * Use like this:
4174  *
4175  * @code
4176  * using our_pair = std::pair<int, std::string>;
4177  * using our_mm = std::multimap<int, our_pair>;
4178  *
4179  * const std::vector<our_pair> = {
4180  * { 42, "Life" },
4181  * { 23, "Hangar" },
4182  * { 66, "Route" },
4183  * };
4184  *
4185  * using namespace coveo::linq;
4186  * auto omp = from(NUMS)
4187  * | to_associative<our_mm>([](our_pair p) { return p.first; });
4188  * // omp == our_mm{
4189  * // 23 => { 23, "Hangar" },
4190  * // 42 => { 42, "Life" },
4191  * // 66 => { 66, "Route" }
4192  * // }
4193  * @endcode
4194  *
4195  * @tparam Container Type of associative container to convert to.
4196  * @param key_sel Selector used to extract keys for sequence elements.
4197  * @return (Once applied) Object of type @c Container
4198  * mapping the source sequence's elements as specified.
4199  */
4200 template<typename Container,
4201  typename KeySelector>
4202 auto to_associative(const KeySelector& key_sel)
4203  -> detail::to_associative_impl_1<Container, KeySelector>
4204 {
4205  return detail::to_associative_impl_1<Container, KeySelector>(key_sel);
4206 }
4207 
4208 /**
4209  * @ingroup linq_op_to
4210  * @brief Converts sequence into associative container using key and element selector.
4211  *
4212  * Given a source sequence, returns a new associative container of the
4213  * provided type that maps each element's key, as extracted by the provided
4214  * <em>key selector</em>, to the corresponding mapped value, as extracted by
4215  * the provided <em>element selector</em>.
4216  *
4217  * Use like this:
4218  *
4219  * @code
4220  * using our_pair = std::pair<int, std::string>;
4221  * using our_mm = std::multimap<int, std::string>;
4222  *
4223  * const std::vector<our_pair> = {
4224  * { 42, "Life" },
4225  * { 23, "Hangar" },
4226  * { 66, "Route" },
4227  * };
4228  *
4229  * using namespace coveo::linq;
4230  * auto omp = from(NUMS)
4231  * | to_associative<our_mm>([](our_pair p) { return p.first; },
4232  * [](our_pair p) { return p.second; });
4233  * // omp == our_mm{
4234  * // 23 => "Hangar",
4235  * // 42 => "Life",
4236  * // 66 => "Route"
4237  * // }
4238  * @endcode
4239  *
4240  * @tparam Container Type of associative container to convert to.
4241  * @param key_sel Selector used to extract keys for sequence elements.
4242  * @param elem_sel Selector used to extract mapped values for sequence elements.
4243  * @return (Once applied) Object of type @c Container
4244  * mapping the source sequence's elements as specified.
4245  */
4246 template<typename Container,
4247  typename KeySelector,
4248  typename ElementSelector>
4249 auto to_associative(const KeySelector& key_sel,
4250  const ElementSelector& elem_sel)
4251  -> detail::to_associative_impl_2<Container, KeySelector, ElementSelector>
4252 {
4253  return detail::to_associative_impl_2<Container, KeySelector, ElementSelector>(key_sel, elem_sel);
4254 }
4255 
4256 /**
4257  * @ingroup linq_op_to
4258  * @brief Converts sequence into <tt>std::map</tt> using key selector.
4259  *
4260  * Given a source sequence, returns a new <tt>std::map</tt> that maps
4261  * each element's key, as extracted by the provided <em>key selector</em>,
4262  * to the corresponding element. The map's type is auto-detected from
4263  * the source sequence and selector.
4264  *
4265  * Use like this:
4266  *
4267  * @code
4268  * using our_pair = std::pair<int, std::string>;
4269  *
4270  * const std::vector<our_pair> = {
4271  * { 42, "Life" },
4272  * { 23, "Hangar" },
4273  * { 66, "Route" },
4274  * };
4275  *
4276  * using namespace coveo::linq;
4277  * auto omp = from(NUMS)
4278  * | to_map([](our_pair p) { return p.first; });
4279  * // omp == std::map<int, our_pair>{
4280  * // 23 => { 23, "Hangar" },
4281  * // 42 => { 42, "Life" },
4282  * // 66 => { 66, "Route" }
4283  * // }
4284  * @endcode
4285  *
4286  * @param key_sel Selector used to extract keys for sequence elements.
4287  * @return (Once applied) <tt>std::map</tt> mapping the source sequence's
4288  * elements as specified.
4289  */
4290 template<typename KeySelector>
4291 auto to_map(const KeySelector& key_sel)
4292  -> detail::to_map_impl_1<KeySelector>
4293 {
4294  return detail::to_map_impl_1<KeySelector>(key_sel);
4295 }
4296 
4297 /**
4298  * @ingroup linq_op_to
4299  * @brief Converts sequence into <tt>std::map</tt> using key and element selector.
4300  *
4301  * Given a source sequence, returns a new <tt>std::map</tt> that maps
4302  * each element's key, as extracted by the provided <em>key selector</em>,
4303  * to the corresponding mapped value, as extracted by the provided
4304  * <em>element selector</em>. The map's type is auto-detected from
4305  * the source sequence and selectors.
4306  *
4307  * Use like this:
4308  *
4309  * @code
4310  * using our_pair = std::pair<int, std::string>;
4311  *
4312  * const std::vector<our_pair> = {
4313  * { 42, "Life" },
4314  * { 23, "Hangar" },
4315  * { 66, "Route" },
4316  * };
4317  *
4318  * using namespace coveo::linq;
4319  * auto omp = from(NUMS)
4320  * | to_map([](our_pair p) { return p.first; },
4321  * [](our_pair p) { return p.second; });
4322  * // omp == std::map<int, std::string>{
4323  * // 23 => "Hangar",
4324  * // 42 => "Life",
4325  * // 66 => "Route"
4326  * // }
4327  * @endcode
4328  *
4329  * @param key_sel Selector used to extract keys for sequence elements.
4330  * @param elem_sel Selector used to extract mapped values for sequence elements.
4331  * @return (Once applied) <tt>std::map</tt> mapping the source sequence's
4332  * elements as specified.
4333  */
4334 template<typename KeySelector,
4335  typename ElementSelector>
4336 auto to_map(const KeySelector& key_sel,
4337  const ElementSelector& elem_sel)
4338  -> detail::to_map_impl_2<KeySelector, ElementSelector>
4339 {
4340  return detail::to_map_impl_2<KeySelector, ElementSelector>(key_sel, elem_sel);
4341 }
4342 
4343 /**
4344  * @ingroup linq_operators_list
4345  * @defgroup linq_op_union union_with
4346  * @brief Performs a set union of two sequences.
4347  *
4348  * The @c union_with operator returns the union of all elements in the first and
4349  * second sequence (essentially a set union). Similar to a concatenation, except
4350  * duplicate elements are filtered out. The elements are returned in the order
4351  * that they appear in the sequences.
4352  *
4353  * <b>.NET equivalent:</b> Union
4354  */
4355 
4356 /**
4357  * @ingroup linq_op_union
4358  * @brief Performs set union of two sequences.
4359  *
4360  * Returns a sequence containing all elements from the two source sequences
4361  * (essentially a set union). Duplicate elements are filtered out. Elements
4362  * are returned in the order that they appear in the sequences.
4363  *
4364  * Elements are compared using <tt>operator&lt;()</tt>.
4365  *
4366  * Use like this:
4367  *
4368  * @code
4369  * const int ONE[] = { 42, 23, 66, 11, 7, 67 };
4370  * const int TWO[] = { 10, 7, 60, 42, 43, 23 };
4371  *
4372  * using namespace coveo::linq;
4373  * auto seq = from(ONE)
4374  * | union_with(TWO);
4375  * // seq = { 42, 23, 66, 11, 7, 67, 10, 60, 43 }
4376  * @endcode
4377  *
4378  * @param seq2 Second source sequence.
4379  * @return (Once applied) Sequence containing all elements from
4380  * first source sequence and from @c seq2.
4381  */
4382 template<typename Seq2>
4383 auto union_with(Seq2&& seq2)
4384  -> detail::union_impl<Seq2, detail::less<>>
4385 {
4386  return detail::union_impl<Seq2, detail::less<>>(std::forward<Seq2>(seq2),
4387  detail::less<>());
4388 }
4389 
4390 /**
4391  * @ingroup linq_op_union
4392  * @brief Performs set union of two sequences using predicate.
4393  *
4394  * Returns a sequence containing all elements from the two source sequences
4395  * (essentially a set union). Duplicate elements are filtered out. Elements
4396  * are returned in the order that they appear in the sequences.
4397  *
4398  * Elements are compared using the provided predicate. The predicate must
4399  * provide a strict ordering of the elements, like <tt>std::less</tt>.
4400  *
4401  * Use like this:
4402  *
4403  * @code
4404  * const int ONE[] = { 42, 23, 66, 11, 7, 67 };
4405  * const int TWO[] = { 10, 7, 60, 42, 43, 23 };
4406  *
4407  * using namespace coveo::linq;
4408  * auto seq = from(ONE)
4409  * | union_with(TWO, [](int i, int j) { return i > j; });
4410  * // seq = { 42, 23, 66, 11, 7, 67, 10, 60, 43 }
4411  * @endcode
4412  *
4413  * @param seq2 Second source sequence.
4414  * @param pred Predicate used to compare sequence elements.
4415  * @return (Once applied) Sequence containing all elements from
4416  * first source sequence and from @c seq2.
4417  */
4418 template<typename Seq2, typename Pred>
4419 auto union_with(Seq2&& seq2, Pred&& pred)
4420  -> detail::union_impl<Seq2, Pred>
4421 {
4422  return detail::union_impl<Seq2, Pred>(std::forward<Seq2>(seq2),
4423  std::forward<Pred>(pred));
4424 }
4425 
4426 /**
4427  * @ingroup linq_operators_list
4428  * @defgroup linq_op_where where / where_with_index
4429  * @brief Filters a sequence.
4430  *
4431  * The @c where operator (and its siblings) filter the elements in a sequence,
4432  * returning a new sequence containing only the elements that satisfy a predicate.
4433  *
4434  * <b>.NET equivalent:</b> Where
4435  */
4436 
4437 /**
4438  * @ingroup linq_op_where
4439  * @brief Filters sequence elements using predicate.
4440  *
4441  * Returns a sequence that contains only the elements from the
4442  * source sequence that satisfy the given predicate. Order of
4443  * the elements is preserved.
4444  *
4445  * Use like this:
4446  *
4447  * @code
4448  * const int NUMS[] = { 42, 23, 66, 11, 7 };
4449  *
4450  * using namespace coveo::linq;
4451  * auto seq = from(NUMS)
4452  * | where([](int i) { return i % 2 != 0; });
4453  * // seq = { 23, 11, 7 }
4454  * @endcode
4455  *
4456  * @param pred Predicate to satisfy.
4457  * @return (Once applied) Sequence containing all elements from
4458  * source sequence for which @c pred returned @c true.
4459  */
4460 template<typename Pred>
4461 auto where(Pred&& pred)
4462  -> detail::where_impl<detail::indexless_selector_proxy<Pred>>
4463 {
4464  return detail::where_impl<detail::indexless_selector_proxy<Pred>>(
4465  detail::indexless_selector_proxy<Pred>(std::forward<Pred>(pred)));
4466 }
4467 
4468 /**
4469  * @ingroup linq_op_where
4470  * @brief Filters sequence elements using predicate and element index.
4471  *
4472  * Returns a sequence that contains only the elements from the
4473  * source sequence that satisfy the given predicate. Order of
4474  * the elements is preserved.
4475  *
4476  * The predicate receives two arguments: a sequence element and its
4477  * position in the sequence.
4478  *
4479  * Use like this:
4480  *
4481  * @code
4482  * const int NUMS[] = { 42, 23, 66, 11, 7 };
4483  *
4484  * using namespace coveo::linq;
4485  * auto seq = from(NUMS)
4486  * | where_with_index([](int i, std::size_t idx) { return i % 2 != 0 || idx == 0; });
4487  * // seq = { 42, 23, 11, 7 }
4488  * @endcode
4489  *
4490  * @param pred Predicate to satisfy.
4491  * @return (Once applied) Sequence containing all elements from
4492  * source sequence for which @c pred returned @c true.
4493  */
4494 template<typename Pred>
4495 auto where_with_index(Pred&& pred)
4496  -> detail::where_impl<Pred>
4497 {
4498  return detail::where_impl<Pred>(std::forward<Pred>(pred));
4499 }
4500 
4501 /**
4502  * @ingroup linq_operators_list
4503  * @defgroup linq_op_zip zip
4504  * @brief Zips two sequences by combining corresponding elements.
4505  *
4506  * The @c zip operator scans two source sequences and and passes elements
4507  * with the same index to a <em>result selector</em>, then produces a
4508  * sequence containing the results returned by that selector.
4509  *
4510  * <b>.NET equivalent:</b> Zip
4511  */
4512 
4513 /**
4514  * @ingroup linq_op_zip
4515  * @brief Zips two sequences.
4516  *
4517  * Scans two source sequences and calls the provided
4518  * <em>result selector</em> with elements of the two
4519  * sequences that have the same index. Then, produces
4520  * a sequence of the results returned by that selector.
4521  * The resulting sequence will be as long as the shortest
4522  * of the two input sequences.
4523  *
4524  * Use like this:
4525  *
4526  * @code
4527  * const int ONE[] = { 42, 23, 66, 11, 7 };
4528  * const int TWO[] = { 8, 21, 90, 4 };
4529  *
4530  * using namespace coveo::linq;
4531  * auto seq = from(ONE)
4532  * | zip(TWO, [](int i, int j) { return i + j; });
4533  * // seq = { 50, 44, 156, 15 }
4534  * @endcode
4535  *
4536  * @param seq2 Second sequence to scan. The first sequence is the
4537  * one to which the operator is applied, e.g. the
4538  * one passed to <tt>coveo::linq::from()</tt>.
4539  * @param result_sel Selector used to "zip" two corresponding
4540  * sequence elements.
4541  * @return (Once applied) Sequence containing zipped elements
4542  * from the two sequences.
4543  */
4544 template<typename Seq2,
4545  typename ResultSelector>
4547  -> detail::zip_impl<Seq2, ResultSelector>
4548 {
4549  return detail::zip_impl<Seq2, ResultSelector>(std::forward<Seq2>(seq2),
4550  std::forward<ResultSelector>(result_sel));
4551 }
4552 
4553 } // linq
4554 } // coveo
4555 
4556 #endif // COVEO_LINQ_H
auto join(InnerSeq &&inner_seq, OuterKeySelector &&outer_key_sel, InnerKeySelector &&inner_key_sel, ResultSelector &&result_sel, Pred &&pred) -> detail::join_impl< InnerSeq, OuterKeySelector, InnerKeySelector, ResultSelector, Pred >
Joins elements in two sequences according to their keys using predicate.
Definition: linq.h:2558
auto to() -> detail::to_impl< Container >
Converts sequence into another container.
Definition: linq.h:4130
auto select_many_with_index(Selector &&sel) -> detail::select_many_impl< Selector >
Projects elements in sequence into many values using element index and flattens them.
Definition: linq.h:3543
auto select_many(Selector &&sel) -> detail::select_many_impl< detail::indexless_selector_proxy< Selector >>
Projects elements in sequence into many values and flattens them.
Definition: linq.h:3500
auto contains(const T &obj, const Pred &pred) -> detail::contains_impl_2< T, Pred >
Look for element in a sequence using a predicate.
Definition: linq.h:1085
auto any() -> detail::any_impl_0<>
Checks for any element.
Definition: linq.h:843
auto to_vector() -> detail::to_vector_impl<>
Converts sequence into std::vector.
Definition: linq.h:4159
auto skip_while(Pred &&pred) -> detail::skip_impl< detail::indexless_selector_proxy< Pred >>
Skips the first elements in sequence satisfying predicate.
Definition: linq.h:3897
auto count() -> detail::count_impl_0<>
Counts elements in sequence.
Definition: linq.h:1124
auto min() -> detail::min_impl_0<>
Returns minimum element in sequence.
Definition: linq.h:2865
auto union_with(Seq2 &&seq2) -> detail::union_impl< Seq2, detail::less<>>
Performs set union of two sequences.
Definition: linq.h:4383
auto last_or_default(const Pred &pred) -> detail::last_or_default_impl_1< Pred >
Returns last element in sequence that satisfy predicate, or default value.
Definition: linq.h:2738
auto to_map(const KeySelector &key_sel, const ElementSelector &elem_sel) -> detail::to_map_impl_2< KeySelector, ElementSelector >
Converts sequence into std::map using key and element selector.
Definition: linq.h:4336
auto max() -> detail::max_impl_0<>
Returns maximum element in sequence.
Definition: linq.h:2784
auto group_by_and_fold(KeySelector &&key_sel, ResultSelector &&result_sel) -> detail::group_by_impl< KeySelector, detail::identity<>, ResultSelector, detail::less<>>
Groups elements in sequence according to their keys then folds the results.
Definition: linq.h:1938
auto sequence_equal(const Seq2 &seq2, const Pred &pred) -> detail::sequence_equal_impl_2< Seq2, Pred >
Compares elements in two sequences using predicate.
Definition: linq.h:3633
auto distinct() -> detail::distinct_impl< detail::less<>>
Filters out duplicate elements in sequence.
Definition: linq.h:1269
auto aggregate(const F &agg_f) -> detail::aggregate_impl_1< F >
Aggregates values using an aggregation function.
Definition: linq.h:685
auto group_by(KeySelector &&key_sel, Pred &&pred) -> detail::group_by_impl< KeySelector, detail::identity<>, detail::pair_of<>, Pred >
Groups elements in sequence according to their keys using predicate.
Definition: linq.h:1760
auto then_by_descending(KeySelector &&key_sel, Pred &&pred) -> decltype(order_by_descending(std::forward< KeySelector >(key_sel), std::forward< Pred >(pred)))
Further orders elements in sequence by descending key using predicate.
Definition: linq.h:3343
auto any(const Pred &pred) -> detail::any_impl_1< Pred >
Checks for any element that satisfy a predicate.
Definition: linq.h:878
auto except(Seq2 &&seq2, Pred &&pred) -> detail::except_impl< Seq2, Pred >
Performs set difference between two sequences using predicate.
Definition: linq.h:1478
auto max(const Selector &sel) -> detail::max_impl_1< Selector >
Returns maximum projected value in sequence.
Definition: linq.h:2819
auto all(const Pred &pred) -> detail::all_impl< Pred >
Checks elements in a sequence against a predicate.
Definition: linq.h:800
auto intersect(Seq2 &&seq2, Pred &&pred) -> detail::intersect_impl< Seq2, Pred >
Performs set intersection of two sequences using predicate.
Definition: linq.h:2391
auto from_range(It ibeg, It iend) -> decltype(enumerate_range(std::move(ibeg), std::move(iend)))
LINQ expression entry point from iterators.
Definition: linq.h:554
auto group_values_by(KeySelector &&key_sel, ValueSelector &&value_sel, Pred &&pred) -> detail::group_by_impl< KeySelector, ValueSelector, detail::pair_of<>, Pred >
Groups values in sequence according to their keys using predicate.
Definition: linq.h:1884
auto then_by(KeySelector &&key_sel) -> decltype(order_by(std::forward< KeySelector >(key_sel)))
Further orders elements in sequence by ascending key.
Definition: linq.h:3195
auto first() -> detail::first_impl_0<>
Returns first element in sequence.
Definition: linq.h:1525
auto union_with(Seq2 &&seq2, Pred &&pred) -> detail::union_impl< Seq2, Pred >
Performs set union of two sequences using predicate.
Definition: linq.h:4419
auto sum(const F &num_f) -> detail::sum_impl< F >
Computes sum using numerical function.
Definition: linq.h:3978
auto from_int_range(IntT first, std::size_t count) -> coveo::enumerable< const typename std::decay< IntT >::type >
LINQ expression entry point from range of numbers.
Definition: linq.h:580
auto take_while_with_index(Pred &&pred) -> detail::take_impl< Pred >
Keeps the first elements in sequence satisfying predicate using element index.
Definition: linq.h:4086
auto operator|(Seq &&seq, Op &&op) -> decltype(std::forward< Op >(op)(std::forward< Seq >(seq)))
Applies LINQ operators and allows chaining.
Definition: linq.h:640
auto take(std::size_t n) -> detail::take_impl< detail::skip_n_pred<>>
Keeps the first N elements in sequence.
Definition: linq.h:4020
auto intersect(Seq2 &&seq2) -> detail::intersect_impl< Seq2, detail::less<>>
Performs set intersection of two sequences.
Definition: linq.h:2355
auto last() -> detail::last_impl_0<>
Returns last element in sequence.
Definition: linq.h:2621
auto single_or_default() -> detail::single_or_default_impl_0<>
Returns only element in sequence, or default value.
Definition: linq.h:3782
auto except(Seq2 &&seq2) -> detail::except_impl< Seq2, detail::less<>>
Performs set difference between two sequences.
Definition: linq.h:1442
auto take_while(Pred &&pred) -> detail::take_impl< detail::indexless_selector_proxy< Pred >>
Keeps the first elements in sequence satisfying predicate.
Definition: linq.h:4051
auto join(InnerSeq &&inner_seq, OuterKeySelector &&outer_key_sel, InnerKeySelector &&inner_key_sel, ResultSelector &&result_sel) -> detail::join_impl< InnerSeq, OuterKeySelector, InnerKeySelector, ResultSelector, detail::less<>>
Joins elements in two sequences according to their keys.
Definition: linq.h:2473
auto then_by(KeySelector &&key_sel, Pred &&pred) -> decltype(order_by(std::forward< KeySelector >(key_sel), std::forward< Pred >(pred)))
Further orders elements in sequence by ascending key using predicate.
Definition: linq.h:3245
auto first_or_default(const Pred &pred) -> detail::first_or_default_impl_1< Pred >
Returns first element in sequence that satisfy predicate, or default value.
Definition: linq.h:1642
auto min(const Selector &sel) -> detail::min_impl_1< Selector >
Returns minimum projected value in sequence.
Definition: linq.h:2900
auto count(const Pred &pred) -> detail::count_impl_1< Pred >
Counts elements in sequence satisfying a predicate.
Definition: linq.h:1152
auto order_by_descending(KeySelector &&key_sel, Pred &&pred) -> detail::order_by_impl< detail::order_by_comparator< KeySelector, Pred, true >>
Orders elements in sequence by descending key using predicate.
Definition: linq.h:3148
auto element_at_or_default(std::size_t n) -> detail::element_at_or_default_impl<>
Returns nth element in sequence or default value.
Definition: linq.h:1395
auto aggregate(const Acc &seed, const F &agg_f) -> detail::aggregate_impl_2< Acc, F >
Aggregates values using an aggregation function, starting with a seed.
Definition: linq.h:717
auto from_repeated(const T &value, std::size_t count) -> coveo::enumerable< const typename std::decay< T >::type >
LINQ expression entry point from a repeated value.
Definition: linq.h:611
auto none(const Pred &pred) -> detail::none_impl< Pred >
Checks elements in a sequence against a predicate.
Definition: linq.h:2947
auto select_with_index(Selector &&sel) -> detail::select_impl< Selector >
Projects elements in sequence into another form using element index.
Definition: linq.h:3462
auto select(Selector &&sel) -> detail::select_impl< detail::indexless_selector_proxy< Selector >>
Projects elements in sequence into another form.
Definition: linq.h:3426
auto order_by(KeySelector &&key_sel, Pred &&pred) -> detail::order_by_impl< detail::order_by_comparator< KeySelector, Pred, false >>
Orders elements in sequence by ascending key using predicate.
Definition: linq.h:3053
auto concat(Seq2 &&seq2) -> detail::concat_impl< Seq2 >
Concatenates two sequences.
Definition: linq.h:1007
auto to_map(const KeySelector &key_sel) -> detail::to_map_impl_1< KeySelector >
Converts sequence into std::map using key selector.
Definition: linq.h:4291
Type-erased sequence wrapper.
Definition: enumerable.h:62
auto first_or_default() -> detail::first_or_default_impl_0<>
Returns first element in sequence, or default value.
Definition: linq.h:1608
auto group_by_and_fold(KeySelector &&key_sel, ResultSelector &&result_sel, Pred &&pred) -> detail::group_by_impl< KeySelector, detail::identity<>, ResultSelector, Pred >
Groups elements in sequence according to their keys using predicate, then folds the results.
Definition: linq.h:1995
auto default_if_empty() -> detail::default_if_empty_impl_0<>
Ensures sequence has at least one element.
Definition: linq.h:1195
auto order_by_descending(KeySelector &&key_sel) -> detail::order_by_impl< detail::order_by_comparator< KeySelector, detail::less<>, true >>
Orders elements in sequence by descending key.
Definition: linq.h:3099
auto first(const Pred &pred) -> detail::first_impl_1< Pred >
Returns first element in sequence that satisfy predicate.
Definition: linq.h:1561
auto where_with_index(Pred &&pred) -> detail::where_impl< Pred >
Filters sequence elements using predicate and element index.
Definition: linq.h:4495
auto skip_while_with_index(Pred &&pred) -> detail::skip_impl< Pred >
Skips the first elements in sequence satisfying predicate using element index.
Definition: linq.h:3932
auto group_join(InnerSeq &&inner_seq, OuterKeySelector &&outer_key_sel, InnerKeySelector &&inner_key_sel, ResultSelector &&result_sel, Pred &&pred) -> detail::group_join_impl< InnerSeq, OuterKeySelector, InnerKeySelector, ResultSelector, Pred >
Joins and groups elements in two sequences according to their keys using predicate.
Definition: linq.h:2294
auto single(const Pred &pred) -> detail::single_impl_1< Pred >
Returns only element in sequence satisfying predicate.
Definition: linq.h:3729
auto skip(std::size_t n) -> detail::skip_impl< detail::skip_n_pred<>>
Skips the first N elements in sequence.
Definition: linq.h:3866
auto sequence_equal(const Seq2 &seq2) -> detail::sequence_equal_impl_1< Seq2 >
Compares elements in two sequences.
Definition: linq.h:3593
auto zip(Seq2 &&seq2, ResultSelector &&result_sel) -> detail::zip_impl< Seq2, ResultSelector >
Zips two sequences.
Definition: linq.h:4546
auto order_by(KeySelector &&key_sel) -> detail::order_by_impl< detail::order_by_comparator< KeySelector, detail::less<>, false >>
Orders elements in sequence by ascending key.
Definition: linq.h:3005
auto reverse() -> detail::reverse_impl<>
Reverses elements in sequence.
Definition: linq.h:3381
auto contains(const T &obj) -> detail::contains_impl_1< T >
Look for element in a sequence.
Definition: linq.h:1050
auto single_or_default(const Pred &pred) -> detail::single_or_default_impl_1< Pred >
Returns only element in sequence satisfying predicate, or default value.
Definition: linq.h:3824
auto average(const F &num_f) -> detail::average_impl< F >
Computes average using numerical function.
Definition: linq.h:923
auto last(const Pred &pred) -> detail::last_impl_1< Pred >
Returns last element in sequence that satisfy predicate.
Definition: linq.h:2657
auto group_values_by(KeySelector &&key_sel, ValueSelector &&value_sel) -> detail::group_by_impl< KeySelector, ValueSelector, detail::pair_of<>, detail::less<>>
Groups values in sequence according to their keys.
Definition: linq.h:1820
auto then_by_descending(KeySelector &&key_sel) -> decltype(order_by_descending(std::forward< KeySelector >(key_sel)))
Further orders elements in sequence by descending key.
Definition: linq.h:3292
auto to_associative(const KeySelector &key_sel) -> detail::to_associative_impl_1< Container, KeySelector >
Converts sequence into associative container using key selector.
Definition: linq.h:4202
auto single() -> detail::single_impl_0<>
Returns only element in sequence.
Definition: linq.h:3686
auto group_values_by_and_fold(KeySelector &&key_sel, ValueSelector &&value_sel, ResultSelector &&result_sel, Pred &&pred) -> detail::group_by_impl< KeySelector, ValueSelector, ResultSelector, Pred >
Groups values in sequence according to their keys using predicate, then folds the results.
Definition: linq.h:2115
auto last_or_default() -> detail::last_or_default_impl_0<>
Returns last element in sequence, or default value.
Definition: linq.h:2704
auto group_values_by_and_fold(KeySelector &&key_sel, ValueSelector &&value_sel, ResultSelector &&result_sel) -> detail::group_by_impl< KeySelector, ValueSelector, ResultSelector, detail::less<>>
Groups values in sequence according to their keys then folds the results.
Definition: linq.h:2053
auto distinct(Pred &&pred) -> detail::distinct_impl< Pred >
Filters out duplicate elements in sequence using predicate.
Definition: linq.h:1303
auto group_by(KeySelector &&key_sel) -> detail::group_by_impl< KeySelector, detail::identity<>, detail::pair_of<>, detail::less<>>
Groups elements in sequence according to their keys.
Definition: linq.h:1701
auto cast() -> detail::select_impl< detail::indexless_selector_proxy< detail::cast_selector< U >>>
Casts sequence elements to another type.
Definition: linq.h:961
auto default_if_empty(const T &obj) -> detail::default_if_empty_impl_1< T >
Ensures sequence has at least one element, specifying said element.
Definition: linq.h:1228
auto to_associative(const KeySelector &key_sel, const ElementSelector &elem_sel) -> detail::to_associative_impl_2< Container, KeySelector, ElementSelector >
Converts sequence into associative container using key and element selector.
Definition: linq.h:4249
auto element_at(std::size_t n) -> detail::element_at_impl<>
Returns nth element in sequence.
Definition: linq.h:1349
auto group_join(InnerSeq &&inner_seq, OuterKeySelector &&outer_key_sel, InnerKeySelector &&inner_key_sel, ResultSelector &&result_sel) -> detail::group_join_impl< InnerSeq, OuterKeySelector, InnerKeySelector, ResultSelector, detail::less<>>
Joins and groups elements in two sequences according to their keys.
Definition: linq.h:2208
auto aggregate(const Acc &seed, const F &agg_f, const RF &result_f) -> detail::aggregate_impl_3< Acc, F, RF >
Aggregates values using aggregation function, seed and result selector.
Definition: linq.h:753
auto where(Pred &&pred) -> detail::where_impl< detail::indexless_selector_proxy< Pred >>
Filters sequence elements using predicate.
Definition: linq.h:4461
auto from(Seq &&seq) -> decltype(std::forward< Seq >(seq))
Standard LINQ expression entry point.
Definition: linq.h:528