// ---------------------------------------------------------------------------------------------- // Copyright (c) Mårten Rånge. // ---------------------------------------------------------------------------------------------- // This source code is subject to terms and conditions of the Microsoft Public License. A // copy of the license can be found in the License.html file at the root of this distribution. // If you cannot locate the Microsoft Public License, please send an email to // dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound // by the terms of the Microsoft Public License. // ---------------------------------------------------------------------------------------------- // You must not remove this notice, or any other, from this software. // ---------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------- #ifndef CPPLINQ__HEADER_GUARD # define CPPLINQ__HEADER_GUARD #define NOMINMAX // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include #include #// ---------------------------------------------------------------------------- #ifdef _MSC_VER # pragma warning (push) # pragma warning (disable:4512) // 'class' : assignment operator could not be generated // Rationale: cpplinq doesn't rely on assignment operators # pragma warning (disable:4702) // unreachable code // Rationale: Depending on the predicates and the calling // code the compiler might detect unreacable code that with // other predicates are reachable. # pragma warning (disable:4003) #endif #define NOMINMAX // so we wont have conflicts with std:: thing // ---------------------------------------------------------------------------- #define CPPLINQ_METHOD #define CPPLINQ_INLINEMETHOD inline #define CPPLINQ_NOEXCEPT throw () // ---------------------------------------------------------------------------- // TODO: Struggled with getting slice protection // and assignment operator detection for MINGW // Look into using delete standard functions // #define CPPLINQ_DETECT_INVALID_METHODS // ---------------------------------------------------------------------------- namespace cpplinq { // ------------------------------------------------------------------------- typedef std::size_t size_type; // ------------------------------------------------------------------------- struct base_exception : std::exception { virtual const char* what () const CPPLINQ_NOEXCEPT { return "base_exception"; } }; struct programming_error_exception : base_exception { virtual const char* what () const CPPLINQ_NOEXCEPT { return "programming_error_exception"; } }; struct sequence_empty_exception : base_exception { virtual const char* what () const CPPLINQ_NOEXCEPT { return "sequence_empty_exception"; } }; // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- // Tedious implementation details of cpplinq // ------------------------------------------------------------------------- namespace detail { // ------------------------------------------------------------------------- size_type const invalid_size = static_cast(-1); // ------------------------------------------------------------------------- template struct cleanup_type { typedef typename std::remove_const< typename std::remove_reference::type >::type type; }; template struct get_builtup_type { static TRangeBuilder get_builder (); static TRange get_range (); typedef decltype (get_builder ().build (get_range ())) type; }; template struct get_transformed_type { static TValue get_value (); static TPredicate get_predicate (); typedef decltype (get_predicate ()(get_value ())) raw_type ; typedef typename cleanup_type::type type ; }; template struct get_array_properties; template struct get_array_properties { enum { size = Size , }; typedef typename cleanup_type::type value_type ; typedef value_type* iterator_type ; }; template struct opt { typedef TValue value_type; CPPLINQ_INLINEMETHOD opt () CPPLINQ_NOEXCEPT : is_initialized (false) { } CPPLINQ_INLINEMETHOD explicit opt (value_type && value) : is_initialized (true) { new (&storage) value_type (std::move (value)); } CPPLINQ_INLINEMETHOD explicit opt (value_type const & value) : is_initialized (true) { new (&storage) value_type (value); } CPPLINQ_INLINEMETHOD ~opt () CPPLINQ_NOEXCEPT { auto ptr = get_ptr (); if (ptr) { ptr->~value_type (); } is_initialized = false; } CPPLINQ_INLINEMETHOD opt (opt const & v) : is_initialized (v.is_initialized) { if (v.is_initialized) { copy (&storage , &v.storage ); } } CPPLINQ_INLINEMETHOD opt (opt && v) CPPLINQ_NOEXCEPT : is_initialized (v.is_initialized) { if (v.is_initialized) { move (&storage , &v.storage ); } v.is_initialized = false; } CPPLINQ_METHOD void swap (opt & v) { if (is_initialized && v.is_initialized) { storage_type tmp; move (&tmp , &storage ); move (&storage , &v.storage ); move (&v.storage , &tmp ); } else if (is_initialized) { move (&v.storage , &storage ); v.is_initialized= true; is_initialized = false; } else if (v.is_initialized) { move (&storage , &v.storage ); v.is_initialized= false; is_initialized = true; } else { // Do nothing } } CPPLINQ_INLINEMETHOD opt & operator= (opt const & v) { if (this == std::addressof (v)) { return *this; } opt o (v); swap (o); return *this; } CPPLINQ_INLINEMETHOD opt & operator= (opt && v) { if (this == std::addressof (v)) { return *this; } swap (v); return *this; } CPPLINQ_INLINEMETHOD opt & operator= (value_type v) { return *this = opt (std::move (v)); } CPPLINQ_INLINEMETHOD void clear () CPPLINQ_NOEXCEPT { opt empty; swap (empty); } CPPLINQ_INLINEMETHOD value_type const * get_ptr () const CPPLINQ_NOEXCEPT { if (is_initialized) { return reinterpret_cast (&storage); } else { return nullptr; } } CPPLINQ_INLINEMETHOD value_type * get_ptr () CPPLINQ_NOEXCEPT { if (is_initialized) { return reinterpret_cast (&storage); } else { return nullptr; } } CPPLINQ_INLINEMETHOD value_type const & get () const CPPLINQ_NOEXCEPT { assert (is_initialized); return *get_ptr (); } CPPLINQ_INLINEMETHOD value_type & get () CPPLINQ_NOEXCEPT { assert (is_initialized); return *get_ptr (); } CPPLINQ_INLINEMETHOD bool has_value () const CPPLINQ_NOEXCEPT { return is_initialized; } typedef bool (opt::*type_safe_bool_type) () const; CPPLINQ_INLINEMETHOD operator type_safe_bool_type () const CPPLINQ_NOEXCEPT { return is_initialized ? &opt::has_value : nullptr; } CPPLINQ_INLINEMETHOD value_type const & operator* () const CPPLINQ_NOEXCEPT { return get (); } CPPLINQ_INLINEMETHOD value_type & operator* () CPPLINQ_NOEXCEPT { return get (); } CPPLINQ_INLINEMETHOD value_type const * operator-> () const CPPLINQ_NOEXCEPT { return get_ptr (); } CPPLINQ_INLINEMETHOD value_type * operator-> () CPPLINQ_NOEXCEPT { return get_ptr (); } private: typedef typename std::aligned_storage< sizeof (value_type) , std::alignment_of::value >::type storage_type ; storage_type storage ; bool is_initialized ; CPPLINQ_INLINEMETHOD static void move ( storage_type * to , storage_type * from ) CPPLINQ_NOEXCEPT { auto f = reinterpret_cast (from); new (to) value_type (std::move (*f)); f->~value_type (); } CPPLINQ_INLINEMETHOD static void copy ( storage_type * to , storage_type const * from ) { auto f = reinterpret_cast (from); new (to) value_type (*f); } }; // ------------------------------------------------------------------------- // The generic interface // ------------------------------------------------------------------------- // _range classes: // inherit base_range // COPYABLE // MOVEABLE (movesemantics) // typedef ... this_type ; // typedef ... value_type ; // typedef ... return_type ; // value_type | value_type const & // enum { returns_reference = 0|1 }; // return_type front () const // bool next () // template // typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const // ------------------------------------------------------------------------- // _builder classes: // inherit base_builder // COPYABLE // MOVEABLE (movesemantics) // typedef ... this_type ; // template // TAggregated build (TRange range) const // ------------------------------------------------------------------------- struct base_range { #ifdef CPPLINQ_DETECT_INVALID_METHODS protected: // In order to prevent object slicing CPPLINQ_INLINEMETHOD base_range () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD base_range (base_range const &) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD base_range (base_range &&) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD ~base_range () CPPLINQ_NOEXCEPT { } private: CPPLINQ_INLINEMETHOD base_range & operator= (base_range const &); CPPLINQ_INLINEMETHOD base_range & operator= (base_range &&); #endif }; struct base_builder { #ifdef CPPLINQ_DETECT_INVALID_METHODS protected: // In order to prevent object slicing CPPLINQ_INLINEMETHOD base_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD base_builder (base_builder const &) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD base_builder (base_builder &&) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD ~base_builder () CPPLINQ_NOEXCEPT { } private: CPPLINQ_INLINEMETHOD base_builder & operator= (base_builder const &); CPPLINQ_INLINEMETHOD base_builder & operator= (base_builder &&); #endif }; template struct from_range : base_range { static TValueIterator get_iterator (); typedef from_range this_type ; typedef TValueIterator iterator_type ; typedef decltype (*get_iterator ()) raw_value_type ; typedef typename cleanup_type::type value_type ; typedef value_type const & return_type ; enum { returns_reference = 1, }; iterator_type current ; iterator_type upcoming; iterator_type end ; CPPLINQ_INLINEMETHOD from_range ( iterator_type begin , iterator_type end ) CPPLINQ_NOEXCEPT : current (std::move (begin)) , upcoming(current) , end (std::move (end)) { } CPPLINQ_INLINEMETHOD from_range (from_range const & v) CPPLINQ_NOEXCEPT : current (v.current) , upcoming(v.upcoming) , end (v.end) { } CPPLINQ_INLINEMETHOD from_range (from_range && v) CPPLINQ_NOEXCEPT : current (std::move (v.current)) , upcoming(std::move (v.upcoming)) , end (std::move (v.end)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { assert (current != upcoming); assert (current != end); return *current; } CPPLINQ_INLINEMETHOD bool next () CPPLINQ_NOEXCEPT { if (upcoming == end) { return false; } current = upcoming; ++upcoming; return true; } }; // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- template struct from_copy_range : base_range { typedef from_copy_range this_type ; typedef TContainer container_type ; typedef typename TContainer::const_iterator iterator_type ; typedef typename TContainer::value_type value_type ; typedef value_type const & return_type ; enum { returns_reference = 1 , }; container_type container ; iterator_type current ; iterator_type upcoming ; iterator_type end ; CPPLINQ_INLINEMETHOD from_copy_range ( container_type&& container ) : container (std::move (container)) , current (container.begin ()) , upcoming (container.begin ()) , end (container.end ()) { } CPPLINQ_INLINEMETHOD from_copy_range ( container_type const & container ) : container (container) , current (container.begin ()) , upcoming (container.begin ()) , end (container.end ()) { } CPPLINQ_INLINEMETHOD from_copy_range (from_copy_range const & v) : container (v.container) , current (v.current) , upcoming (v.upcoming) , end (v.end) { } CPPLINQ_INLINEMETHOD from_copy_range (from_copy_range && v) CPPLINQ_NOEXCEPT : container (std::move (v.container)) , current (std::move (v.current)) , upcoming (std::move (v.upcoming)) , end (std::move (v.end)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { assert (current != upcoming); assert (current != end); return *current; } CPPLINQ_INLINEMETHOD bool next () CPPLINQ_NOEXCEPT { if (upcoming == end) { return false; } current = upcoming; ++upcoming; return true; } }; // ------------------------------------------------------------------------- struct int_range : base_range { typedef int_range this_type ; typedef int value_type ; typedef int return_type ; enum { returns_reference = 0 , }; int current ; int end ; static int get_current (int begin, int end) { return (begin < end ? begin : end) - 1; // -1 in order to start one-step before the first element } static int get_end (int begin, int end) // -1 in order to avoid an extra test in next { return (begin < end ? end : begin) - 1; } CPPLINQ_INLINEMETHOD int_range ( int begin , int end ) CPPLINQ_NOEXCEPT : current (get_current (begin, end)) , end (get_end (begin,end)) { } CPPLINQ_INLINEMETHOD int_range (int_range const & v) CPPLINQ_NOEXCEPT : current (v.current) , end (v.end) { } CPPLINQ_INLINEMETHOD int_range (int_range && v) CPPLINQ_NOEXCEPT : current (std::move (v.current)) , end (std::move (v.end)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return current; } CPPLINQ_INLINEMETHOD bool next () CPPLINQ_NOEXCEPT { if (current >= end) { return false; } ++current; return true; } }; // ------------------------------------------------------------------------- template struct repeat_range : base_range { typedef repeat_range this_type ; typedef TValue value_type ; typedef TValue return_type ; enum { returns_reference = 0 , }; TValue value ; size_type remaining ; CPPLINQ_INLINEMETHOD repeat_range ( value_type element , size_type count ) CPPLINQ_NOEXCEPT : value (std::move (element)) , remaining (count) { } CPPLINQ_INLINEMETHOD repeat_range (repeat_range const & v) CPPLINQ_NOEXCEPT : value (v.value) , remaining (v.remaining) { } CPPLINQ_INLINEMETHOD repeat_range (repeat_range && v) CPPLINQ_NOEXCEPT : value (std::move (v.value)) , remaining (std::move (v.remaining)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return value; } CPPLINQ_INLINEMETHOD bool next () CPPLINQ_NOEXCEPT { if (remaining == 0U) { return false; } --remaining; return true; } }; // ------------------------------------------------------------------------- template struct empty_range : base_range { typedef empty_range this_type ; typedef TValue value_type ; typedef TValue return_type ; enum { returns_reference = 0 , }; CPPLINQ_INLINEMETHOD empty_range () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD empty_range (empty_range const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD empty_range (empty_range && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { assert (false); throw programming_error_exception (); } CPPLINQ_INLINEMETHOD bool next () CPPLINQ_NOEXCEPT { return false; } }; // ------------------------------------------------------------------------- template struct singleton_range : base_range { typedef singleton_range this_type ; typedef TValue value_type ; typedef TValue const & return_type ; enum { returns_reference = 1 , }; value_type value ; bool done ; CPPLINQ_INLINEMETHOD singleton_range (TValue const & value) : value (value) , done (false) { } CPPLINQ_INLINEMETHOD singleton_range (TValue&& value) CPPLINQ_NOEXCEPT : value (std::move (value)) , done (false) { } CPPLINQ_INLINEMETHOD singleton_range (singleton_range const & v) CPPLINQ_NOEXCEPT : value (v.value) , done (v.done) { } CPPLINQ_INLINEMETHOD singleton_range (singleton_range && v) CPPLINQ_NOEXCEPT : value (std::move (v.value)) , done (std::move (v.done)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const CPPLINQ_NOEXCEPT { return value; } CPPLINQ_INLINEMETHOD bool next () CPPLINQ_NOEXCEPT { auto d = done; done = true; return !d; } }; // ------------------------------------------------------------------------- struct sorting_range : base_range { #ifdef CPPLINQ_DETECT_INVALID_METHODS protected: // In order to prevent object slicing CPPLINQ_INLINEMETHOD sorting_range () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD sorting_range (sorting_range const &) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD sorting_range (sorting_range &&) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD ~sorting_range () CPPLINQ_NOEXCEPT { } private: CPPLINQ_INLINEMETHOD sorting_range & operator= (sorting_range const &); CPPLINQ_INLINEMETHOD sorting_range & operator= (sorting_range &&); #endif }; template struct orderby_range : sorting_range { typedef orderby_range this_type ; typedef TRange range_type ; typedef TPredicate predicate_type ; typedef typename TRange::value_type value_type ; typedef typename TRange::return_type forwarding_return_type ; typedef value_type const & return_type ; enum { forward_returns_reference = TRange::returns_reference , returns_reference = 1 , }; range_type range ; predicate_type predicate ; bool sort_ascending ; size_type current ; std::vector sorted_values ; CPPLINQ_INLINEMETHOD orderby_range ( range_type range , predicate_type predicate , bool sort_ascending ) CPPLINQ_NOEXCEPT : range (std::move (range)) , predicate (std::move (predicate)) , sort_ascending (sort_ascending) , current (invalid_size) { static_assert ( !std::is_convertible::value , "orderby may not follow orderby or thenby" ); } CPPLINQ_INLINEMETHOD orderby_range (orderby_range const & v) : range (v.range) , predicate (v.predicate) , sort_ascending (v.sort_ascending) , current (v.current) , sorted_values (v.sorted_values) { } CPPLINQ_INLINEMETHOD orderby_range (orderby_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , predicate (std::move (v.predicate)) , sort_ascending (std::move (v.sort_ascending)) , current (std::move (v.current)) , sorted_values (std::move (v.sorted_values)) { } CPPLINQ_INLINEMETHOD forwarding_return_type forwarding_front () const { return range.front (); } CPPLINQ_INLINEMETHOD bool forwarding_next () { return range.next (); } CPPLINQ_INLINEMETHOD bool compare_values (value_type const & l, value_type const & r) const { if (sort_ascending) { return predicate (l) < predicate (r); } else { return predicate (r) < predicate (l); } } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return sorted_values[current]; } CPPLINQ_METHOD bool next () { if (current == invalid_size) { sorted_values.clear (); while (range.next ()) { sorted_values.push_back (range.front ()); } if (sorted_values.size () == 0) { return false; } std::sort ( sorted_values.begin () , sorted_values.end () , [this] (value_type const & l, value_type const & r) { return this->compare_values (l,r); } ); current = 0U; return true; } if (current < sorted_values.size ()) { ++current; } return current < sorted_values.size (); } }; template struct orderby_builder : base_builder { typedef orderby_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; bool sort_ascending ; CPPLINQ_INLINEMETHOD explicit orderby_builder (predicate_type predicate, bool sort_ascending) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) , sort_ascending (sort_ascending) { } CPPLINQ_INLINEMETHOD orderby_builder (orderby_builder const & v) : predicate (v.predicate) , sort_ascending (v.sort_ascending) { } CPPLINQ_INLINEMETHOD orderby_builder (orderby_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) , sort_ascending (std::move (v.sort_ascending)) { } template CPPLINQ_INLINEMETHOD orderby_range build (TRange range) const { return orderby_range(std::move (range), predicate, sort_ascending); } }; // ------------------------------------------------------------------------- template struct thenby_range : sorting_range { typedef thenby_range this_type ; typedef TRange range_type ; typedef TPredicate predicate_type ; typedef typename TRange::value_type value_type ; typedef typename TRange::forwarding_return_type forwarding_return_type ; typedef value_type const & return_type ; enum { forward_returns_reference = TRange::forward_returns_reference , returns_reference = 1 , }; range_type range ; predicate_type predicate ; bool sort_ascending ; size_type current ; std::vector sorted_values ; CPPLINQ_INLINEMETHOD thenby_range ( range_type range , predicate_type predicate , bool sort_ascending ) CPPLINQ_NOEXCEPT : range (std::move (range)) , predicate (std::move (predicate)) , sort_ascending (sort_ascending) , current (invalid_size) { static_assert ( std::is_convertible::value , "thenby may only follow orderby or thenby" ); } CPPLINQ_INLINEMETHOD thenby_range (thenby_range const & v) : range (v.range) , predicate (v.predicate) , sort_ascending (v.sort_ascending) , current (v.current) , sorted_values (v.sorted_values) { } CPPLINQ_INLINEMETHOD thenby_range (thenby_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , predicate (std::move (v.predicate)) , sort_ascending (std::move (v.sort_ascending)) , current (std::move (v.current)) , sorted_values (std::move (v.sorted_values)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD forwarding_return_type forwarding_front () const { return range.front (); } CPPLINQ_INLINEMETHOD bool forwarding_next () { return range.next (); } CPPLINQ_INLINEMETHOD bool compare_values (value_type const & l, value_type const & r) const { auto pless = range.compare_values (l,r); if (pless) { return true; } auto pgreater = range.compare_values (r,l); if (pgreater) { return false; } if (sort_ascending) { return predicate (l) < predicate (r); } else { return predicate (r) < predicate (l); } } CPPLINQ_INLINEMETHOD return_type front () const { return sorted_values[current]; } CPPLINQ_METHOD bool next () { if (current == invalid_size) { sorted_values.clear (); while (range.forwarding_next ()) { sorted_values.push_back (range.forwarding_front ()); } if (sorted_values.size () == 0) { return false; } std::sort ( sorted_values.begin () , sorted_values.end () , [this] (value_type const & l, value_type const & r) { return this->compare_values (l,r); } ); current = 0U; return true; } if (current < sorted_values.size ()) { ++current; } return current < sorted_values.size (); } }; template struct thenby_builder : base_builder { typedef thenby_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; bool sort_ascending ; CPPLINQ_INLINEMETHOD explicit thenby_builder (predicate_type predicate, bool sort_ascending) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) , sort_ascending (sort_ascending) { } CPPLINQ_INLINEMETHOD thenby_builder (thenby_builder const & v) : predicate (v.predicate) , sort_ascending (v.sort_ascending) { } CPPLINQ_INLINEMETHOD thenby_builder (thenby_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) , sort_ascending (std::move (v.sort_ascending)) { } template CPPLINQ_INLINEMETHOD thenby_range build (TRange range) const { return thenby_range(std::move (range), predicate, sort_ascending); } }; // ------------------------------------------------------------------------- template struct reverse_range : base_range { typedef reverse_range this_type ; typedef TRange range_type ; typedef typename TRange::value_type value_type ; typedef value_type const & return_type ; typedef std::vector stack_type ; enum { returns_reference = 1 , }; range_type range ; size_type capacity ; std::vector reversed ; bool start ; CPPLINQ_INLINEMETHOD reverse_range ( range_type range , size_type capacity ) CPPLINQ_NOEXCEPT : range (std::move (range)) , capacity (capacity) , start (true) { } CPPLINQ_INLINEMETHOD reverse_range (reverse_range const & v) CPPLINQ_NOEXCEPT : range (v.range) , capacity (v.capacity) , reversed (v.reversed) , start (v.start) { } CPPLINQ_INLINEMETHOD reverse_range (reverse_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , capacity (std::move (v.capacity)) , reversed (std::move (v.reversed)) , start (std::move (v.start)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const CPPLINQ_NOEXCEPT { assert (!start); assert (!reversed.empty ()); return reversed[reversed.size () - 1]; } CPPLINQ_INLINEMETHOD bool next () { if (start) { start = false; reversed.clear (); reversed.reserve (capacity); while (range.next ()) { reversed.push_back (range.front ()); } return !reversed.empty (); } if (reversed.empty ()) { return false; } reversed.pop_back (); return !reversed.empty (); } }; struct reverse_builder : base_builder { typedef reverse_builder this_type ; size_type capacity ; CPPLINQ_INLINEMETHOD reverse_builder (size_type capacity) CPPLINQ_NOEXCEPT : capacity (capacity) { } CPPLINQ_INLINEMETHOD reverse_builder (reverse_builder const & v) CPPLINQ_NOEXCEPT : capacity (v.capacity) { } CPPLINQ_INLINEMETHOD reverse_builder (reverse_builder && v) CPPLINQ_NOEXCEPT : capacity (std::move (v.capacity)) { } template CPPLINQ_INLINEMETHOD reverse_range build (TRange range) const { return reverse_range (std::move (range), capacity); } }; // ------------------------------------------------------------------------- template struct where_range : base_range { typedef where_range this_type ; typedef TRange range_type ; typedef TPredicate predicate_type ; typedef typename TRange::value_type value_type ; typedef typename TRange::return_type return_type ; enum { returns_reference = TRange::returns_reference , }; range_type range ; predicate_type predicate ; CPPLINQ_INLINEMETHOD where_range ( range_type range , predicate_type predicate ) CPPLINQ_NOEXCEPT : range (std::move (range)) , predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD where_range (where_range const & v) : range (v.range) , predicate (v.predicate) { } CPPLINQ_INLINEMETHOD where_range (where_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return range.front (); } CPPLINQ_INLINEMETHOD bool next () { while (range.next ()) { if (predicate (range.front ())) { return true; } } return false; } }; template struct where_builder : base_builder { typedef where_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; CPPLINQ_INLINEMETHOD explicit where_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD where_builder (where_builder const & v) : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD where_builder (where_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD where_range build (TRange range) const { return where_range(std::move (range), predicate); } }; // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- template struct take_range : base_range { typedef take_range this_type ; typedef TRange range_type ; typedef typename TRange::value_type value_type ; typedef typename TRange::return_type return_type ; enum { returns_reference = TRange::returns_reference , }; range_type range ; size_type count ; size_type current ; CPPLINQ_INLINEMETHOD take_range ( range_type range , size_type count ) CPPLINQ_NOEXCEPT : range (std::move (range)) , count (std::move (count)) , current (0) { } CPPLINQ_INLINEMETHOD take_range (take_range const & v) : range (v.range) , count (v.count) , current (v.current) { } CPPLINQ_INLINEMETHOD take_range (take_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , count (std::move (v.count)) , current (std::move (v.current)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return range.front (); } CPPLINQ_INLINEMETHOD bool next () { if (current >= count) { return false; } ++current; return range.next (); } }; struct take_builder : base_builder { typedef take_builder this_type ; size_type count ; CPPLINQ_INLINEMETHOD explicit take_builder (size_type count) CPPLINQ_NOEXCEPT : count (std::move (count)) { } CPPLINQ_INLINEMETHOD take_builder (take_builder const & v) CPPLINQ_NOEXCEPT : count (v.count) { } CPPLINQ_INLINEMETHOD take_builder (take_builder && v) CPPLINQ_NOEXCEPT : count (std::move (v.count)) { } template CPPLINQ_INLINEMETHOD take_range build (TRange range) const { return take_range(std::move (range), count); } }; // ------------------------------------------------------------------------- template struct take_while_range : base_range { typedef take_while_range this_type ; typedef TRange range_type ; typedef TPredicate predicate_type ; typedef typename TRange::value_type value_type ; typedef typename TRange::return_type return_type ; enum { returns_reference = TRange::returns_reference , }; range_type range ; predicate_type predicate ; bool done ; CPPLINQ_INLINEMETHOD take_while_range ( range_type range , predicate_type predicate ) CPPLINQ_NOEXCEPT : range (std::move (range)) , predicate (std::move (predicate)) , done (false) { } CPPLINQ_INLINEMETHOD take_while_range (take_while_range const & v) : range (v.range) , predicate (v.predicate) , done (v.done) { } CPPLINQ_INLINEMETHOD take_while_range (take_while_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , predicate (std::move (v.predicate)) , done (std::move (v.done)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return range.front (); } CPPLINQ_INLINEMETHOD bool next () { if (done) { return false; } if (!range.next ()) { done = true; return false; } if (!predicate (range.front ())) { done = true; return false; } return true; } }; template struct take_while_builder : base_builder { typedef take_while_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; CPPLINQ_INLINEMETHOD take_while_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD take_while_builder (take_while_builder const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD take_while_builder (take_while_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD take_while_range build (TRange range) const { return take_while_range(std::move (range), predicate); } }; // ------------------------------------------------------------------------- template struct skip_range : base_range { typedef skip_range this_type ; typedef TRange range_type ; typedef typename TRange::value_type value_type ; typedef typename TRange::return_type return_type ; enum { returns_reference = TRange::returns_reference , }; range_type range ; size_type count ; size_type current ; CPPLINQ_INLINEMETHOD skip_range ( range_type range , size_type count ) CPPLINQ_NOEXCEPT : range (std::move (range)) , count (std::move (count)) , current (0) { } CPPLINQ_INLINEMETHOD skip_range (skip_range const & v) : range (v.range) , count (v.count) , current (v.current) { } CPPLINQ_INLINEMETHOD skip_range (skip_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , count (std::move (v.count)) , current (std::move (v.current)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return range.front (); } CPPLINQ_INLINEMETHOD bool next () { if (current == invalid_size) { return false; } while (current < count && range.next ()) { ++current; } if (current < count) { current = invalid_size; return false; } return range.next (); } }; struct skip_builder : base_builder { typedef skip_builder this_type ; size_type count ; CPPLINQ_INLINEMETHOD explicit skip_builder (size_type count) CPPLINQ_NOEXCEPT : count (std::move (count)) { } CPPLINQ_INLINEMETHOD skip_builder (skip_builder const & v) CPPLINQ_NOEXCEPT : count (v.count) { } CPPLINQ_INLINEMETHOD skip_builder (skip_builder && v) CPPLINQ_NOEXCEPT : count (std::move (v.count)) { } template CPPLINQ_INLINEMETHOD skip_range build (TRange range) const { return skip_range(std::move (range), count); } }; // ------------------------------------------------------------------------- template struct skip_while_range : base_range { typedef skip_while_range this_type ; typedef TRange range_type ; typedef TPredicate predicate_type ; typedef typename TRange::value_type value_type ; typedef typename TRange::return_type return_type ; enum { returns_reference = TRange::returns_reference , }; range_type range ; predicate_type predicate ; bool skipping ; CPPLINQ_INLINEMETHOD skip_while_range ( range_type range , predicate_type predicate ) CPPLINQ_NOEXCEPT : range (std::move (range)) , predicate (std::move (predicate)) , skipping (true) { } CPPLINQ_INLINEMETHOD skip_while_range (skip_while_range const & v) : range (v.range) , predicate (v.predicate) , skipping (v.skipping) { } CPPLINQ_INLINEMETHOD skip_while_range (skip_while_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , predicate (std::move (v.predicate)) , skipping (std::move (v.skipping)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return range.front (); } CPPLINQ_INLINEMETHOD bool next () { if (!skipping) { return range.next (); } while (range.next ()) { if (!predicate (range.front ())) { skipping = false; return true; } } return false; } }; template struct skip_while_builder : base_builder { typedef skip_while_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; CPPLINQ_INLINEMETHOD skip_while_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD skip_while_builder (skip_while_builder const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD skip_while_builder (skip_while_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD skip_while_range build (TRange range) const { return skip_while_range(std::move (range), predicate); } }; // ------------------------------------------------------------------------- template struct ref_range : base_range { typedef std::reference_wrapper< typename TRange::value_type const> value_type ; typedef value_type return_type ; enum { returns_reference = 0 , }; typedef ref_range this_type ; typedef TRange range_type ; range_type range ; CPPLINQ_INLINEMETHOD ref_range ( range_type range ) CPPLINQ_NOEXCEPT : range (std::move (range)) { static_assert ( TRange::returns_reference , "ref may only follow a range that returns references" ); } CPPLINQ_INLINEMETHOD ref_range (ref_range const & v) : range (v.range) { } CPPLINQ_INLINEMETHOD ref_range (ref_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return value_type (range.front ()); } CPPLINQ_INLINEMETHOD bool next () { return range.next (); } }; struct ref_builder : base_builder { typedef ref_builder this_type ; CPPLINQ_INLINEMETHOD ref_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD ref_builder (ref_builder const & v) { } CPPLINQ_INLINEMETHOD ref_builder (ref_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD ref_range build (TRange range) const { return ref_range(std::move (range)); } }; // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- template struct select_range : base_range { static typename TRange::value_type get_source (); static TPredicate get_predicate (); typedef decltype (get_predicate ()(get_source ())) raw_value_type ; typedef typename cleanup_type::type value_type ; typedef value_type return_type ; enum { returns_reference = 0 , }; typedef select_range this_type ; typedef TRange range_type ; typedef TPredicate predicate_type ; range_type range ; predicate_type predicate ; CPPLINQ_INLINEMETHOD select_range ( range_type range , predicate_type predicate ) CPPLINQ_NOEXCEPT : range (std::move (range)) , predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD select_range (select_range const & v) : range (v.range) , predicate (v.predicate) { } CPPLINQ_INLINEMETHOD select_range (select_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return predicate (range.front ()); } CPPLINQ_INLINEMETHOD bool next () { return range.next (); } }; template struct select_builder : base_builder { typedef select_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; CPPLINQ_INLINEMETHOD explicit select_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD select_builder (select_builder const & v) : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD select_builder (select_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD select_range build (TRange range) const { return select_range(std::move (range), predicate); } }; // ------------------------------------------------------------------------- // Some trickery in order to force the code to compile on VS2012 template struct select_many_range_helper { static typename TRange::value_type get_source (); static TPredicate get_predicate (); typedef decltype (get_predicate ()(get_source ())) raw_inner_range_type ; typedef typename cleanup_type::type inner_range_type ; static inner_range_type get_inner_range (); typedef decltype (get_inner_range ().front ()) raw_value_type ; typedef typename cleanup_type::type value_type ; }; template struct select_many_range : base_range { typedef select_many_range_helper helper_type ; typedef typename helper_type::inner_range_type inner_range_type ; typedef typename helper_type::value_type value_type ; typedef value_type return_type ; enum { returns_reference = 0 , }; typedef select_many_range this_type ; typedef TRange range_type ; typedef TPredicate predicate_type ; range_type range ; predicate_type predicate ; opt inner_range ; CPPLINQ_INLINEMETHOD select_many_range ( range_type range , predicate_type predicate ) CPPLINQ_NOEXCEPT : range (std::move (range)) , predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD select_many_range (select_many_range const & v) : range (v.range) , predicate (v.predicate) , inner_range (v.inner_range) { } CPPLINQ_INLINEMETHOD select_many_range (select_many_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , predicate (std::move (v.predicate)) , inner_range (std::move (v.inner_range)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { assert (inner_range); return inner_range->front (); } CPPLINQ_INLINEMETHOD bool next () { if (inner_range && inner_range->next ()) { return true; } if (range.next ()) { inner_range = predicate (range.front ()); return inner_range && inner_range->next (); } return false; } }; template struct select_many_builder : base_builder { typedef select_many_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; CPPLINQ_INLINEMETHOD explicit select_many_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD select_many_builder (select_many_builder const & v) : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD select_many_builder (select_many_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD select_many_range build (TRange range) const { return select_many_range(std::move (range), predicate); } }; // ------------------------------------------------------------------------- template< typename TRange , typename TOtherRange , typename TKeySelector , typename TOtherKeySelector , typename TCombiner > struct join_range : base_range { static typename TRange::value_type get_source () ; static typename TOtherRange::value_type get_other_source () ; static TKeySelector get_key_selector () ; static TOtherKeySelector get_other_key_selector () ; static TCombiner get_combiner () ; typedef decltype (get_key_selector () (get_source ())) raw_key_type ; typedef typename cleanup_type::type key_type ; typedef decltype (get_other_key_selector () (get_other_source ())) raw_other_key_type ; typedef typename cleanup_type::type other_key_type ; typedef decltype (get_combiner () (get_source (), get_other_source ())) raw_value_type ; typedef typename cleanup_type::type value_type ; typedef value_type return_type ; enum { returns_reference = 0 , }; typedef join_range< TRange , TOtherRange , TKeySelector , TOtherKeySelector , TCombiner > this_type ; typedef TRange range_type ; typedef TOtherRange other_range_type ; typedef TKeySelector key_selector_type ; typedef TOtherKeySelector other_key_selector_type ; typedef TCombiner combiner_type ; typedef std::multimap< other_key_type , typename TOtherRange::value_type > map_type ; typedef typename map_type::const_iterator map_iterator_type ; range_type range ; other_range_type other_range ; key_selector_type key_selector ; other_key_selector_type other_key_selector ; combiner_type combiner ; bool start ; map_type map ; map_iterator_type current ; CPPLINQ_INLINEMETHOD join_range ( range_type range , other_range_type other_range , key_selector_type key_selector , other_key_selector_type other_key_selector , combiner_type combiner ) CPPLINQ_NOEXCEPT : range (std::move (range)) , other_range (std::move (other_range)) , key_selector (std::move (key_selector)) , other_key_selector (std::move (other_key_selector)) , combiner (std::move (combiner)) , start (true) { } CPPLINQ_INLINEMETHOD join_range (join_range const & v) : range (v.range) , other_range (v.other_range) , key_selector (v.key_selector) , other_key_selector (v.other_key_selector) , combiner (v.combiner) , start (v.start) , map (v.map) , current (v.current) { } CPPLINQ_INLINEMETHOD join_range (join_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , other_range (std::move (v.other_range)) , key_selector (std::move (v.key_selector)) , other_key_selector (std::move (v.other_key_selector)) , combiner (std::move (v.combiner)) , start (std::move (v.start)) , map (std::move (v.map)) , current (std::move (v.current)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { assert (current != map.end ()); return combiner (range.front (), current->second); } CPPLINQ_INLINEMETHOD bool next () { if (start) { start = false; while (other_range.next ()) { auto other_value = other_range.front (); auto other_key = other_key_selector (other_value); map.insert (typename map_type::value_type (std::move (other_key), std::move (other_value))); } current = map.end (); if (map.size () == 0U) { return false; } } if (current != map.end ()) { auto previous = current; ++current; if (current != map.end () && !(previous->first < current->first)) { return true; } } while (range.next ()) { auto value = range.front (); auto key = key_selector (value); current = map.find (key); if (current != map.end ()) { return true; } } return false; } }; template< typename TOtherRange , typename TKeySelector , typename TOtherKeySelector , typename TCombiner > struct join_builder : base_builder { typedef join_builder< TOtherRange , TKeySelector , TOtherKeySelector , TCombiner > this_type ; typedef TOtherRange other_range_type ; typedef TKeySelector key_selector_type ; typedef TOtherKeySelector other_key_selector_type ; typedef TCombiner combiner_type ; other_range_type other_range ; key_selector_type key_selector ; other_key_selector_type other_key_selector ; combiner_type combiner ; CPPLINQ_INLINEMETHOD join_builder ( other_range_type other_range , key_selector_type key_selector , other_key_selector_type other_key_selector , combiner_type combiner ) CPPLINQ_NOEXCEPT : other_range (std::move (other_range)) , key_selector (std::move (key_selector)) , other_key_selector (std::move (other_key_selector)) , combiner (std::move (combiner)) { } CPPLINQ_INLINEMETHOD join_builder (join_builder const & v) : other_range (v.other_range) , key_selector (v.key_selector) , other_key_selector (v.other_key_selector) , combiner (v.combiner) { } CPPLINQ_INLINEMETHOD join_builder (join_builder && v) CPPLINQ_NOEXCEPT : other_range (std::move (v.other_range)) , key_selector (std::move (v.key_selector)) , other_key_selector (std::move (v.other_key_selector)) , combiner (std::move (v.combiner)) { } template CPPLINQ_INLINEMETHOD join_range build (TRange range) const { return join_range ( std::move (range) , other_range , key_selector , other_key_selector , combiner ); } }; // ------------------------------------------------------------------------- template struct distinct_range : base_range { typedef distinct_range this_type ; typedef TRange range_type ; typedef typename cleanup_type::type value_type ; typedef value_type const & return_type ; enum { returns_reference = 1 , }; typedef std::set set_type ; typedef typename set_type::const_iterator set_iterator_type ; range_type range ; set_type set ; set_iterator_type current ; CPPLINQ_INLINEMETHOD distinct_range ( range_type range ) CPPLINQ_NOEXCEPT : range (std::move (range)) { } CPPLINQ_INLINEMETHOD distinct_range (distinct_range const & v) CPPLINQ_NOEXCEPT : range (v.range) , set (v.set) , current (v.current) { } CPPLINQ_INLINEMETHOD distinct_range (distinct_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , set (std::move (v.set)) , current (std::move (v.current)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return *current; } CPPLINQ_INLINEMETHOD bool next () { while (range.next ()) { auto result = set.insert (range.front ()); if (result.second) { current = result.first; return true; } } return false; } }; struct distinct_builder : base_builder { typedef distinct_builder this_type ; CPPLINQ_INLINEMETHOD distinct_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD distinct_builder (distinct_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD distinct_builder (distinct_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD distinct_range build (TRange range) const { return distinct_range (std::move (range)); } }; // ------------------------------------------------------------------------- template struct union_range : base_range { typedef union_range this_type ; typedef TRange range_type ; typedef TOtherRange other_range_type ; typedef typename cleanup_type::type value_type ; typedef value_type const & return_type ; enum { returns_reference = 1 , }; typedef std::set set_type ; typedef typename set_type::const_iterator set_iterator_type ; range_type range ; other_range_type other_range ; set_type set ; set_iterator_type current ; CPPLINQ_INLINEMETHOD union_range ( range_type range , other_range_type other_range ) CPPLINQ_NOEXCEPT : range (std::move (range)) , other_range (std::move (other_range)) { } CPPLINQ_INLINEMETHOD union_range (union_range const & v) CPPLINQ_NOEXCEPT : range (v.range) , other_range (v.other_range) , set (v.set) , current (v.current) { } CPPLINQ_INLINEMETHOD union_range (union_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , other_range (std::move (v.other_range)) , set (std::move (v.set)) , current (std::move (v.current)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return *current; } CPPLINQ_INLINEMETHOD bool next () { while (range.next ()) { auto result = set.insert (range.front ()); if (result.second) { current = result.first; return true; } } while (other_range.next ()) { auto result = set.insert (other_range.front ()); if (result.second) { current = result.first; return true; } } return false; } }; template struct union_builder : base_builder { typedef union_builder this_type ; typedef TOtherRange other_range_type; other_range_type other_range ; CPPLINQ_INLINEMETHOD union_builder (TOtherRange other_range) CPPLINQ_NOEXCEPT : other_range (std::move (other_range)) { } CPPLINQ_INLINEMETHOD union_builder (union_builder const & v) CPPLINQ_NOEXCEPT : other_range (v.other_range) { } CPPLINQ_INLINEMETHOD union_builder (union_builder && v) CPPLINQ_NOEXCEPT : other_range (std::move (v.other_range)) { } template CPPLINQ_INLINEMETHOD union_range build (TRange range) const { return union_range (std::move (range), std::move (other_range)); } }; // ------------------------------------------------------------------------- template struct intersect_range : base_range { typedef intersect_range this_type ; typedef TRange range_type ; typedef TOtherRange other_range_type ; typedef typename cleanup_type::type value_type ; typedef value_type const & return_type ; enum { returns_reference = 1 , }; typedef std::set set_type ; typedef typename set_type::const_iterator set_iterator_type ; range_type range ; other_range_type other_range ; set_type set ; set_iterator_type current ; bool start ; CPPLINQ_INLINEMETHOD intersect_range ( range_type range , other_range_type other_range ) CPPLINQ_NOEXCEPT : range (std::move (range)) , other_range (std::move (other_range)) , start (true) { } CPPLINQ_INLINEMETHOD intersect_range (intersect_range const & v) CPPLINQ_NOEXCEPT : range (v.range) , other_range (v.other_range) , set (v.set) , current (v.current) , start (v.start) { } CPPLINQ_INLINEMETHOD intersect_range (intersect_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , other_range (std::move (v.other_range)) , set (std::move (v.set)) , current (std::move (v.current)) , start (std::move (v.start)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { assert (!start); return *current; } CPPLINQ_INLINEMETHOD bool next () { if (start) { start = false; while (other_range.next ()) { set.insert (other_range.front ()); } while (range.next ()) { current = set.find (range.front ()); if (current != set.end ()) { return true; } } set.clear (); return false; } if (set.empty ()) { return false; } set.erase (current); while (range.next ()) { current = set.find (range.front ()); if (current != set.end ()) { return true; } } return false; } }; template struct intersect_builder : base_builder { typedef intersect_builder this_type ; typedef TOtherRange other_range_type; other_range_type other_range ; CPPLINQ_INLINEMETHOD intersect_builder (TOtherRange other_range) CPPLINQ_NOEXCEPT : other_range (std::move (other_range)) { } CPPLINQ_INLINEMETHOD intersect_builder (intersect_builder const & v) CPPLINQ_NOEXCEPT : other_range (v.other_range) { } CPPLINQ_INLINEMETHOD intersect_builder (intersect_builder && v) CPPLINQ_NOEXCEPT : other_range (std::move (v.other_range)) { } template CPPLINQ_INLINEMETHOD intersect_range build (TRange range) const { return intersect_range (std::move (range), std::move (other_range)); } }; // ------------------------------------------------------------------------- template struct except_range : base_range { typedef except_range this_type ; typedef TRange range_type ; typedef TOtherRange other_range_type ; typedef typename cleanup_type::type value_type ; typedef value_type const & return_type ; enum { returns_reference = 1 , }; typedef std::set set_type ; typedef typename set_type::const_iterator set_iterator_type ; range_type range ; other_range_type other_range ; set_type set ; set_iterator_type current ; bool start ; CPPLINQ_INLINEMETHOD except_range ( range_type range , other_range_type other_range ) CPPLINQ_NOEXCEPT : range (std::move (range)) , other_range (std::move (other_range)) , start (true) { } CPPLINQ_INLINEMETHOD except_range (except_range const & v) CPPLINQ_NOEXCEPT : range (v.range) , other_range (v.other_range) , set (v.set) , current (v.current) , start (v.start) { } CPPLINQ_INLINEMETHOD except_range (except_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , other_range (std::move (v.other_range)) , set (std::move (v.set)) , current (std::move (v.current)) , start (std::move (v.start)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return *current; } CPPLINQ_INLINEMETHOD bool next () { if (start) { start = false; while (other_range.next ()) { set.insert (other_range.front ()); } } while (range.next ()) { auto result = set.insert (range.front ()); if (result.second) { current = result.first; return true; } } return false; } }; template struct except_builder : base_builder { typedef union_builder this_type ; typedef TOtherRange other_range_type; other_range_type other_range ; CPPLINQ_INLINEMETHOD except_builder (TOtherRange other_range) CPPLINQ_NOEXCEPT : other_range (std::move (other_range)) { } CPPLINQ_INLINEMETHOD except_builder (except_builder const & v) CPPLINQ_NOEXCEPT : other_range (v.other_range) { } CPPLINQ_INLINEMETHOD except_builder (except_builder && v) CPPLINQ_NOEXCEPT : other_range (std::move (v.other_range)) { } template CPPLINQ_INLINEMETHOD except_range build (TRange range) const { return except_range (std::move (range), std::move (other_range)); } }; // ------------------------------------------------------------------------- template struct concat_range : base_range { typedef concat_range this_type ; typedef TRange range_type ; typedef TOtherRange other_range_type ; typedef typename cleanup_type::type value_type ; typedef typename cleanup_type::type other_value_type ; typedef value_type return_type ; enum { returns_reference = 0 , }; enum state { state_initial , state_iterating_range , state_iterating_other_range , state_end , }; range_type range ; other_range_type other_range ; state state ; CPPLINQ_INLINEMETHOD concat_range ( range_type range , other_range_type other_range ) CPPLINQ_NOEXCEPT : range (std::move (range)) , other_range (std::move (other_range)) , state (state_initial) { } CPPLINQ_INLINEMETHOD concat_range (concat_range const & v) CPPLINQ_NOEXCEPT : range (v.range) , other_range (v.other_range) , state (v.state) { } CPPLINQ_INLINEMETHOD concat_range (concat_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , other_range (std::move (v.other_range)) , state (std::move (v.state)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { switch (state) { case state_initial: case state_end: default: assert (false); // Intentionally falls through case state_iterating_range: return range.front (); case state_iterating_other_range: return other_range.front (); }; } CPPLINQ_INLINEMETHOD bool next () { switch (state) { case state_initial: if (range.next ()) { state = state_iterating_range; return true; } if (other_range.next ()) { state = state_iterating_other_range; return true; } return false; case state_iterating_range: if (range.next ()) { return true; } if (other_range.next ()) { state = state_iterating_other_range; return true; } return false; case state_iterating_other_range: if (other_range.next ()) { return true; } return false; case state_end: default: return false; } } }; template struct concat_builder : base_builder { typedef concat_builder this_type ; typedef TOtherRange other_range_type; other_range_type other_range ; CPPLINQ_INLINEMETHOD concat_builder (TOtherRange other_range) CPPLINQ_NOEXCEPT : other_range (std::move (other_range)) { } CPPLINQ_INLINEMETHOD concat_builder (concat_builder const & v) CPPLINQ_NOEXCEPT : other_range (v.other_range) { } CPPLINQ_INLINEMETHOD concat_builder (concat_builder && v) CPPLINQ_NOEXCEPT : other_range (std::move (v.other_range)) { } template CPPLINQ_INLINEMETHOD concat_range build (TRange range) const { return concat_range (std::move (range), std::move (other_range)); } }; // ------------------------------------------------------------------------- namespace experimental { // ------------------------------------------------------------------------- // TODO: Verify that container range aggregator has the right semantics template struct container_iterator { typedef std::forward_iterator_tag iterator_category ; typedef typename TRange::value_type value_type ; typedef typename TRange::return_type return_type ; enum { returns_reference = TRange::returns_reference , }; typedef std::ptrdiff_t difference_type ; typedef value_type* pointer ; typedef value_type& reference ; typedef container_iterator this_type ; typedef TRange range_type ; bool has_value ; opt range ; CPPLINQ_INLINEMETHOD container_iterator () CPPLINQ_NOEXCEPT : has_value (false) { } CPPLINQ_INLINEMETHOD container_iterator (range_type r) CPPLINQ_NOEXCEPT : range (std::move (r)) { has_value = range && range->next (); } CPPLINQ_INLINEMETHOD container_iterator (container_iterator const & v) CPPLINQ_NOEXCEPT : has_value (v.has_value) , range (v.range) { } CPPLINQ_INLINEMETHOD container_iterator (container_iterator && v) CPPLINQ_NOEXCEPT : has_value (std::move (v.has_value)) , range (std::move (v.range)) { } CPPLINQ_INLINEMETHOD return_type operator* () const { assert (has_value); assert (range); return range->front (); } CPPLINQ_INLINEMETHOD value_type const * operator-> () const { static_assert ( returns_reference , "operator-> requires a range that returns a reference, typically select causes ranges to return values not references" ); return &range->front (); } CPPLINQ_INLINEMETHOD this_type & operator++() { if (has_value && range) { has_value = range->next (); } return *this; } CPPLINQ_INLINEMETHOD bool operator== (this_type const & v) const CPPLINQ_NOEXCEPT { if (!has_value && !v.has_value) { return true; } else if (has_value && has_value && range.get_ptr () == v.range.get_ptr ()) { return true; } else { return false; } } CPPLINQ_INLINEMETHOD bool operator!= (this_type const & v) const CPPLINQ_NOEXCEPT { return !(*this == v); } }; template struct container { typedef container this_type ; typedef TRange range_type ; typedef typename TRange::value_type value_type ; typedef typename TRange::return_type return_type ; enum { returns_reference = TRange::returns_reference , }; range_type range ; CPPLINQ_INLINEMETHOD explicit container (TRange range) : range (std::move (range)) { } CPPLINQ_INLINEMETHOD container (container const & v) CPPLINQ_NOEXCEPT : range (v.range) { } CPPLINQ_INLINEMETHOD container (container && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) { } CPPLINQ_INLINEMETHOD container_iterator begin () CPPLINQ_NOEXCEPT { return container_iterator(range); } CPPLINQ_INLINEMETHOD container_iterator end () CPPLINQ_NOEXCEPT { return container_iterator(); } }; struct container_builder : base_builder { typedef container_builder this_type ; CPPLINQ_INLINEMETHOD container_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD container_builder (container_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD container_builder (container_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_METHOD container build (TRange range) const { return container (std::move (range)); } }; } // ------------------------------------------------------------------------- struct to_vector_builder : base_builder { typedef to_vector_builder this_type ; size_type capacity; CPPLINQ_INLINEMETHOD explicit to_vector_builder (size_type capacity = 16U) CPPLINQ_NOEXCEPT : capacity (capacity) { } CPPLINQ_INLINEMETHOD to_vector_builder (to_vector_builder const & v) CPPLINQ_NOEXCEPT : capacity (v.capacity) { } CPPLINQ_INLINEMETHOD to_vector_builder (to_vector_builder && v) CPPLINQ_NOEXCEPT : capacity (std::move (v.capacity)) { } template CPPLINQ_METHOD std::vector build (TRange range) const { std::vector result; result.reserve (capacity); while (range.next ()) { result.push_back (range.front ()); } return result; } }; struct to_list_builder : base_builder { typedef to_list_builder this_type ; CPPLINQ_INLINEMETHOD explicit to_list_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD to_list_builder (to_list_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD to_list_builder (to_list_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_METHOD std::list build (TRange range) const { std::list result; while (range.next ()) { result.push_back (range.front ()); } return result; } }; // ------------------------------------------------------------------------- template struct to_map_builder : base_builder { static TKeyPredicate get_key_predicate (); typedef to_map_builder this_type ; typedef TKeyPredicate key_predicate_type ; key_predicate_type key_predicate ; CPPLINQ_INLINEMETHOD explicit to_map_builder (key_predicate_type key_predicate) CPPLINQ_NOEXCEPT : key_predicate (std::move (key_predicate)) { } CPPLINQ_INLINEMETHOD to_map_builder (to_map_builder const & v) : key_predicate (v.key_predicate) { } CPPLINQ_INLINEMETHOD to_map_builder (to_map_builder && v) CPPLINQ_NOEXCEPT : key_predicate (std::move (v.key_predicate)) { } template CPPLINQ_METHOD std::map< typename get_transformed_type::type , typename TRange::value_type > build (TRange range) const { typedef std::map< typename get_transformed_type::type , typename TRange::value_type > result_type; result_type result; while (range.next ()) { auto v = range.front (); auto k = key_predicate (v); result.insert (typename result_type::value_type (std::move (k), std::move (v))); } return result; } }; // ------------------------------------------------------------------------- template struct lookup { typedef TKey key_type ; typedef TValue value_type ; typedef std::vector> keys_type ; typedef std::vector values_type ; typedef typename values_type::const_iterator values_iterator_type; template CPPLINQ_METHOD lookup (size_type capacity, TRange range, TSelector selector) { keys_type k; values_type v; k.reserve (capacity); v.reserve (capacity); auto index = 0U; while (range.next ()) { auto value = range.front (); auto key = selector (value); v.push_back (std::move (value)); k.push_back (typename keys_type::value_type (std::move (key), index)); ++index; } if (v.size () == 0) { return; } std::sort ( k.begin () , k.end () , [] (typename keys_type::value_type const & l, typename keys_type::value_type const & r) { return l.first < r.first; } ); keys.reserve (k.size ()); values.reserve (v.size ()); auto iter = k.begin (); auto end = k.end (); index = 0U; if (iter != end) { values.push_back (std::move (v[iter->second])); keys.push_back (typename keys_type::value_type (iter->first, index)); } auto previous = iter; ++iter; ++index; while (iter != end) { values.push_back (v[iter->second]); if (previous->first < iter->first) { keys.push_back (typename keys_type::value_type (iter->first, index)); } previous = iter; ++iter; ++index; } } CPPLINQ_INLINEMETHOD lookup (lookup const & v) : values (v.values) , keys (v.keys) { } CPPLINQ_INLINEMETHOD lookup (lookup && v) CPPLINQ_NOEXCEPT : values (std::move (v.values)) , keys (std::move (v.keys)) { } CPPLINQ_INLINEMETHOD void swap (lookup & v) CPPLINQ_NOEXCEPT { values.swap (v.values); keys.swap (v.keys); } CPPLINQ_INLINEMETHOD lookup & operator= (lookup const & v) { if (this == std::addressof (v)) { return *this; } lookup tmp (v); swap (tmp); return *this; } CPPLINQ_INLINEMETHOD lookup & operator= (lookup && v) CPPLINQ_NOEXCEPT { if (this == std::addressof (v)) { return *this; } swap (v); return *this; } struct lookup_range : base_range { typedef lookup_range this_type ; enum { returns_reference = 1 , }; typedef TValue value_type ; typedef value_type const & return_type ; enum state { state_initial , state_iterating , state_end , }; values_type const * values ; size_type iter ; size_type end ; state state ; CPPLINQ_INLINEMETHOD lookup_range ( values_type const * values , size_type iter , size_type end ) CPPLINQ_NOEXCEPT : values (values) , iter (iter) , end (end) , state (state_initial) { assert (values); } CPPLINQ_INLINEMETHOD lookup_range (lookup_range const & v) CPPLINQ_NOEXCEPT : values (v.values) , iter (v.iter) , end (v.end) , state (v.state) { } CPPLINQ_INLINEMETHOD lookup_range (lookup_range && v) CPPLINQ_NOEXCEPT : values (std::move (v.values)) , iter (std::move (v.iter)) , end (std::move (v.end)) , state (std::move (v.state)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const CPPLINQ_NOEXCEPT { assert (state == state_iterating); assert (iter < end); return (*values)[iter]; } CPPLINQ_INLINEMETHOD bool next () CPPLINQ_NOEXCEPT { switch (state) { case state_initial: { auto has_elements = iter < end; state = has_elements ? state_iterating : state_end; return has_elements; } break; case state_iterating: { ++iter; auto has_elements = iter < end; state = has_elements ? state_iterating : state_end; return has_elements; } break; case state_end: default: return false; } } }; CPPLINQ_METHOD lookup_range operator[](key_type const & key) const CPPLINQ_NOEXCEPT { if (values.empty ()) { return lookup_range (std::addressof (values), 0U, 0U); } if (keys.empty ()) { return lookup_range (std::addressof (values), 0U, 0U); } auto find = std::lower_bound ( keys.begin () , keys.end () , typename keys_type::value_type (key, 0U) , [](typename keys_type::value_type const & l, typename keys_type::value_type const & r) { return l.first < r.first; }); if (find == keys.end ()) { return lookup_range (std::addressof (values), 0U, 0U); } auto next = find + 1; if (next == keys.end ()) { return lookup_range (std::addressof (values), find->second, values.size ()); } return lookup_range (std::addressof (values), find->second, next->second); } CPPLINQ_INLINEMETHOD size_type size_of_keys () const CPPLINQ_NOEXCEPT { return keys.size (); } CPPLINQ_INLINEMETHOD size_type size_of_values () const CPPLINQ_NOEXCEPT { return values.size (); } CPPLINQ_INLINEMETHOD from_range range_of_values () const CPPLINQ_NOEXCEPT { return from_range ( values.begin () , values.end () ); } private: values_type values ; keys_type keys ; }; template struct to_lookup_builder : base_builder { static TKeyPredicate get_key_predicate (); typedef to_lookup_builder this_type ; typedef TKeyPredicate key_predicate_type ; key_predicate_type key_predicate ; CPPLINQ_INLINEMETHOD explicit to_lookup_builder (key_predicate_type key_predicate) CPPLINQ_NOEXCEPT : key_predicate (std::move (key_predicate)) { } CPPLINQ_INLINEMETHOD to_lookup_builder (to_lookup_builder const & v) : key_predicate (v.key_predicate) { } CPPLINQ_INLINEMETHOD to_lookup_builder (to_lookup_builder && v) CPPLINQ_NOEXCEPT : key_predicate (std::move (v.key_predicate)) { } template CPPLINQ_INLINEMETHOD lookup< typename get_transformed_type::type , typename TRange::value_type > build (TRange range) const { typedef lookup< typename get_transformed_type::type , typename TRange::value_type > result_type; result_type result (16U, range, key_predicate); return result; } }; // ------------------------------------------------------------------------- template struct for_each_builder : base_builder { typedef for_each_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate; CPPLINQ_INLINEMETHOD explicit for_each_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD for_each_builder (for_each_builder const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD for_each_builder (for_each_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD void build (TRange range) const { while (range.next ()) { predicate (range.front ()); } } }; // ------------------------------------------------------------------------- template struct first_predicate_builder : base_builder { typedef first_predicate_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; CPPLINQ_INLINEMETHOD first_predicate_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD first_predicate_builder (first_predicate_builder const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD first_predicate_builder (first_predicate_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD typename TRange::return_type build (TRange range) { while (range.next ()) { if (predicate (range.front ())) { return range.front (); } } throw sequence_empty_exception (); } }; // ------------------------------------------------------------------------- struct first_builder : base_builder { typedef first_builder this_type ; CPPLINQ_INLINEMETHOD first_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD first_builder (first_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD first_builder (first_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD typename TRange::return_type build (TRange range) { if (range.next ()) { return range.front (); } throw sequence_empty_exception (); } }; // ------------------------------------------------------------------------- template struct first_or_default_predicate_builder : base_builder { typedef first_or_default_predicate_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate; CPPLINQ_INLINEMETHOD first_or_default_predicate_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD first_or_default_predicate_builder (first_or_default_predicate_builder const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD first_or_default_predicate_builder (first_or_default_predicate_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { while (range.next ()) { if (predicate (range.front ())) { return range.front (); } } return typename TRange::value_type (); } }; struct first_or_default_builder : base_builder { typedef first_or_default_builder this_type ; CPPLINQ_INLINEMETHOD first_or_default_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD first_or_default_builder (first_or_default_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD first_or_default_builder (first_or_default_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { if (range.next ()) { return range.front (); } return typename TRange::value_type (); } }; // ------------------------------------------------------------------------- template struct last_or_default_predicate_builder : base_builder { typedef last_or_default_predicate_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate; CPPLINQ_INLINEMETHOD last_or_default_predicate_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD last_or_default_predicate_builder (last_or_default_predicate_builder const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD last_or_default_predicate_builder (last_or_default_predicate_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto current = typename TRange::value_type (); while (range.next ()) { if (predicate (range.front ())) { current = std::move (range.front ()); } } return current; } }; struct last_or_default_builder : base_builder { typedef last_or_default_builder this_type ; CPPLINQ_INLINEMETHOD last_or_default_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD last_or_default_builder (last_or_default_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD last_or_default_builder (last_or_default_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto current = typename TRange::value_type (); while (range.next ()) { current = std::move (range.front ()); } return current; } }; // ------------------------------------------------------------------------- template struct count_predicate_builder : base_builder { typedef count_predicate_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; CPPLINQ_INLINEMETHOD count_predicate_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD count_predicate_builder (count_predicate_builder const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD count_predicate_builder (count_predicate_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD size_type build (TRange range) const { size_type count = 0U; while (range.next ()) { if (predicate (range.front ())) { ++count; } } return count; } }; struct count_builder : base_builder { typedef count_builder this_type ; CPPLINQ_INLINEMETHOD count_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD count_builder (count_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD count_builder (count_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD size_type build (TRange range) const { size_type count = 0U; while (range.next ()) { ++count; } return count; } }; // ------------------------------------------------------------------------- template struct sum_selector_builder : base_builder { typedef sum_selector_builder this_type ; typedef TSelector selector_type ; selector_type selector; CPPLINQ_INLINEMETHOD sum_selector_builder (selector_type selector) CPPLINQ_NOEXCEPT : selector (std::move (selector)) { } CPPLINQ_INLINEMETHOD sum_selector_builder (sum_selector_builder const & v) CPPLINQ_NOEXCEPT : selector (v.selector) { } CPPLINQ_INLINEMETHOD sum_selector_builder (sum_selector_builder && v) CPPLINQ_NOEXCEPT : selector (std::move (v.selector)) { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto sum = typename TRange::value_type (); while (range.next ()) { sum += selector (range.front ()); } return sum; } }; struct sum_builder : base_builder { typedef sum_builder this_type ; CPPLINQ_INLINEMETHOD sum_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD sum_builder (sum_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD sum_builder (sum_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto sum = typename TRange::value_type (); while (range.next ()) { sum += range.front (); } return sum; } }; // ------------------------------------------------------------------------- template struct max_selector_builder : base_builder { typedef max_selector_builder this_type ; typedef TSelector selector_type ; selector_type selector; CPPLINQ_INLINEMETHOD max_selector_builder (selector_type selector) CPPLINQ_NOEXCEPT : selector (std::move (selector)) { } CPPLINQ_INLINEMETHOD max_selector_builder (max_selector_builder const & v) CPPLINQ_NOEXCEPT : selector (v.selector) { } CPPLINQ_INLINEMETHOD max_selector_builder (max_selector_builder && v) CPPLINQ_NOEXCEPT : selector (std::move (v.selector)) { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto current = std::numeric_limits::min (); while (range.next ()) { auto v = selector (range.front ()); if (current < v) { current = std::move (v); } } return current; } }; struct max_builder : base_builder { typedef max_builder this_type ; CPPLINQ_INLINEMETHOD max_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD max_builder (max_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD max_builder (max_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto current = std::numeric_limits::min (); while (range.next ()) { auto v = range.front (); if (current < v) { current = std::move (v); } } return current; } }; // ------------------------------------------------------------------------- template struct min_selector_builder : base_builder { typedef min_selector_builder this_type ; typedef TSelector selector_type ; selector_type selector; CPPLINQ_INLINEMETHOD min_selector_builder (selector_type selector) CPPLINQ_NOEXCEPT : selector (std::move (selector)) { } CPPLINQ_INLINEMETHOD min_selector_builder (min_selector_builder const & v) CPPLINQ_NOEXCEPT : selector (v.selector) { } CPPLINQ_INLINEMETHOD min_selector_builder (min_selector_builder && v) CPPLINQ_NOEXCEPT : selector (std::move (v.selector)) { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto current = std::numeric_limits::max (); while (range.next ()) { auto v = selector (range.front ()); if (v < current) { current = std::move (v); } } return current; } }; struct min_builder : base_builder { typedef min_builder this_type ; CPPLINQ_INLINEMETHOD min_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD min_builder (min_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD min_builder (min_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto current = std::numeric_limits::max (); while (range.next ()) { auto v = range.front (); if (v < current) { current = std::move (v); } } return current; } }; // ------------------------------------------------------------------------- template struct avg_selector_builder : base_builder { typedef avg_selector_builder this_type ; typedef TSelector selector_type ; selector_type selector; CPPLINQ_INLINEMETHOD avg_selector_builder (selector_type selector) CPPLINQ_NOEXCEPT : selector (std::move (selector)) { } CPPLINQ_INLINEMETHOD avg_selector_builder (avg_selector_builder const & v) CPPLINQ_NOEXCEPT : selector (v.selector) { } CPPLINQ_INLINEMETHOD avg_selector_builder (avg_selector_builder && v) CPPLINQ_NOEXCEPT : selector (std::move (v.selector)) { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto sum = typename TRange::value_type (); int count = 0; while (range.next ()) { sum += selector (range.front ()); ++count; } if (count == 0) { return sum; } return sum/count; } }; struct avg_builder : base_builder { typedef avg_builder this_type ; CPPLINQ_INLINEMETHOD avg_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD avg_builder (avg_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD avg_builder (avg_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { auto sum = typename TRange::value_type (); int count = 0; while (range.next ()) { sum += range.front (); ++count; } if (count == 0) { return sum; } return sum/count; } }; // ------------------------------------------------------------------------- template struct aggregate_builder : base_builder { typedef aggregate_builder this_type ; typedef TAccumulator accumulator_type; typedef TAccumulate seed_type; seed_type seed; accumulator_type accumulator; CPPLINQ_INLINEMETHOD aggregate_builder (seed_type seed, accumulator_type accumulator) CPPLINQ_NOEXCEPT : seed (std::move (seed)) , accumulator (std::move (accumulator)) { } CPPLINQ_INLINEMETHOD aggregate_builder (aggregate_builder const & v) CPPLINQ_NOEXCEPT : seed (v.seed) , accumulator (v.accumulator) { } CPPLINQ_INLINEMETHOD aggregate_builder (aggregate_builder && v) CPPLINQ_NOEXCEPT : seed (std::move (v.seed)) , accumulator (std::move (v.accumulator)) { } template CPPLINQ_INLINEMETHOD seed_type build (TRange range) const { auto sum = seed; while (range.next ()) { sum = accumulator (sum, range.front ()); } return sum; } }; template struct aggregate_result_selector_builder : base_builder { typedef aggregate_result_selector_builder this_type ; typedef TAccumulator accumulator_type; typedef TAccumulate seed_type; typedef TSelector result_selector_type; seed_type seed; accumulator_type accumulator; result_selector_type result_selector; CPPLINQ_INLINEMETHOD aggregate_result_selector_builder (seed_type seed, accumulator_type accumulator, result_selector_type result_selector) CPPLINQ_NOEXCEPT : seed (std::move (seed)) , accumulator (std::move (accumulator)) , result_selector (std::move (result_selector)) { } CPPLINQ_INLINEMETHOD aggregate_result_selector_builder (aggregate_result_selector_builder const & v) CPPLINQ_NOEXCEPT : seed (v.seed) , accumulator (v.accumulator) , result_selector (v.result_selector) { } CPPLINQ_INLINEMETHOD aggregate_result_selector_builder (aggregate_result_selector_builder && v) CPPLINQ_NOEXCEPT : seed (std::move (v.seed)) , accumulator (std::move (v.accumulator)) , result_selector (std::move (v.result_selector)) { } template CPPLINQ_INLINEMETHOD auto build (TRange range) const -> decltype (result_selector (seed)) { auto sum = seed; while (range.next ()) { sum = accumulator (sum, range.front ()); } return result_selector (sum); } }; // ------------------------------------------------------------------------- template struct sequence_equal_predicate_builder : base_builder { typedef sequence_equal_predicate_builder this_type ; typedef TOtherRange other_range_type; typedef TComparer comparer_type ; other_range_type other_range ; comparer_type comparer ; CPPLINQ_INLINEMETHOD sequence_equal_predicate_builder ( TOtherRange other_range , comparer_type comparer) CPPLINQ_NOEXCEPT : other_range (std::move (other_range)) , comparer (std::move (comparer)) { } CPPLINQ_INLINEMETHOD sequence_equal_predicate_builder (sequence_equal_predicate_builder const & v) CPPLINQ_NOEXCEPT : other_range (v.other_range) , comparer (v.comparer) { } CPPLINQ_INLINEMETHOD sequence_equal_predicate_builder (sequence_equal_predicate_builder && v) CPPLINQ_NOEXCEPT : other_range (std::move (v.other_range)) , comparer (std::move (v.comparer)) { } template CPPLINQ_INLINEMETHOD bool build (TRange range) const { auto copy = other_range; for (;;) { bool next1 = range.next (); bool next2 = copy.next (); // sequences are not of same length if (next1 != next2) { return false; } // both sequences are over, next1 = next2 = false if (!next1) { return true; } if (!comparer (range.front (), copy.front ())) { return false; } } } }; template struct sequence_equal_builder : base_builder { typedef sequence_equal_builder this_type ; typedef TOtherRange other_range_type; other_range_type other_range ; CPPLINQ_INLINEMETHOD sequence_equal_builder (TOtherRange other_range) CPPLINQ_NOEXCEPT : other_range (std::move (other_range)) { } CPPLINQ_INLINEMETHOD sequence_equal_builder (sequence_equal_builder const & v) CPPLINQ_NOEXCEPT : other_range (v.other_range) { } CPPLINQ_INLINEMETHOD sequence_equal_builder (sequence_equal_builder && v) CPPLINQ_NOEXCEPT : other_range (std::move (v.other_range)) { } template CPPLINQ_INLINEMETHOD bool build (TRange range) const { auto copy = other_range; for (;;) { bool next1 = range.next (); bool next2 = copy.next (); // sequences are not of same length if (next1 != next2) { return false; } // both sequences are over, next1 = next2 = false if (!next1) { return true; } if (range.front () != copy.front ()) { return false; } } } }; // ------------------------------------------------------------------------- template struct concatenate_builder : base_builder { typedef concatenate_builder this_type ; std::basic_string separator ; size_type capacity ; CPPLINQ_INLINEMETHOD concatenate_builder ( std::basic_string separator , size_type capacity ) CPPLINQ_NOEXCEPT : separator (std::move (separator)) , capacity (capacity) { } CPPLINQ_INLINEMETHOD concatenate_builder (concatenate_builder const & v) CPPLINQ_NOEXCEPT : separator (v.separator) , capacity (v.capacity) { } CPPLINQ_INLINEMETHOD concatenate_builder (concatenate_builder && v) CPPLINQ_NOEXCEPT : separator (std::move (v.separator)) , capacity (std::move (v.capacity)) { } template CPPLINQ_INLINEMETHOD typename std::basic_string build (TRange range) const { auto first = true ; std::vector buffer ; buffer.reserve (capacity); while (range.next ()) { if (first) { first = false; } else { buffer.insert ( buffer.end () , separator.begin () , separator.end () ); } auto v = range.front (); buffer.insert ( buffer.end () , v.begin () , v.end () ); } return std::basic_string ( buffer.begin () , buffer.end () ); } }; // ------------------------------------------------------------------------- template struct any_predicate_builder : base_builder { typedef any_predicate_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; CPPLINQ_INLINEMETHOD any_predicate_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD any_predicate_builder (any_predicate_builder const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD any_predicate_builder (any_predicate_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD bool build (TRange range) const { bool any = false; while (range.next () && !any) { any = predicate (range.front ()); } return any; } }; struct any_builder : base_builder { typedef any_builder this_type ; CPPLINQ_INLINEMETHOD any_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD any_builder (any_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD any_builder (any_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD bool build (TRange range) const { return range.next (); } }; // ------------------------------------------------------------------------- template struct all_predicate_builder : base_builder { typedef all_predicate_builder this_type ; typedef TPredicate predicate_type ; predicate_type predicate ; CPPLINQ_INLINEMETHOD all_predicate_builder (predicate_type predicate) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD all_predicate_builder (all_predicate_builder const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) { } CPPLINQ_INLINEMETHOD all_predicate_builder (all_predicate_builder && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD bool build (TRange range) const { while (range.next ()) { if (!predicate (range.front ())) { return false; } } return true; } }; // ------------------------------------------------------------------------- template struct contains_builder : base_builder { typedef contains_builder this_type ; typedef TValue value_type ; value_type value; CPPLINQ_INLINEMETHOD contains_builder (value_type value) CPPLINQ_NOEXCEPT : value (std::move (value)) { } CPPLINQ_INLINEMETHOD contains_builder (contains_builder const & v) CPPLINQ_NOEXCEPT : value (v.value) { } CPPLINQ_INLINEMETHOD contains_builder (contains_builder && v) CPPLINQ_NOEXCEPT : value (std::move (v.value)) { } template CPPLINQ_INLINEMETHOD bool build (TRange range) const { while (range.next ()) { if (range.front () == value) { return true; } } return false; } }; template struct contains_predicate_builder : base_builder { typedef contains_predicate_builder this_type ; typedef TValue value_type ; typedef TPredicate predicate_type ; value_type value; predicate_type predicate ; CPPLINQ_INLINEMETHOD contains_predicate_builder (value_type value, predicate_type predicate) CPPLINQ_NOEXCEPT : value (std::move (value)) , predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD contains_predicate_builder (contains_predicate_builder const & v) CPPLINQ_NOEXCEPT : value (v.value) , predicate (v.predicate) { } CPPLINQ_INLINEMETHOD contains_predicate_builder (contains_predicate_builder && v) CPPLINQ_NOEXCEPT : value (std::move (v.value)) , predicate (std::move (v.predicate)) { } template CPPLINQ_INLINEMETHOD bool build (TRange range) const { while (range.next ()) { if (predicate (range.front (), value)) { return true; } } return false; } }; // ------------------------------------------------------------------------- struct element_at_or_default_builder : base_builder { typedef element_at_or_default_builder this_type ; size_type index; CPPLINQ_INLINEMETHOD element_at_or_default_builder (size_type index) CPPLINQ_NOEXCEPT : index (std::move (index)) { } CPPLINQ_INLINEMETHOD element_at_or_default_builder (element_at_or_default_builder const & v) CPPLINQ_NOEXCEPT : index (v.index) { } CPPLINQ_INLINEMETHOD element_at_or_default_builder (element_at_or_default_builder && v) CPPLINQ_NOEXCEPT : index (std::move (v.index)) { } template CPPLINQ_INLINEMETHOD typename TRange::value_type build (TRange range) const { size_type current = 0U; while (range.next ()) { if (current < index) { ++current; } else { return range.front (); } } return typename TRange::value_type (); } }; // ------------------------------------------------------------------------- template struct pairwise_range : base_range { typedef pairwise_range this_type ; typedef TRange range_type ; typedef typename TRange::value_type element_type ; typedef std::pair value_type ; typedef value_type return_type ; enum { returns_reference = 0 , }; range_type range ; opt previous ; opt current ; CPPLINQ_INLINEMETHOD pairwise_range ( range_type range ) CPPLINQ_NOEXCEPT : range (std::move (range)) { } CPPLINQ_INLINEMETHOD pairwise_range (pairwise_range const & v) CPPLINQ_NOEXCEPT : range (v.range) , previous (v.previous) , current (v.current) { } CPPLINQ_INLINEMETHOD pairwise_range (pairwise_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , previous (std::move (v.previous)) , current (std::move (v.current)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TPairwiseBuilder pairwise_builder) const { return pairwise_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { assert (previous.has_value ()); assert (current.has_value ()); return std::make_pair (previous.get (), current.get ()); } CPPLINQ_INLINEMETHOD bool next () { if (!previous.has_value ()) { if (range.next ()) { current = range.front (); } else { return false; } } previous.swap (current); if (range.next ()) { current = range.front (); return true; } return false; } }; struct pairwise_builder : base_builder { typedef pairwise_builder this_type ; CPPLINQ_INLINEMETHOD pairwise_builder () CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD pairwise_builder (pairwise_builder const & v) CPPLINQ_NOEXCEPT { } CPPLINQ_INLINEMETHOD pairwise_builder (pairwise_builder && v) CPPLINQ_NOEXCEPT { } template CPPLINQ_INLINEMETHOD pairwise_range build (TRange range) const { return pairwise_range (std::move (range)); } }; // ------------------------------------------------------------------------- template struct zip_with_range : base_range { typedef zip_with_range this_type ; typedef TRange range_type ; typedef TOtherRange other_range_type ; typedef typename cleanup_type::type left_element_type ; typedef typename cleanup_type::type right_element_type ; typedef std::pair value_type ; typedef value_type return_type ; enum { returns_reference = 0 , }; range_type range ; other_range_type other_range ; CPPLINQ_INLINEMETHOD zip_with_range ( range_type range , other_range_type other_range ) CPPLINQ_NOEXCEPT : range (std::move (range)) , other_range (std::move (other_range)) { } CPPLINQ_INLINEMETHOD zip_with_range (zip_with_range const & v) CPPLINQ_NOEXCEPT : range (v.range) , other_range (v.other_range) { } CPPLINQ_INLINEMETHOD zip_with_range (zip_with_range && v) CPPLINQ_NOEXCEPT : range (std::move (v.range)) , other_range (std::move (v.other_range)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { return std::make_pair (range.front (), other_range.front ()); } CPPLINQ_INLINEMETHOD bool next () { return range.next () && other_range.next (); } }; template struct zip_with_builder : base_builder { typedef zip_with_builder this_type ; typedef TOtherRange other_range_type; other_range_type other_range ; CPPLINQ_INLINEMETHOD zip_with_builder (TOtherRange other_range) CPPLINQ_NOEXCEPT : other_range (std::move (other_range)) { } CPPLINQ_INLINEMETHOD zip_with_builder (zip_with_builder const & v) CPPLINQ_NOEXCEPT : other_range (v.other_range) { } CPPLINQ_INLINEMETHOD zip_with_builder (zip_with_builder && v) CPPLINQ_NOEXCEPT : other_range (std::move (v.other_range)) { } template CPPLINQ_INLINEMETHOD zip_with_range build (TRange range) const { return zip_with_range (std::move (range), std::move (other_range)); } }; // ------------------------------------------------------------------------- template struct generate_range : base_range { static TPredicate get_predicate (); typedef decltype (get_predicate ()()) raw_opt_value_type ; typedef typename cleanup_type::type opt_value_type ; typedef decltype (*(get_predicate ()())) raw_value_type ; typedef typename cleanup_type::type value_type ; typedef generate_range this_type ; typedef TPredicate predicate_type ; typedef value_type const & return_type ; enum { returns_reference = 1, }; TPredicate predicate ; opt_value_type current_value ; CPPLINQ_INLINEMETHOD generate_range ( TPredicate predicate ) CPPLINQ_NOEXCEPT : predicate (std::move (predicate)) { } CPPLINQ_INLINEMETHOD generate_range (generate_range const & v) CPPLINQ_NOEXCEPT : predicate (v.predicate) , current_value (v.current_value) { } CPPLINQ_INLINEMETHOD generate_range (generate_range && v) CPPLINQ_NOEXCEPT : predicate (std::move (v.predicate)) , current_value (std::move (v.current_value)) { } template CPPLINQ_INLINEMETHOD typename get_builtup_type::type operator>>(TRangeBuilder range_builder) const { return range_builder.build (*this); } CPPLINQ_INLINEMETHOD return_type front () const { assert (current_value); return *current_value; } CPPLINQ_INLINEMETHOD bool next () CPPLINQ_NOEXCEPT { current_value = predicate (); return current_value; } }; // ------------------------------------------------------------------------- } // namespace detail // ------------------------------------------------------------------------- // The interface of cpplinq // ------------------------------------------------------------------------- // Range sources template CPPLINQ_INLINEMETHOD detail::from_range from_iterators ( TValueIterator begin , TValueIterator end ) CPPLINQ_NOEXCEPT { return detail::from_range (std::move (begin), std::move (end)); } template CPPLINQ_INLINEMETHOD detail::from_range from ( TContainer const & container ) { return detail::from_range ( container.begin () , container.end () ); } template CPPLINQ_INLINEMETHOD detail::from_range::iterator_type> from_array ( TValueArray & a ) CPPLINQ_NOEXCEPT { typedef detail::get_array_properties array_properties; typedef typename array_properties::iterator_type iterator_type; iterator_type begin = a; iterator_type end = begin + array_properties::size; return detail::from_range ( std::move (begin) , std::move (end) ); } template CPPLINQ_INLINEMETHOD detail::from_copy_range::type> from_copy ( TContainer&& container ) { typedef typename detail::cleanup_type::type container_type; return detail::from_copy_range ( std::forward (container) ); } template CPPLINQ_INLINEMETHOD detail::generate_range generate ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::generate_range (std::move (predicate)); } // Restriction operators template CPPLINQ_INLINEMETHOD detail::where_builder where ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::where_builder (std::move (predicate)); } // Projection operators CPPLINQ_INLINEMETHOD detail::ref_builder ref () CPPLINQ_NOEXCEPT { return detail::ref_builder (); } template CPPLINQ_INLINEMETHOD detail::select_builder select ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::select_builder (std::move (predicate)); } template CPPLINQ_INLINEMETHOD detail::select_many_builder select_many ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::select_many_builder (std::move (predicate)); } template< typename TOtherRange , typename TKeySelector , typename TOtherKeySelector , typename TCombiner > CPPLINQ_INLINEMETHOD detail::join_builder< TOtherRange , TKeySelector , TOtherKeySelector , TCombiner > join ( TOtherRange other_range , TKeySelector key_selector , TOtherKeySelector other_key_selector , TCombiner combiner ) CPPLINQ_NOEXCEPT { return detail::join_builder< TOtherRange , TKeySelector , TOtherKeySelector , TCombiner > ( std::move (other_range) , std::move (key_selector) , std::move (other_key_selector) , std::move (combiner) ); } // Concatenation operators template CPPLINQ_INLINEMETHOD detail::concat_builder concat (TOtherRange other_range) CPPLINQ_NOEXCEPT { return detail::concat_builder (std::move (other_range)); } // Partitioning operators template CPPLINQ_INLINEMETHOD detail::take_while_builder take_while ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::take_while_builder (std::move (predicate)); } CPPLINQ_INLINEMETHOD detail::take_builder take ( size_type count ) CPPLINQ_NOEXCEPT { return detail::take_builder (count); } template CPPLINQ_INLINEMETHOD detail::skip_while_builder skip_while ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::skip_while_builder (predicate); } CPPLINQ_INLINEMETHOD detail::skip_builder skip ( size_type count ) CPPLINQ_NOEXCEPT { return detail::skip_builder (count); } // Ordering operators template CPPLINQ_INLINEMETHOD detail::orderby_builder orderby ( TPredicate predicate , bool sort_ascending = true ) CPPLINQ_NOEXCEPT { return detail::orderby_builder (std::move (predicate), sort_ascending); } template CPPLINQ_INLINEMETHOD detail::orderby_builder orderby_ascending ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::orderby_builder (std::move (predicate), true); } template CPPLINQ_INLINEMETHOD detail::orderby_builder orderby_descending ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::orderby_builder (std::move (predicate), false); } template CPPLINQ_INLINEMETHOD detail::thenby_builder thenby ( TPredicate predicate , bool sort_ascending = true ) CPPLINQ_NOEXCEPT { return detail::thenby_builder (std::move (predicate), sort_ascending); } template CPPLINQ_INLINEMETHOD detail::thenby_builder thenby_ascending ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::thenby_builder (std::move (predicate), true); } template CPPLINQ_INLINEMETHOD detail::thenby_builder thenby_descending ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::thenby_builder (std::move (predicate), false); } CPPLINQ_INLINEMETHOD detail::reverse_builder reverse (size_type capacity = 16U) CPPLINQ_NOEXCEPT { return detail::reverse_builder (capacity); } // Conversion operators namespace experimental { CPPLINQ_INLINEMETHOD detail::experimental::container_builder container () CPPLINQ_NOEXCEPT { return detail::experimental::container_builder (); } } template CPPLINQ_INLINEMETHOD detail::opt::type> to_opt (TValue && v) { return detail::opt::type> (std::forward (v)); } template CPPLINQ_INLINEMETHOD detail::opt to_opt () { return detail::opt (); } CPPLINQ_INLINEMETHOD detail::to_vector_builder to_vector (size_type capacity = 16U) CPPLINQ_NOEXCEPT { return detail::to_vector_builder (capacity); } CPPLINQ_INLINEMETHOD detail::to_list_builder to_list () CPPLINQ_NOEXCEPT { return detail::to_list_builder (); } template CPPLINQ_INLINEMETHOD detail::to_map_builder to_map (TKeyPredicate key_predicate) CPPLINQ_NOEXCEPT { return detail::to_map_builder(std::move (key_predicate)); } template CPPLINQ_INLINEMETHOD detail::to_lookup_builder to_lookup (TKeyPredicate key_predicate) CPPLINQ_NOEXCEPT { return detail::to_lookup_builder(std::move (key_predicate)); } // Equality operators template CPPLINQ_INLINEMETHOD detail::sequence_equal_builder sequence_equal (TOtherRange other_range) CPPLINQ_NOEXCEPT { return detail::sequence_equal_builder (std::move (other_range)); } template CPPLINQ_INLINEMETHOD detail::sequence_equal_predicate_builder sequence_equal ( TOtherRange other_range , TComparer comparer) CPPLINQ_NOEXCEPT { return detail::sequence_equal_predicate_builder (std::move (other_range), std::move (comparer)); } // Element operators template CPPLINQ_INLINEMETHOD detail::first_predicate_builder first ( TPredicate predicate ) { return detail::first_predicate_builder (std::move (predicate)); } CPPLINQ_INLINEMETHOD detail::first_builder first () { return detail::first_builder (); } template CPPLINQ_INLINEMETHOD detail::first_or_default_predicate_builder first_or_default ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::first_or_default_predicate_builder (predicate); } CPPLINQ_INLINEMETHOD detail::first_or_default_builder first_or_default () CPPLINQ_NOEXCEPT { return detail::first_or_default_builder (); } template CPPLINQ_INLINEMETHOD detail::last_or_default_predicate_builder last_or_default ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::last_or_default_predicate_builder (predicate); } CPPLINQ_INLINEMETHOD detail::last_or_default_builder last_or_default () CPPLINQ_NOEXCEPT { return detail::last_or_default_builder (); } CPPLINQ_INLINEMETHOD detail::element_at_or_default_builder element_at_or_default ( size_type index ) CPPLINQ_NOEXCEPT { return detail::element_at_or_default_builder (index); } // Generation operators CPPLINQ_INLINEMETHOD detail::int_range range ( int start , int count ) CPPLINQ_NOEXCEPT { auto c = count > 0 ? count : 0; auto end = (INT_MAX - c) > start ? (start + c) : INT_MAX; return detail::int_range (start, end); } template CPPLINQ_INLINEMETHOD detail::repeat_range repeat ( TValue element , int count ) CPPLINQ_NOEXCEPT { auto c = count > 0 ? count : 0; return detail::repeat_range (element, c); } template CPPLINQ_INLINEMETHOD detail::empty_range empty () CPPLINQ_NOEXCEPT { return detail::empty_range (); } template CPPLINQ_INLINEMETHOD detail::singleton_range::type> singleton (TValue&& value) CPPLINQ_NOEXCEPT { return detail::singleton_range::type> (std::forward (value)); } // Quantifiers template CPPLINQ_INLINEMETHOD detail::any_predicate_builder any ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::any_predicate_builder (std::move (predicate)); } CPPLINQ_INLINEMETHOD detail::any_builder any () CPPLINQ_NOEXCEPT { return detail::any_builder (); } template CPPLINQ_INLINEMETHOD detail::all_predicate_builder all ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::all_predicate_builder (std::move (predicate)); } template CPPLINQ_INLINEMETHOD detail::contains_builder contains ( TValue value ) CPPLINQ_NOEXCEPT { return detail::contains_builder (value); } template CPPLINQ_INLINEMETHOD detail::contains_predicate_builder contains ( TValue value , TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::contains_predicate_builder (value, predicate); } // Aggregate operators template CPPLINQ_INLINEMETHOD detail::count_predicate_builder count ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::count_predicate_builder (std::move (predicate)); } CPPLINQ_INLINEMETHOD detail::count_builder count () CPPLINQ_NOEXCEPT { return detail::count_builder (); } template CPPLINQ_INLINEMETHOD detail::sum_selector_builder sum ( TSelector selector ) CPPLINQ_NOEXCEPT { return detail::sum_selector_builder (std::move (selector)); } CPPLINQ_INLINEMETHOD detail::sum_builder sum () CPPLINQ_NOEXCEPT { return detail::sum_builder (); } /*template CPPLINQ_INLINEMETHOD detail::max_selector_builder max (TSelector selector) CPPLINQ_NOEXCEPT { return detail::max_selector_builder (std::move (selector)); } CPPLINQ_INLINEMETHOD detail::max_builder max () CPPLINQ_NOEXCEPT { return detail::max_builder (); }*/ /*template CPPLINQ_INLINEMETHOD detail::min_selector_builder min ( TSelector selector ) CPPLINQ_NOEXCEPT { return detail::min_selector_builder (std::move (selector)); } CPPLINQ_INLINEMETHOD detail::min_builder min () CPPLINQ_NOEXCEPT { return detail::min_builder (); } template CPPLINQ_INLINEMETHOD detail::avg_selector_builder avg ( TSelector selector ) CPPLINQ_NOEXCEPT { return detail::avg_selector_builder (std::move (selector)); } CPPLINQ_INLINEMETHOD detail::avg_builder avg () CPPLINQ_NOEXCEPT { return detail::avg_builder (); }*/ template CPPLINQ_INLINEMETHOD detail::aggregate_builder aggregate ( TAccumulate seed , TAccumulator accumulator ) CPPLINQ_NOEXCEPT { return detail::aggregate_builder (seed, accumulator); } template CPPLINQ_INLINEMETHOD detail::aggregate_result_selector_builder aggregate ( TAccumulate seed , TAccumulator accumulator , TSelector result_selector ) CPPLINQ_NOEXCEPT { return detail::aggregate_result_selector_builder (seed, accumulator, result_selector); } // set operators CPPLINQ_INLINEMETHOD detail::distinct_builder distinct () CPPLINQ_NOEXCEPT { return detail::distinct_builder (); } template CPPLINQ_INLINEMETHOD detail::union_builder union_with (TOtherRange other_range) CPPLINQ_NOEXCEPT { return detail::union_builder (std::move (other_range)); } template CPPLINQ_INLINEMETHOD detail::intersect_builder intersect_with (TOtherRange other_range) CPPLINQ_NOEXCEPT { return detail::intersect_builder (std::move (other_range)); } template CPPLINQ_INLINEMETHOD detail::except_builder except (TOtherRange other_range) CPPLINQ_NOEXCEPT { return detail::except_builder (std::move (other_range)); } // other operators template CPPLINQ_INLINEMETHOD detail::for_each_builder for_each ( TPredicate predicate ) CPPLINQ_NOEXCEPT { return detail::for_each_builder (std::move (predicate)); } CPPLINQ_INLINEMETHOD detail::concatenate_builder concatenate ( std::string separator , size_type capacity = 16U ) CPPLINQ_NOEXCEPT { return detail::concatenate_builder ( std::move (separator) , capacity ); } CPPLINQ_INLINEMETHOD detail::concatenate_builder concatenate ( std::wstring separator , size_type capacity = 16U ) CPPLINQ_NOEXCEPT { return detail::concatenate_builder ( std::move (separator) , capacity ); } CPPLINQ_INLINEMETHOD detail::pairwise_builder pairwise () CPPLINQ_NOEXCEPT { return detail::pairwise_builder (); } template CPPLINQ_INLINEMETHOD detail::zip_with_builder zip_with (TOtherRange other_range) CPPLINQ_NOEXCEPT { return detail::zip_with_builder (std::move (other_range)); } // ------------------------------------------------------------------------- } // ---------------------------------------------------------------------------- #ifdef _MSC_VER # pragma warning (pop) #endif // ---------------------------------------------------------------------------- #endif // CPPLINQ__HEADER_GUARD // ----------------------------------------------------------------------------