Skip to content

Commit 891624c

Browse files
paulpaul
paul
authored and
paul
committedFeb 12, 2013
Update linq.h file
1 parent 67732f5 commit 891624c

File tree

1 file changed

+2
-1370
lines changed

1 file changed

+2
-1370
lines changed
 

‎linq.h

+2-1,370
Original file line numberDiff line numberDiff line change
@@ -8,1375 +8,7 @@
88
#ifndef INCLUDE_GUARD_LINQ_H
99
#define INCLUDE_GUARD_LINQ_H
1010

11-
#include <utility>
12-
#include <boost/optional.hpp>
13-
#include <boost/preprocessor.hpp>
14-
#include <boost/preprocessor/facilities/is_empty.hpp>
15-
#include <boost/range.hpp>
16-
#include <boost/range/adaptor/filtered.hpp>
17-
#include <boost/range/adaptor/transformed.hpp>
18-
#include <boost/unordered_map.hpp>
19-
#include <boost/unordered_set.hpp>
20-
#include <numeric>
21-
22-
//
23-
//
24-
// Some preprocessor utilites
25-
//
26-
//
27-
28-
//
29-
// LINQ_RETURNS for auto return type deduction.
30-
//
31-
#define LINQ_RETURNS(...) -> decltype(__VA_ARGS__) { return (__VA_ARGS__); } static_assert(true, "")
32-
33-
34-
#define LINQ_ERROR_RETURN_REQUIRES_NEEDS_AN_EXPRESSION(...) decltype(__VA_ARGS__)>::type { return __VA_ARGS__; }
35-
#define LINQ_RETURN_REQUIRES(...) -> typename boost::enable_if<__VA_ARGS__, LINQ_ERROR_RETURN_REQUIRES_NEEDS_AN_EXPRESSION
36-
37-
//
38-
// LINQ_IS_PAREN is used to detect if the first token is a parenthesis.
39-
// It expands to 1 if it is, otherwise it expands to 0.
40-
//
41-
#define LINQ_IS_PAREN(x) LINQ_IS_PAREN_CHECK(LINQ_IS_PAREN_PROBE x)
42-
#define LINQ_IS_PAREN_CHECK(...) LINQ_IS_PAREN_CHECK_N(__VA_ARGS__,0)
43-
#define LINQ_IS_PAREN_PROBE(...) ~, 1,
44-
#ifndef _MSC_VER
45-
#define LINQ_IS_PAREN_CHECK_N(x, n, ...) n
46-
#else
47-
// MSVC workarounds
48-
#define LINQ_IS_PAREN_CHECK_RES(x) x
49-
#define LINQ_IS_PAREN_CHECK_II(x, n, ...) n
50-
#define LINQ_IS_PAREN_CHECK_I(x) LINQ_IS_PAREN_CHECK_RES(LINQ_IS_PAREN_CHECK_II x)
51-
#define LINQ_IS_PAREN_CHECK_N(...) LINQ_IS_PAREN_CHECK_I((__VA_ARGS__))
52-
#endif
53-
54-
//
55-
// LINQ_IS_EMPTY will expands to 1 if the parameter is empty, otherwise
56-
// it expands to 0. This will work even if the parameter given is a set
57-
// of parenthesis.
58-
//
59-
#define LINQ_IS_EMPTY(x) BOOST_PP_CAT(LINQ_IS_EMPTY_, LINQ_IS_PAREN(x))(x)
60-
#define LINQ_IS_EMPTY_0(x) BOOST_PP_IS_EMPTY(x)
61-
#define LINQ_IS_EMPTY_1(x) 0
62-
63-
//
64-
// LINQ_HEAD retrieves the first element of a sequence.
65-
// Example:
66-
//
67-
// LINQ_HEAD((1)(2)(3)) // Expands to (1)
68-
//
69-
#define LINQ_HEAD(x) LINQ_PICK_HEAD(LINQ_MARK x)
70-
#define LINQ_MARK(...) (__VA_ARGS__),
71-
#define LINQ_PICK_HEAD(...) LINQ_PICK_HEAD_I(__VA_ARGS__,)
72-
#ifndef _MSC_VER
73-
#define LINQ_PICK_HEAD_I(x, ...) x
74-
#else
75-
// MSVC workarounds
76-
#define LINQ_PICK_HEAD_III(x, ...) x
77-
#define LINQ_PICK_HEAD_II(x) LINQ_PICK_HEAD_III x
78-
#define LINQ_PICK_HEAD_I(...) LINQ_PICK_HEAD_II((__VA_ARGS__))
79-
#endif
80-
81-
82-
//
83-
// LINQ_TAIL retrieves the tail of a sequence.
84-
// Example:
85-
//
86-
// LINQ_TAIL((1)(2)(3)) // Expands to (2)(3)
87-
//
88-
#define LINQ_TAIL(x) LINQ_EAT x
89-
// Various utilities
90-
#define LINQ_EMPTY(...)
91-
#define LINQ_EAT(...)
92-
#define LINQ_REM(...) __VA_ARGS__
93-
#define LINQ_EXPAND(...) __VA_ARGS__
94-
#define LINQ_DEFER(...) __VA_ARGS__ LINQ_EMPTY()
95-
#define LINQ_OBSTRUCT(...) __VA_ARGS__ LINQ_DEFER(LINQ_EMPTY)()
96-
97-
#define LINQ_EVAL(...) LINQ_EVAL_A(LINQ_EVAL_A(LINQ_EVAL_A(__VA_ARGS__)))
98-
#define LINQ_EVAL_A(...) LINQ_EVAL_B(LINQ_EVAL_B(LINQ_EVAL_B(__VA_ARGS__)))
99-
#define LINQ_EVAL_B(...) LINQ_EVAL_C(LINQ_EVAL_C(LINQ_EVAL_C(__VA_ARGS__)))
100-
#define LINQ_EVAL_C(...) LINQ_EVAL_D(LINQ_EVAL_D(LINQ_EVAL_D(__VA_ARGS__)))
101-
#define LINQ_EVAL_D(...) LINQ_EVAL_E(LINQ_EVAL_E(LINQ_EVAL_E(__VA_ARGS__)))
102-
#define LINQ_EVAL_E(...) __VA_ARGS__
103-
104-
//
105-
// LINQ_BACK gets the last element of a sequence
106-
//
107-
#define LINQ_BACK(seq) BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)), seq)
108-
109-
//
110-
// LINQ_KEYWORD transforms the keyword. Keywords are generally defined
111-
// like this:
112-
//
113-
// //This defines a `my_keyword` macro
114-
// //NOTE: The space between the keyword and parenthesis is necessary
115-
// #define LINQ_KEYWORD_my_keyword (MY_KEYWORD_MACRO)
116-
//
117-
// Here is an example:
118-
//
119-
// LINQ_KEYWORD(my_keyword foo) // Expands to (MY_KEYWORD_MACRO) foo
120-
//
121-
#define LINQ_KEYWORD(x) BOOST_PP_CAT(LINQ_KEYWORD_, x)
122-
123-
//
124-
// LINQ_IS_KEYWORD will expand to 1 if the first token is a valid keyword
125-
//
126-
#define LINQ_IS_KEYWORD(x) LINQ_IS_PAREN(LINQ_KEYWORD(x))
127-
128-
//
129-
// LINQ_PLACE retrieves whats placed in parenthesis. In essence it does
130-
// this:
131-
//
132-
// LINQ_PLACE((1) foo) //Expands to 1
133-
//
134-
// But when its used in the contexts of keywords, it will retrieve whats
135-
// been defined inside the parenthesis of a keyword. Heres an example:
136-
//
137-
// //This defines a `my_keyword` macro
138-
// //NOTE: The space between the keyword and parenthesis is necessary
139-
// #define LINQ_KEYWORD_my_keyword (MY_KEYWORD_MACRO)
140-
// LINQ_PLACE(LINQ_KEYWORD(my_keyword foo)) // Expands to MY_KEYWORD_MACRO
141-
//
142-
#define LINQ_PLACE(x) LINQ_EXPAND(LINQ_REM LINQ_PICK_HEAD(LINQ_MARK x))
143-
144-
//
145-
// LINQ_TO_SEQ converts the keywords into a preprocessor sequence
146-
//
147-
#define LINQ_TO_SEQ(x) LINQ_TO_SEQ_WHILE_M \
148-
( \
149-
BOOST_PP_WHILE(LINQ_TO_SEQ_WHILE_P, LINQ_TO_SEQ_WHILE_O, (,x)) \
150-
)
151-
152-
#define LINQ_TO_SEQ_WHILE_P(r, state) LINQ_TO_SEQ_P state
153-
#define LINQ_TO_SEQ_WHILE_O(r, state) LINQ_TO_SEQ_O state
154-
#define LINQ_TO_SEQ_WHILE_M(state) LINQ_TO_SEQ_M state
155-
156-
#define LINQ_TO_SEQ_P(prev, tail) BOOST_PP_NOT(LINQ_IS_EMPTY(tail))
157-
#define LINQ_TO_SEQ_O(prev, tail) \
158-
BOOST_PP_IF(LINQ_IS_PAREN(tail), \
159-
LINQ_TO_SEQ_PAREN, \
160-
LINQ_TO_SEQ_KEYWORD \
161-
)(prev, tail)
162-
#define LINQ_TO_SEQ_PAREN(prev, tail) \
163-
(prev (LINQ_HEAD(tail)), LINQ_TAIL(tail))
164-
165-
#define LINQ_TO_SEQ_KEYWORD(prev, tail) \
166-
LINQ_TO_SEQ_REPLACE(prev, LINQ_KEYWORD(tail))
167-
168-
#define LINQ_TO_SEQ_REPLACE(prev, tail) \
169-
(prev LINQ_HEAD(tail), LINQ_TAIL(tail))
170-
171-
#define LINQ_TO_SEQ_M(prev, tail) prev
172-
173-
174-
//
175-
// LINQ_SEQ_TO_STRING convert a sequence back to a string of tokens
176-
//
177-
#define LINQ_SEQ_TO_STRING(seq) BOOST_PP_SEQ_FOR_EACH(LINQ_SEQ_TO_STRING_EACH, ~, seq)
178-
#define LINQ_SEQ_TO_STRING_EACH(r, data, x) x
179-
180-
//
181-
// LINQ_SEQ_SPLIT
182-
//
183-
#define LINQ_SEQ_SPLIT(seq, pred, data) LINQ_SEQ_SPLIT_FOLD_LEFT_M(BOOST_PP_SEQ_FOLD_LEFT(LINQ_SEQ_SPLIT_FOLD_LEFT_O, (pred, data,,), seq))
184-
#define LINQ_SEQ_SPLIT_FOLD_LEFT_O(s, state, x) LINQ_SEQ_SPLIT_FOLD_LEFT_INVOKE((s, x, LINQ_REM state))
185-
#ifndef _MSC_VER
186-
#define LINQ_SEQ_SPLIT_FOLD_LEFT_INVOKE(x) LINQ_SEQ_SPLIT_OP x
187-
#else
188-
#define LINQ_SEQ_SPLIT_FOLD_LEFT_INVOKE(x) LINQ_SEQ_SPLIT_FOLD_LEFT_INVOKE_I x
189-
#define LINQ_SEQ_SPLIT_FOLD_LEFT_INVOKE_I(...) LINQ_SEQ_SPLIT_FOLD_LEFT_INVOKE_II((__VA_ARGS__))
190-
#define LINQ_SEQ_SPLIT_FOLD_LEFT_INVOKE_II(x) LINQ_SEQ_SPLIT_OP x
191-
#endif
192-
#define LINQ_SEQ_SPLIT_OP(s, x, pred, data, seq, elem) BOOST_PP_IF(pred(s, data, x), LINQ_SEQ_SPLIT_OP_TRUE, LINQ_SEQ_SPLIT_OP_FALSE)(x, pred, data, seq, elem)
193-
#define LINQ_SEQ_SPLIT_OP_TRUE(x, pred, data, seq, elem) BOOST_PP_IIF(LINQ_IS_PAREN(elem), \
194-
(pred, data, seq(elem),),\
195-
(pred, data, seq,) )
196-
#define LINQ_SEQ_SPLIT_OP_FALSE(x, pred, data, seq, elem) (pred, data, seq, elem (x))
197-
#ifndef _MSC_VER
198-
#define LINQ_SEQ_SPLIT_FOLD_LEFT_M(x) LINQ_SEQ_SPLIT_M x
199-
#else
200-
#define LINQ_SEQ_SPLIT_FOLD_LEFT_M_X(x) x
201-
#define LINQ_SEQ_SPLIT_FOLD_LEFT_M_N(x) LINQ_SEQ_SPLIT_FOLD_LEFT_M_X(LINQ_SEQ_SPLIT_FOLD_LEFT_M_X(LINQ_SEQ_SPLIT_FOLD_LEFT_M_X(LINQ_SEQ_SPLIT_FOLD_LEFT_M_X(x))))
202-
#define LINQ_SEQ_SPLIT_FOLD_LEFT_M(x) LINQ_SEQ_SPLIT_FOLD_LEFT_M_N(LINQ_SEQ_SPLIT_M x)
203-
#endif
204-
#define LINQ_SEQ_SPLIT_M(pred, data, seq, elem) seq BOOST_PP_IIF(LINQ_IS_PAREN(elem), (elem),)
205-
206-
//
207-
// LINQ_SEQ_NEST
208-
//
209-
#define LINQ_SEQ_NEST(seq) BOOST_PP_SEQ_FOLD_LEFT(LINQ_SEQ_NEST_OP, LINQ_BACK(seq) , BOOST_PP_SEQ_POP_BACK(seq))
210-
#define LINQ_SEQ_NEST_OP(s, state, x) x(state)
211-
212-
//
213-
// LINQ_SEQ_NEST_REVERSE
214-
//
215-
#define LINQ_SEQ_NEST_REVERSE(seq) BOOST_PP_SEQ_FOLD_RIGHT(LINQ_SEQ_NEST_OP, LINQ_BACK(seq) , BOOST_PP_SEQ_POP_BACK(seq))
216-
217-
//
218-
// LINQ_VARN_CAT
219-
//
220-
#define LINQ_VARN_CAT(n, tuple) LINQ_EVAL(LINQ_VARN_CAT_D(n, tuple))
221-
#define LINQ_VARN_CAT_D(n, tuple) LINQ_VARN_INVOKE((n, LINQ_REM tuple, BOOST_PP_INTERCEPT, BOOST_PP_INTERCEPT, BOOST_PP_INTERCEPT, BOOST_PP_INTERCEPT, BOOST_PP_INTERCEPT, BOOST_PP_INTERCEPT, BOOST_PP_INTERCEPT, BOOST_PP_INTERCEPT))
222-
#define LINQ_VARN_CAT_ID() LINQ_VARN_CAT_D
223-
224-
#ifndef _MSC_VER
225-
#define LINQ_VARN_INVOKE(data) LINQ_VARN_PRIMITIVE_CAT data
226-
#else
227-
// MSVC Workarounds
228-
#define LINQ_VARN_INVOKE(data) LINQ_VARN_INVOKE_I(data)
229-
#define LINQ_VARN_INVOKE_I(data) LINQ_VARN_PRIMITIVE_CAT data
230-
#endif
231-
#define LINQ_VARN_PRIMITIVE_CAT(n, a, b, c, d, e, f, g, h, ...) LINQ_VARN_CAT_E(a, n) LINQ_VARN_CAT_E(b, n) LINQ_VARN_CAT_E(c, n) LINQ_VARN_CAT_E(d, n) LINQ_VARN_CAT_E(e, n) LINQ_VARN_CAT_E(f, n) LINQ_VARN_CAT_E(g, n) LINQ_VARN_CAT_E(h, n)
232-
233-
#define LINQ_VARN_CAT_E(a, n) BOOST_PP_IF(LINQ_IS_PAREN(a), LINQ_VARN_CAT_EACH_PAREN, LINQ_VARN_CAT_EACH_TOKEN)(a, n)
234-
#define LINQ_VARN_CAT_EACH_PAREN(a, n) (LINQ_OBSTRUCT(LINQ_VARN_CAT_ID)()(n, a))
235-
#define LINQ_VARN_CAT_EACH_TOKEN(a, n) a ## n
236-
237-
//
238-
// LINQ_PARAMS
239-
//
240-
#define LINQ_PARAMS(n, ...) BOOST_PP_ENUM(n, LINQ_PARAMS_EACH, (__VA_ARGS__))
241-
#define LINQ_PARAMS_Z(z, n, ...) BOOST_PP_ENUM_ ## z(n, LINQ_PARAMS_EACH, (__VA_ARGS__))
242-
#define LINQ_PARAMS_EACH(z, n, data) LINQ_VARN_CAT(n, data)
243-
244-
//
245-
// LINQ_GEN
246-
//
247-
#define LINQ_GEN(n, ...) BOOST_PP_REPEAT(n, LINQ_GEN_EACH, (__VA_ARGS__))
248-
#define LINQ_GEN_Z(z, n, ...) BOOST_PP_REPEAT_ ## z(n, LINQ_GEN_EACH, (__VA_ARGS__))
249-
#define LINQ_GEN_EACH(z, n, data) LINQ_VARN_CAT(n, data)
250-
251-
252-
//
253-
// LINQ_FORWARD_PARAMS
254-
//
255-
#define LINQ_FORWARD_PARAMS(n, type, var) BOOST_PP_ENUM(n, LINQ_FORWARD_PARAMS_EACH, (type, var))
256-
#define LINQ_FORWARD_PARAMS_Z(z, n, type, var) BOOST_PP_ENUM_ ## z(n, LINQ_FORWARD_PARAMS_EACH, (type, var))
257-
#define LINQ_FORWARD_PARAMS_EACH(z, n, data) std::forward<BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, data),n)>(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data),n))
258-
259-
260-
//
261-
//
262-
// Extensions
263-
//
264-
//
265-
266-
namespace linq {
267-
268-
// MSVC 2010 doesn't provide declval
269-
// We also return T&& instead std::add_rvalue_reference<T>
270-
// because MSVC has a buggy implementation of it.
271-
// So, this function will work in all cases except when T
272-
// is void(which should rarely happen).
273-
template <typename T>
274-
T&& declval(); // no definition required
275-
276-
//
277-
// is_iterator type trait
278-
//
279-
namespace detail {
280-
BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator_category)
281-
}
282-
283-
template<class T, class Enabler = void>
284-
struct is_iterator
285-
: boost::mpl::false_
286-
{};
287-
template<class T>
288-
struct is_iterator<T, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::has_iterator_category<T> >::type >
289-
: boost::mpl::true_
290-
{};
291-
template<class T>
292-
struct is_iterator<T, BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_pointer<T> >::type >
293-
: boost::mpl::true_
294-
{};
295-
296-
//
297-
// is_range type trait
298-
//
299-
template<class T>
300-
struct is_range : boost::mpl::eval_if< boost::is_const<T>,
301-
boost::has_range_const_iterator<BOOST_DEDUCED_TYPENAME boost::remove_const<T>::type>,
302-
boost::mpl::and_<boost::has_range_iterator<T>, boost::has_range_const_iterator<T> >
303-
>::type
304-
{};
305-
template<class T, class U>
306-
struct is_range<std::pair<T, U> > : boost::mpl::and_<is_iterator<T>, is_iterator<U>, boost::is_same<T, U> >::type
307-
{};
308-
309-
//
310-
// Range extension
311-
//
312-
#ifndef LINQ_LIMIT_EXTENSION
313-
#define LINQ_LIMIT_EXTENSION 4
314-
#endif
315-
namespace detail {
316-
struct na {};
317-
318-
template<class F, BOOST_PP_ENUM_BINARY_PARAMS_Z(1, LINQ_LIMIT_EXTENSION, class T, = na BOOST_PP_INTERCEPT) >
319-
struct pipe_closure {};
320-
321-
#define LINQ_PIPE_CLOSURE_MEMBERS_OP(z, n, data) T ## n x ## n;
322-
#define LINQ_PIPE_CLOSURE_CONSTRUCTOR_OP(z, n, data) x ## n(std::forward<X ## n>(x ## n))
323-
#define LINQ_PIPE_CLOSURE(z, n, data) \
324-
template<class F, BOOST_PP_ENUM_PARAMS_Z(z, n, T), BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_SUB(LINQ_LIMIT_EXTENSION,n), na BOOST_PP_INTERCEPT)> \
325-
struct pipe_closure \
326-
{ \
327-
BOOST_PP_REPEAT_ ## z(n, LINQ_PIPE_CLOSURE_MEMBERS_OP, ~) \
328-
template<LINQ_PARAMS(n, class X)>\
329-
pipe_closure(LINQ_PARAMS(n, X, && BOOST_PP_INTERCEPT, x)) \
330-
: BOOST_PP_ENUM_ ## z(n, LINQ_PIPE_CLOSURE_CONSTRUCTOR_OP, ~) \
331-
{} \
332-
\
333-
template<class Range> \
334-
friend auto operator|(Range && r, pipe_closure p) LINQ_RETURN_REQUIRES(is_range<Range>) \
335-
(F()(std::forward<Range>(r), LINQ_FORWARD_PARAMS(n, T, x) )) \
336-
\
337-
};
338-
BOOST_PP_REPEAT_FROM_TO_1(1, LINQ_LIMIT_EXTENSION, LINQ_PIPE_CLOSURE, ~)
339-
}
340-
#define LINQ_RANGE_EXTENSION_OP(z, n, data) \
341-
template<LINQ_PARAMS(n, class T)> \
342-
auto operator()(LINQ_PARAMS(n, T, && x) ) const LINQ_RETURNS \
343-
( \
344-
detail::pipe_closure<F, BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, T, && BOOST_PP_INTERCEPT)> \
345-
(LINQ_FORWARD_PARAMS_Z(z, n, T, x) ) \
346-
);
347-
348-
template<class F>
349-
struct range_extension
350-
{
351-
BOOST_PP_REPEAT_1(LINQ_LIMIT_EXTENSION, LINQ_RANGE_EXTENSION_OP, ~)
352-
template<class Range>
353-
friend auto operator|(Range && r, range_extension) LINQ_RETURN_REQUIRES(is_range<Range>)
354-
(F()(std::forward<Range>(r)))
355-
356-
range_extension<F>& operator()
357-
{
358-
return *this;
359-
}
360-
361-
const range_extension<F>& operator() const
362-
{
363-
return *this;
364-
}
365-
};
366-
367-
#define LINQ_EXT(name)
368-
369-
//
370-
// set_filter_iterator
371-
//
372-
namespace detail {
373-
// TODO: Add support for an equality selector
374-
template <class Predicate, class Iterator>
375-
struct set_filter_iterator
376-
: boost::iterator_adaptor<set_filter_iterator<Predicate, Iterator, Iterator, boost::use_default, boost::forward_traversal_tag>
377-
{
378-
379-
// Probably should be the initial base class so it can be
380-
// optimized away via EBO if it is an empty class.
381-
Predicate predicate;
382-
Iterator last;
383-
typedef boost::unordered_set<typename boost::iterator_value<Iterator>::type> set_t;
384-
set_t set;
385-
386-
typedef boost::iterator_adaptor<set_filter_iterator<Predicate, Iterator, Iterator, boost::use_default, boost::forward_traversal_tag> super_t;
387-
388-
set_filter_iterator() { }
389-
390-
template<class Range>
391-
set_filter_iterator(Range && r, Predicate f, Iterator x, Iterator l = Iterator())
392-
: super_t(x), predicate(f), last(l), set(boost::begin(r), boost::end(r))
393-
{
394-
satisfy_predicate();
395-
}
396-
397-
set_filter_iterator(Predicate f, Iterator x, Iterator l = Iterator())
398-
: super_t(x), predicate(f), last(l)
399-
{
400-
satisfy_predicate();
401-
}
402-
403-
set_filter_iterator(Iterator x, Iterator l = Iterator())
404-
: super_t(x), predicate(), last(l)
405-
{
406-
satisfy_predicate();
407-
}
408-
409-
// template<class OtherIterator>
410-
// set_filter_iterator(
411-
// set_filter_iterator<Predicate, OtherIterator> const& t
412-
// , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
413-
// )
414-
// : super_t(t.base()), predicate(t.predicate()), last(t.end()) {}
415-
416-
Predicate predicate() const { return predicate; }
417-
418-
Iterator end() const { return last; }
419-
420-
void increment()
421-
{
422-
++(this->base_reference());
423-
satisfy_predicate();
424-
}
425-
426-
void satisfy_predicate()
427-
{
428-
while (this->base() != this->last && !this->predicate(*this->base(), this->set))
429-
{
430-
++(this->base_reference());
431-
}
432-
}
433-
};
434-
435-
template<class Iterator, class Predicate>
436-
auto make_set_filter_iterator(Iterator it, Predicate p) LINQ_RETURNS
437-
(set_filter_iterator<Predicate, Iterator>(p, it));
438-
439-
template<class Iterator, class Predicate>
440-
auto make_set_filter_iterator(Iterator it, Iterator last, Predicate p) LINQ_RETURNS
441-
(set_filter_iterator<Predicate, Iterator>(p, it, last));
442-
443-
template<class Range, class Iterator, class Predicate>
444-
auto make_set_filter_iterator(Range && r, Iterator it, Iterator last, Predicate p) LINQ_RETURNS
445-
(set_filter_iterator<Predicate, Iterator>(r, p, it, last));
446-
447-
template<class Range, class Predicate>
448-
auto make_set_filter_range(Range && r, Predicate p) LINQ_RETURNS
449-
(boost::make_iterator_range
450-
(
451-
make_set_filter_iterator(boost::begin(r), boost::end(r), p),
452-
make_set_filter_iterator(boost::end(r), p)
453-
));
454-
455-
template<class Set, class Range, class Predicate>
456-
auto make_set_filter_range(Set && s, Range && r, Predicate p) LINQ_RETURNS
457-
(boost::make_iterator_range
458-
(
459-
make_set_filter_iterator(s, boost::begin(r), boost::end(r), p),
460-
make_set_filter_iterator(boost::end(r), p)
461-
));
462-
463-
}
464-
465-
//
466-
// always predicate
467-
//
468-
namespace detail {
469-
470-
struct always
471-
{
472-
template<class T>
473-
bool operator()(T) { return true; }
474-
};
475-
}
476-
477-
//
478-
// or_default
479-
//
480-
namespace detail {
481-
482-
template<class Iterator, class Value>
483-
auto or_default(Iterator it, Iterator last, Value && v) LINQ_RETURNS
484-
((it != last) ? *it : std::forward<Value>(v));
485-
}
486-
487-
488-
//
489-
// find
490-
//
491-
namespace detail {
492-
493-
// TODO: Add overload for string
494-
template<class Range, class T>
495-
auto find(Range && r, T && x) LINQ_RETURNS(std::find(boost::begin(r), boost::end(r), std::forward<T>(x)));
496-
497-
struct find_t
498-
{
499-
template<class Range, class T>
500-
auto operator()(Range && r, T && x)
501-
LINQ_RETURNS(find(std::forward<Range>(r), std::forward<T>(x)));
502-
};
503-
}
504-
namespace {
505-
range_extension<detail::find_t> find = {};
506-
}
507-
508-
//
509-
// select
510-
//
511-
namespace detail {
512-
struct select_t
513-
{
514-
//TODO: make it work for empty and single ranges
515-
516-
template<class F, class It>
517-
static auto make_transform_iterator(F f, It it) LINQ_RETURNS(boost::transform_iterator<F, It>(it, f));
518-
519-
template<class Range, class Selector>
520-
auto operator()(Range && r, Selector selector)
521-
LINQ_RETURNS(boost::make_iterator_range(make_transform_iterator(selector, boost::begin(r)), make_transform_iterator(selector, boost::end(r))) );
522-
523-
};
524-
}
525-
namespace {
526-
range_extension<detail::select_t> select = {};
527-
}
528-
529-
530-
//
531-
// aggregate
532-
//
533-
namespace detail {
534-
struct aggregate_t
535-
{
536-
//TODO: make it work for empty and single ranges
537-
template<class Range, class Reducer>
538-
auto operator()(Range && r, Reducer reducer) LINQ_RETURNS(std::accumulate(++boost::begin(r), boost::end(r), *boost::begin(r)));
539-
540-
template<class Range, class Seed, class Reducer>
541-
auto operator()(Range && r, Seed && s, Reducer reducer) LINQ_RETURNS(std::accumulate(boost::begin(r), boost::end(r), s, reducer));
542-
543-
template<class Range, class Seed, class Reducer>
544-
auto operator()(Range && r, Seed && s, Reducer reducer, Selector sel) LINQ_RETURNS(sel(std::accumulate(boost::begin(r), boost::end(r), s, reducer)));
545-
};
546-
}
547-
namespace {
548-
range_extension<detail::aggregate_t> aggregate = {};
549-
}
550-
551-
//
552-
// all
553-
//
554-
namespace detail {
555-
struct all_t
556-
{
557-
template<class Range, class Pred>
558-
auto operator()(Range && r, Pred p) LINQ_RETURNS(std::all_of(boost::begin(r), boost::end(r), pred));
559-
};
560-
}
561-
namespace {
562-
range_extension<detail::all_t> all = {};
563-
}
564-
565-
//
566-
// any
567-
//
568-
namespace detail {
569-
struct any_t
570-
{
571-
template<class Range, class Pred>
572-
auto operator()(Range && r) LINQ_RETURNS(!boost::empty(r))
573-
574-
template<class Range, class Pred>
575-
auto operator()(Range && r, Pred p) LINQ_RETURNS(std::any_of(boost::begin(r), boost::end(r), pred));
576-
};
577-
}
578-
namespace {
579-
range_extension<detail::any_t> any = {};
580-
}
581-
582-
//
583-
// average
584-
//
585-
// TODO
586-
587-
//
588-
// concat
589-
//
590-
namespace detail {
591-
struct concat_t
592-
{
593-
template<class Range1, class Range2>
594-
auto operator()(Range1 && r1, Range2 && r2) LINQ_RETURNS(boost::join(r1, r2));
595-
};
596-
}
597-
namespace {
598-
range_extension<detail::concat_t> concat = {};
599-
}
600-
601-
//
602-
// contains
603-
//
604-
namespace detail {
605-
struct contains_t
606-
{
607-
template<class Range, class T>
608-
auto operator()(Range && r, T && x) LINQ_RETURNS(return (r | linq::find(x) != boost::end(r)));
609-
};
610-
}
611-
namespace {
612-
range_extension<detail::contains_t> contains = {};
613-
}
614-
615-
616-
//
617-
// count
618-
//
619-
namespace detail {
620-
struct count_t
621-
{
622-
// TODO: add overload for random access ranges
623-
template<class Range>
624-
long operator()(Range && r)
625-
{
626-
return std::count_if(boost::begin(r), boost::end(r), [](decltype(*boost::begin(r))) {return true;});
627-
}
628-
629-
template<class Range, class Pred>
630-
long operator()(Range && r, Pred p)
631-
{
632-
return std::count_if(boost::begin(r), boost::end(r), p);
633-
}
634-
};
635-
}
636-
namespace {
637-
range_extension<detail::count_t> count = {};
638-
}
639-
640-
//
641-
// default_if_empty
642-
//
643-
namespace detail {
644-
645-
template<class Iterator, class Value=typename boost::iterator_value<Iterator>::type>
646-
struct default_if_empty_iterator
647-
: boost::iterator_facade<default_if_empty_iterator, Value, boost::forward_traversal_tag>
648-
{
649-
const bool empty;
650-
Iterator it;
651-
Value* ref;
652-
boost::optional<Value> v;
653-
654-
default_if_empty_iterator(bool empty, Iterator it, Value x)
655-
: empty(empty), it(it), v(not empty, x)
656-
{}
657-
658-
// TODO: Assign operator
659-
660-
void increment()
661-
{
662-
if (not empty) it++;
663-
else v = boost::optional<Value>();
664-
}
665-
666-
bool equal(const default_if_empty_iterator<Iterator>& other) const
667-
{
668-
return
669-
(
670-
it == other.it and
671-
(not (v xor other.v))
672-
);
673-
}
674-
675-
typename boost::iteraror_reference<Iterator>::type deref() const
676-
{
677-
if (not empty) return *it;
678-
else return *v;
679-
}
680-
};
681-
682-
template<class Iterator, class Value>
683-
auto make_default_if_empty_iterator(bool empty, Iterator && it, Value && v) LINQ_RETURNS
684-
(default_if_empty_iterator<Iterator>(empty, it, v));
685-
686-
template<class Range, class Value>
687-
auto make_default_if_empty_range(bool empty, Range && r, Value && v) LINQ_RETURNS
688-
(boost::make_iterator_range
689-
(
690-
make_default_if_empty_iterator(empty, boost::begin(r), v),
691-
make_default_if_empty_iterator(empty, boost::end(r), v)
692-
));
693-
694-
struct default_if_empty_t
695-
{
696-
template<class Range, class T>
697-
auto operator()(Range && r, T && x) LINQ_RETURNS
698-
(make_default_if_empty_range(boost::empty(r), r, x));
699-
700-
template<class Range, class T>
701-
auto operator()(Range && r) LINQ_RETURNS
702-
(make_default_if_empty_range(boost::empty(r), r, typename boost::range_value<Range>::type()));
703-
};
704-
}
705-
namespace {
706-
range_extension<detail::default_if_empty_t> default_if_empty = {};
707-
}
708-
709-
//
710-
// distinct
711-
//
712-
namespace detail {
713-
struct distinct_t
714-
{
715-
struct predicate
716-
{
717-
template<class T, class Set>
718-
bool operator()(const T& x, Set& s) const
719-
{
720-
if (s.find(x) != s.end())
721-
{
722-
s.insert(x);
723-
return true;
724-
}
725-
else
726-
{
727-
return false;
728-
}
729-
}
730-
};
731-
// TODO: Add support for an equality selector
732-
template<class Range>
733-
auto operator()(Range && r) const LINQ_RETURNS(make_set_filter_range(r, p));
734-
};
735-
}
736-
namespace {
737-
range_extension<detail::distinct_t> distinct = {};
738-
}
739-
740-
//
741-
// element_at
742-
//
743-
namespace detail {
744-
struct element_at_t
745-
{
746-
template<class Iterator>
747-
static Iterator advance_it(Iterator it, std::size_t n)
748-
{
749-
std::advance(it, n);
750-
return it;
751-
}
752-
// TODO: Throw when its out of range
753-
// TODO: Add overload to provide a fallback value when its out of range
754-
template<class Range>
755-
auto operator()(Range && r) const LINQ_RETURNS(*(advance_it(boost::begin(r))));
756-
};
757-
}
758-
namespace {
759-
range_extension<detail::element_at_t> element_at = {};
760-
}
761-
762-
//
763-
// empty_range
764-
//
765-
766-
//
767-
// except
768-
//
769-
namespace detail {
770-
struct except_t
771-
{
772-
struct predicate
773-
{
774-
775-
template<class T, class Set>
776-
bool operator()(const T& x, Set & s) const
777-
{
778-
if (s.find(x) == s.end())
779-
{
780-
s.insert(x);
781-
return true;
782-
}
783-
else return false;
784-
}
785-
};
786-
// TODO: Add support for an equality selector
787-
template<class Range1, class Range2>
788-
auto operator()(Range1 && r1, Range2 && r2) LINQ_RETURNS
789-
(make_set_filter_range(r2, r1, predicate()));
790-
791-
};
792-
}
793-
namespace {
794-
range_extension<detail::except_t> except = {};
795-
}
796-
797-
798-
//
799-
// first
800-
//
801-
namespace detail {
802-
struct first_t
803-
{
804-
template<class Iterator, class Predicate, class Value>
805-
static boost::iterator_value<Iterator>::type first_it(Iterator first, Iterator last, Predicate p, Value && v)
806-
{
807-
auto it = std::find_if(first, last, p);
808-
if (it == last) return v;
809-
else return *it;
810-
}
811-
812-
template<class Range, class Predicate, class Value>
813-
auto operator()(Range && r, Predicate p, Value && v) LINQ_RETURNS
814-
(first_it(boost::begin(r), boost::end(r), p, std::forward<Value>(v)));
815-
816-
template<class Range>
817-
auto operator()(Range && r) LINQ_RETURNS(*(boost::begin(r)));
818-
819-
};
820-
}
821-
namespace {
822-
range_extension<detail::first_t> first = {};
823-
}
824-
825-
//
826-
// first_or_default
827-
//
828-
namespace detail {
829-
struct first_or_default_t
830-
{
831-
template<class Range>
832-
auto operator()(Range && r) LINQ_RETURNS(r | linq::first(always(), typename boost::range_value<Range>::type()));
833-
834-
template<class Range, class Predicate>
835-
auto operator()(Range && r, Predicate p) LINQ_RETURNS(r | linq::first(p, typename boost::range_value<Range>::type()));
836-
};
837-
}
838-
namespace {
839-
range_extension<detail::first_or_default_t> first_or_default = {};
840-
}
841-
842-
//
843-
// group_by
844-
//
845-
namespace detail {
846-
struct group_by_t
847-
{
848-
849-
template<class Range>
850-
static auto make_map(Range && r) LINQ_RETURNS
851-
(std::multimap<decltype(boost::begin(r)->first), boost::begin(r)->second>(boost::begin(r), boost::end(r)));
852-
853-
template<class Range, class Compare>
854-
static auto make_map(Range && r, Compare c) LINQ_RETURNS
855-
(std::multimap<decltype(boost::begin(r)->first), boost::begin(r)->second, Compare>(boost::begin(r), boost::end(r), c));
856-
857-
struct identity_selector
858-
{
859-
template<class T>
860-
auto operator()(T&& x) LINQ_RETURNS(std::forward<T>(x));
861-
};
862-
863-
template<class KeySelector, class ElementSelector = identity_selector>
864-
struct map_selector
865-
{
866-
KeySelector key_selector;
867-
ElementSelector element_selector;
868-
869-
map_selector(KeySelector ks, ElementSelector es = ElementSelector()) : key_selector(ks), element_selector(es)
870-
{}
871-
872-
template<class T>
873-
auto operator()(T && x) LINQ_RETURNS(std::make_pair(key_selector(x), element_selector(x)));
874-
};
875-
876-
template<class KeySelector>
877-
static auto make_map_selector(KeySelector ks) LINQ_RETURNS(map_selector<KeySelector>(ks));
878-
879-
template<class KeySelector, class ElementSelector>
880-
static auto make_map_selector(KeySelector ks, ElementSelector es) LINQ_RETURNS(map_selector<KeySelector>(ks, es));
881-
882-
template<class Range, class KeySelector>
883-
auto operator()(Range && r, KeySelector ks) LINQ_RETURNS
884-
(make_map(r | linq::select(make_map_selector(ks))));
885-
886-
// TODO: Custom comparer overloads can't be supported right now,
887-
// because we can't detect the difference between a comparer and
888-
// a selector in msvc
889-
890-
// template<class Range, class KeySelector, class KeyCompare>
891-
// auto operator()(Range && r, KeySelector ks, KeyCompare kc) LINQ_RETURNS
892-
// (make_map(r | linq::select(make_map_selector(ks)), kc));
893-
894-
template<class Range, class KeySelector, class ElementSelector>
895-
auto operator()(Range && r, KeySelector ks, ElementSelector es) LINQ_RETURNS
896-
(make_map(r | linq::select(make_map_selector(ks, es))));
897-
898-
// template<class Range, class KeySelector, class ElementSelector, class KeyCompare>
899-
// auto operator()(Range && r, KeySelector ks,ElementSelector es, KeyCompare kc) LINQ_RETURNS
900-
// (make_map(r | linq::select(make_map_selector(ks, es)), kc));
901-
};
902-
}
903-
namespace {
904-
range_extension<detail::group_by_t> group_by = {};
905-
}
906-
907-
//
908-
// group_join
909-
//
910-
namespace detail {
911-
912-
template<class InnerKeySelector>
913-
struct join_inner_selector
914-
{
915-
InnerKeySelector is;
916-
917-
join_inner_selector(InnerKeySelector is) : is(is)
918-
{}
919-
920-
template<class T>
921-
auto operator()(T && x) LINQ_RETURNS(std::make_pair(is(std::forward<T>(x), std::forward<T>(x)));
922-
};
923-
924-
template<class InnerKeySelector>
925-
auto make_join_inner_selector(InnerKeySelector is) LINQ_RETURNS(join_inner_selector<InnerKeySelector>(is));
926-
927-
template<class Value, class OuterKeySelector, class ResultKeySelector>
928-
struct join_selector
929-
{
930-
typedef decltype(linq::declval<OuterKeySelector>()(linq::declval<Value>())) key_t;
931-
boost::unordered_map<key_t, Value> inner_lookup;
932-
ResultKeySelector rs;
933-
OuterKeySelector os;
934-
935-
template<class Range>
936-
join_selector(Range && r, OuterKeySelector os, ResultKeySelector rs)
937-
: inner_lookup(boost::begin(r), boost::end(r)), rs(rs), os(os)
938-
{}
939-
940-
template<class Key>
941-
auto create_pair(Key && x) LINQ_RETURNS
942-
(
943-
std::make_pair(std::forward<T>(x), inner_lookup.equal_range(std::forward<T>(x)) | boost::adaptors::map_values)
944-
);
945-
946-
template<class T>
947-
auto operator()(T && x) LINQ_RETURNS
948-
(
949-
rs
950-
(
951-
create_pair(os(std::forward<T>(x)))
952-
)
953-
);
954-
};
955-
956-
template<class Range, class OuterKeySelector, class ResultKeySelector>
957-
static auto make_join_selector(Range && r, OuterKeySelector os, ResultKeySelector rs) LINQ_RETURNS
958-
(join_selector<typename boost::range_value<R>, OuterKeySelector, ResultKeySelector >
959-
(
960-
r, os, rs
961-
));
962-
963-
struct group_join_t
964-
{
965-
template<class Outer, class Inner, class OuterKeySelector, class InnerKeySelector, class ResultSelector>
966-
auto operator()(Outer && outer, Inner && inner, OuterKeySelector outer_key_selector, InnerKeySelector inner_key_selector, ResultSelector result_selector) LINQ_RETURNS
967-
(
968-
outer | linq::select
969-
(
970-
make_join_selector(inner | linq::select(make_join_inner_selector(is)), outer_key_selector, result_selector)
971-
)
972-
);
973-
};
974-
}
975-
namespace {
976-
range_extension<detail::group_join_t> group_join = {};
977-
}
978-
979-
//
980-
// intersect
981-
//
982-
namespace detail {
983-
struct intersect_t
984-
{
985-
struct predicate
986-
{
987-
988-
template<class T, class Set>
989-
bool operator()(const T& x, Set & s) const
990-
{
991-
auto it = s.find(x);
992-
if (it != s.end())
993-
{
994-
s.erase(it);
995-
return true;
996-
}
997-
else return false;
998-
}
999-
};
1000-
// TODO: Add support for an equality selector
1001-
template<class Range1, class Range2>
1002-
auto operator()(Range1 && r1, Range2 && r2) LINQ_RETURNS
1003-
(make_set_filter_range(r2, r1, predicate()));
1004-
};
1005-
}
1006-
namespace {
1007-
range_extension<detail::intersect_t> intersect = {};
1008-
}
1009-
1010-
//
1011-
// join
1012-
//
1013-
1014-
//
1015-
// last
1016-
//
1017-
1018-
//
1019-
// last_or_default
1020-
//
1021-
1022-
//
1023-
// max
1024-
//
1025-
1026-
//
1027-
// min
1028-
//
1029-
1030-
//
1031-
// order_by
1032-
//
1033-
1034-
//
1035-
// reverse
1036-
//
1037-
1038-
//
1039-
// select_many
1040-
//
1041-
1042-
//
1043-
// sequence_equal
1044-
//
1045-
1046-
//
1047-
// single
1048-
//
1049-
1050-
//
1051-
// single_or_default
1052-
//
1053-
1054-
//
1055-
// skip
1056-
//
1057-
1058-
//
1059-
// skip_while
1060-
//
1061-
1062-
//
1063-
// sum
1064-
//
1065-
1066-
//
1067-
// take
1068-
//
1069-
1070-
//
1071-
// take_while
1072-
//
1073-
1074-
//
1075-
// to_container
1076-
//
1077-
namespace detail {
1078-
struct to_container_t
1079-
{
1080-
1081-
template<class Range>
1082-
struct converter
1083-
{
1084-
Range r;
1085-
1086-
template<class R>
1087-
converter(R && x) : r(std::forward<R&&>(x))
1088-
{}
1089-
1090-
template<class C>
1091-
operator C() const
1092-
{
1093-
return C(boost::begin(r), boost::end(r));
1094-
}
1095-
};
1096-
1097-
template<class Range>
1098-
auto operator()(Range && r) LINQ_RETURNS
1099-
(converter<Range&&>(std::forward<Range>(r)));
1100-
};
1101-
}
1102-
namespace {
1103-
range_extension<detail::to_container_t> to_container = {};
1104-
}
1105-
1106-
//
1107-
// to_string
1108-
//
1109-
1110-
//
1111-
// union
1112-
//
1113-
1114-
//
1115-
// where
1116-
//
1117-
1118-
//
1119-
// zip
1120-
//
1121-
1122-
// Lambdas aren't very nice, so we use this wrapper to make them play nicer. This
1123-
// will make the function_object default constructible, even if it doesn't have a
1124-
// default constructor. This helpful since these function objects are being used
1125-
// inside of iterators.
1126-
template<class Fun>
1127-
struct function_object
1128-
{
1129-
boost::optional<Fun> f;
1130-
1131-
function_object()
1132-
{}
1133-
function_object(Fun f): f(f)
1134-
{}
1135-
1136-
function_object(const function_object & rhs) : f(rhs.f)
1137-
{}
1138-
1139-
// Assignment operator is just a copy construction, which does not provide
1140-
// the strong exception guarentee.
1141-
function_object& operator=(const function_object& rhs)
1142-
{
1143-
if (this != &rhs)
1144-
{
1145-
this->~function_object();
1146-
new (this) function_object(rhs);
1147-
}
1148-
return *this;
1149-
}
1150-
1151-
template<class F>
1152-
struct result
1153-
{};
1154-
1155-
template<class F, class T>
1156-
struct result<F(T)>
1157-
{
1158-
typedef decltype(linq::declval<Fun>()(linq::declval<T>())) type;
1159-
};
1160-
1161-
template<class T>
1162-
auto operator()(T && x) const LINQ_RETURNS((*f)(std::forward<T>(x)));
1163-
1164-
template<class T>
1165-
auto operator()(T && x) LINQ_RETURNS((*f)(std::forward<T>(x)));
1166-
};
1167-
1168-
template<class F>
1169-
function_object<F> make_function_object(F f)
1170-
{
1171-
return function_object<F>(f);
1172-
}
1173-
1174-
1175-
// bind_iterator
1176-
template<class OuterIterator, class Selector, class SelectorRange = typename std::result_of<Selector(typename boost::iterator_reference<OuterIterator>::type)>::type>
1177-
struct bind_iterator
1178-
: boost::iterator_facade
1179-
<
1180-
bind_iterator<OuterIterator, Selector, SelectorRange>,
1181-
typename boost::range_value<SelectorRange >::type,
1182-
boost::forward_traversal_tag,
1183-
typename boost::range_reference<SelectorRange >::type
1184-
>
1185-
{
1186-
typedef typename boost::range_iterator<SelectorRange >::type InnerIteraror;
1187-
1188-
Selector selector;
1189-
OuterIterator iterator;
1190-
InnerIteraror inner_first;
1191-
InnerIteraror inner_last;
1192-
OuterIterator last;
1193-
1194-
bind_iterator(Selector selector, OuterIterator iterator, OuterIterator last) : selector(selector), iterator(iterator), last(last)
1195-
{
1196-
this->select();
1197-
}
1198-
1199-
void select()
1200-
{
1201-
for(;iterator!=last;iterator++)
1202-
{
1203-
if (inner_first==inner_last)
1204-
{
1205-
auto&& r = selector(*iterator);
1206-
inner_first = boost::begin(r);
1207-
inner_last = boost::end(r);
1208-
}
1209-
else inner_first++;
1210-
for(;inner_first!=inner_last;inner_first++)
1211-
return;
1212-
}
1213-
}
1214-
1215-
void increment()
1216-
{
1217-
this->select();
1218-
}
1219-
1220-
bool equal(const bind_iterator& other) const
1221-
{
1222-
return this->iterator == other.iterator;
1223-
}
1224-
1225-
typename boost::range_reference<SelectorRange >::type dereference() const
1226-
{
1227-
return *inner_first;
1228-
}
1229-
1230-
};
1231-
1232-
template<class Iterator, class Selector>
1233-
bind_iterator<Iterator, Selector> make_bind_iterator(Selector selector, Iterator iterator, Iterator last)
1234-
{
1235-
return bind_iterator<Iterator, Selector>(selector, iterator, last);
1236-
}
1237-
1238-
template<class Range, class Selector>
1239-
auto bind_range(Range && r, Selector s) LINQ_RETURNS
1240-
(
1241-
boost::make_iterator_range
1242-
(
1243-
make_bind_iterator(s, boost::begin(r), boost::end(r)),
1244-
make_bind_iterator(s, boost::end(r), boost::end(r))
1245-
)
1246-
);
1247-
1248-
// Bound range adaptor
1249-
namespace detail {
1250-
template<class Selector>
1251-
struct bound_t
1252-
{
1253-
Selector s;
1254-
bound_t(Selector s) : s(s)
1255-
{
1256-
}
1257-
1258-
template<class Range>
1259-
friend auto operator|(Range && r, const bound_t self) -> decltype(linq::bind_range(std::forward<Range>(r), linq::declval<Selector>()))
1260-
{
1261-
return linq::bind_range(std::forward<Range>(r), self.s);
1262-
}
1263-
1264-
};
1265-
}
1266-
1267-
template<class Selector>
1268-
detail::bound_t<Selector> bound(Selector s)
1269-
{
1270-
return detail::bound_t<Selector>(s);
1271-
}
1272-
1273-
1274-
1275-
namespace detail {
1276-
1277-
// These are used to avoid using parenthessis with lambdas, since it
1278-
// could perhaps result in a pathological case for the preprocessor.
1279-
struct where_t
1280-
{
1281-
template<class Pred>
1282-
auto operator+(Pred p) LINQ_RETURNS(boost::adaptors::filtered(linq::make_function_object(p)));
1283-
};
1284-
1285-
struct select_t
1286-
{
1287-
template<class Tran>
1288-
auto operator+(Tran t) LINQ_RETURNS(boost::adaptors::transformed(linq::make_function_object(t)));
1289-
};
1290-
1291-
struct select_many_t
1292-
{
1293-
template<class Sel>
1294-
auto operator+(Sel s) LINQ_RETURNS(linq::bound(make_function_object(s)));
1295-
};
1296-
}
1297-
1298-
detail::select_many_t select_many = {};
1299-
detail::select_t select = {};
1300-
detail::where_t where = {};
1301-
1302-
}
1303-
1304-
// Helps in defining lambdas in two steps. It also dedcues the type held
1305-
// by the container.
1306-
#define LINQ_LAMBDA_BLOCK(...) { return (__VA_ARGS__); }
1307-
#define LINQ_LAMBDA_HEADER(var, col) [&](decltype( *(boost::begin(col)) ) var)
1308-
1309-
// These macros help in defining the clauses. So instead of writing this:
1310-
//
1311-
// auto r = numbers | boost::adaptors::filtered([](int i) { return i > 2});
1312-
//
1313-
// This can be written:
1314-
//
1315-
// auto r = numbers | LINQ_WHERE(i, numbers)(i > 2);
1316-
//
1317-
#define LINQ_WHERE(var, col) linq::where + LINQ_LAMBDA_HEADER(var, col) LINQ_LAMBDA_BLOCK
1318-
#define LINQ_SELECT(var, col) linq::select + LINQ_LAMBDA_HEADER(var, col) LINQ_LAMBDA_BLOCK
1319-
#define LINQ_SELECT_MANY(var, col) linq::select_many + LINQ_LAMBDA_HEADER(var, col) LINQ_LAMBDA_BLOCK
1320-
1321-
//
1322-
// Keywords used by linq
1323-
//
1324-
#define LINQ_KEYWORD_from ()
1325-
#define LINQ_KEYWORD_select (LINQ_SELECT)
1326-
#define LINQ_KEYWORD_where (LINQ_WHERE)
1327-
1328-
//
1329-
// Process the sequence
1330-
//
1331-
1332-
// Expands the parameter, for another preprocessor scan
1333-
#define LINQ_X(...) __VA_ARGS__
1334-
1335-
#define LINQ_PROCESS_PAREN(data, x) x
1336-
#ifndef _MSC_VER
1337-
#define LINQ_PROCESS_KEYWORD(data, x) | x data
1338-
#else
1339-
// MSVC Workarounds
1340-
#define LINQ_PROCESS_KEYWORD_RES(x) x
1341-
#define LINQ_PROCESS_KEYWORD(data, x) | LINQ_PROCESS_KEYWORD_RES(x data)
1342-
#endif
1343-
1344-
#define LINQ_COL(var, col) col
1345-
1346-
// Process the select, where clauses
1347-
#define LINQ_SELECT_WHERE(seq) LINQ_SELECT_WHERE_TRANSFORM(BOOST_PP_SEQ_ELEM(0, seq) ,BOOST_PP_SEQ_REST_N(1, seq))
1348-
#define LINQ_SELECT_WHERE_TRANSFORM(data, seq) LINQ_COL data LINQ_SEQ_TO_STRING(BOOST_PP_SEQ_TRANSFORM(LINQ_SELECT_WHERE_O, data, seq))
1349-
#define LINQ_SELECT_WHERE_O(s, data, x) BOOST_PP_IF(LINQ_IS_PAREN(x), LINQ_PROCESS_PAREN, LINQ_PROCESS_KEYWORD)(data, x)
1350-
1351-
// Process from clauses
1352-
// ()((x, col))()((y, x.col))(LINQ_SELECT)((x))
1353-
// SPLIT
1354-
// ( ((x, col)) ) ( ((y, x.col))(LINQ_SELECT)((x)) )
1355-
// TRANSFORM
1356-
// (SELECT_MANY(x, col))((y, x.col)(LINQ_SELECT)(x))
1357-
// NEST
1358-
#define LINQ_FROM(seq) LINQ_FROM_CHECK(LINQ_SEQ_SPLIT(seq, LINQ_FROM_P, data))
1359-
#define LINQ_FROM_CHECK(seq) BOOST_PP_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)), LINQ_FROM_MULTI, LINQ_FROM_SINGLE)(seq)
1360-
#define LINQ_FROM_MULTI(seq) LINQ_SEQ_NEST(LINQ_FROM_TRANSFORM(seq))
1361-
#define LINQ_FROM_SINGLE(seq) LINQ_SELECT_WHERE(BOOST_PP_SEQ_HEAD(seq))
1362-
1363-
1364-
#define LINQ_FROM_TRANSFORM(seq) BOOST_PP_SEQ_TRANSFORM(LINQ_FROM_OP, data, BOOST_PP_SEQ_POP_BACK(seq)) (LINQ_SELECT_WHERE(LINQ_BACK(seq)))
1365-
1366-
#define LINQ_FROM_P(s, data, x) LINQ_IS_EMPTY(x)
1367-
#ifndef _MSC_VER
1368-
#define LINQ_FROM_OP(s, data, x) LINQ_PROCESS_FROM LINQ_REM x
1369-
#else
1370-
// MSVC Workarounds
1371-
#define LINQ_FROM_OP(s, data, x) LINQ_FROM_OP_INVOKE(LINQ_REM x)
1372-
#define LINQ_FROM_OP_INVOKE_X(x) x
1373-
#define LINQ_FROM_OP_INVOKE(x) LINQ_FROM_OP_INVOKE_X(LINQ_PROCESS_FROM x)
1374-
#endif
1375-
#define LINQ_PROCESS_FROM(var, col) col | LINQ_SELECT_MANY(var, col)
1376-
1377-
// Transforms the sequence
1378-
#define LINQ_TRANSFORM(seq) LINQ_X(LINQ_FROM(seq))
1379-
// And finally the LINQ macro
1380-
#define LINQ(x) LINQ_TRANSFORM(LINQ_TO_SEQ(x))
11+
#include <linq/extensions.h>
12+
#include <linq/query.h>
138113

138214
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.