diff --git a/CppLinq.Mini/CppLinq2015.Mini.vcxproj b/CppLinq.Mini/CppLinq2015.Mini.vcxproj new file mode 100644 index 0000000..0b25e59 --- /dev/null +++ b/CppLinq.Mini/CppLinq2015.Mini.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {4CE7EBDE-D1A2-4B5D-853C-921668821E50} + Win32Proj + CppLinqMini + + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)Output\$(Configuration)\ + Intermediate2015\$(Configuration)\ + + + true + Intermediate2015\$(Configuration)\ + $(SolutionDir)Output\$(Configuration)\ + + + false + $(SolutionDir)Output\$(Configuration)\ + Intermediate2015\$(Configuration)\ + + + false + $(SolutionDir)Output\$(Configuration)\ + Intermediate2015\$(Configuration)\ + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/CppLinq/cpplinq.hpp b/CppLinq/cpplinq.hpp index 0aa3e25..b66c327 100644 --- a/CppLinq/cpplinq.hpp +++ b/CppLinq/cpplinq.hpp @@ -1,5596 +1,5640 @@ -// ---------------------------------------------------------------------------------------------- -// 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 -// ---------------------------------------------------------------------------- -#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. -#endif -// ---------------------------------------------------------------------------- -#ifndef CPPLINQ_ASSERT -# define CPPLINQ_ASSERT(expr) assert(expr) -#endif -#ifndef CPPLINQ_METHOD -# define CPPLINQ_METHOD -#endif -#ifndef CPPLINQ_INLINEMETHOD -# define CPPLINQ_INLINEMETHOD inline -#endif -#ifndef CPPLINQ_NOEXCEPT -# define CPPLINQ_NOEXCEPT throw () -#endif -// ---------------------------------------------------------------------------- - -// 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 const * 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 - { - CPPLINQ_ASSERT (is_initialized); - return *get_ptr (); - } - - CPPLINQ_INLINEMETHOD value_type & get () CPPLINQ_NOEXCEPT - { - CPPLINQ_ASSERT (is_initialized); - return *get_ptr (); - } - - CPPLINQ_INLINEMETHOD bool has_value () const CPPLINQ_NOEXCEPT - { - return is_initialized; - } - - // TODO: To be replaced with explicit operator bool () - 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 - { - CPPLINQ_ASSERT (current != upcoming); - CPPLINQ_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 - { - CPPLINQ_ASSERT (current != upcoming); - CPPLINQ_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 - { - CPPLINQ_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 - { - CPPLINQ_ASSERT (!start); - CPPLINQ_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 const & return_type ; - enum - { - returns_reference = 1 , - }; - - typedef select_range this_type ; - typedef TRange range_type ; - typedef TPredicate predicate_type ; - - range_type range ; - predicate_type predicate ; - - opt cache_value ; - - 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) - , cache_value (v.cache_value) - { - } - - CPPLINQ_INLINEMETHOD select_range (select_range && v) CPPLINQ_NOEXCEPT - : range (std::move (v.range)) - , predicate (std::move (v.predicate)) - , cache_value (std::move (v.cache_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 - { - CPPLINQ_ASSERT (cache_value); - return *cache_value; - } - - CPPLINQ_INLINEMETHOD bool next () - { - if (range.next ()) - { - cache_value = predicate (range.front ()); - return true; - } - - cache_value.clear (); - - return false; - } - }; - - 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 - { - CPPLINQ_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 (); - } - - inner_range.clear (); - - 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 - { - CPPLINQ_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 - { - CPPLINQ_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: - CPPLINQ_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; - } - - state = state_end; - return false; - case state_iterating_range: - if (range.next ()) - { - return true; - } - - if (other_range.next ()) - { - state = state_iterating_other_range; - return true; - } - - state = state_end; - return false; - case state_iterating_other_range: - if (other_range.next ()) - { - return true; - } - - state = state_end; - 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 - { - CPPLINQ_ASSERT (has_value); - CPPLINQ_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) - { - CPPLINQ_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 - { - CPPLINQ_ASSERT (state == state_iterating); - CPPLINQ_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); - } - - 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::value_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::value_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 get_transformed_type::type build (TRange range) const - { - typedef typename get_transformed_type::type value_type; - - auto sum = 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 get_transformed_type::type build (TRange range) const - { - typedef typename get_transformed_type::type value_type; - - auto current = std::numeric_limits::lowest (); - 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::lowest (); - 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 get_transformed_type::type build (TRange range) const - { - typedef typename get_transformed_type::type value_type; - - 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 get_transformed_type::type build (TRange range) const - { - typedef typename get_transformed_type::type value_type; - - auto sum = 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 - { - CPPLINQ_ASSERT (previous.has_value ()); - CPPLINQ_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; - } - - previous.clear (); - current.clear (); - - 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 - { - CPPLINQ_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 -// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------------- +// 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 +// ---------------------------------------------------------------------------- +#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. +#endif +// ---------------------------------------------------------------------------- +#ifndef CPPLINQ_ASSERT +# define CPPLINQ_ASSERT(expr) assert(expr) +#endif +#ifndef CPPLINQ_METHOD +# define CPPLINQ_METHOD +#endif +#ifndef CPPLINQ_INLINEMETHOD +# define CPPLINQ_INLINEMETHOD inline +#endif +#ifndef CPPLINQ_NOEXCEPT +# define CPPLINQ_NOEXCEPT throw () +#endif +// ---------------------------------------------------------------------------- + +// 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 const * 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 + { + CPPLINQ_ASSERT (is_initialized); + return *get_ptr (); + } + + CPPLINQ_INLINEMETHOD value_type & get () CPPLINQ_NOEXCEPT + { + CPPLINQ_ASSERT (is_initialized); + return *get_ptr (); + } + + CPPLINQ_INLINEMETHOD bool has_value () const CPPLINQ_NOEXCEPT + { + return is_initialized; + } + + // TODO: To be replaced with explicit operator bool () + 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 + { + CPPLINQ_ASSERT (current != upcoming); + CPPLINQ_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 + { + CPPLINQ_ASSERT (current != upcoming); + CPPLINQ_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 + { + CPPLINQ_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 + { + CPPLINQ_ASSERT (!start); + CPPLINQ_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 + static auto choose (F&& f, std::tuple&&, T2&&) -> decltype (f (std::declval ()...)); + template + static auto choose (F&& f, T1&&, std::tuple&&) -> decltype (f (std::declval ()...)); + + template + struct select_range : base_range + { + static typename TRange::value_type get_source (); + static TPredicate get_predicate (); + + + typedef decltype (choose (get_predicate (), + std::make_tuple (get_source ()), + std::make_tuple (get_source (), 0))) + raw_value_type ; + typedef typename cleanup_type::type value_type ; + typedef value_type const & return_type ; + enum + { + returns_reference = 1 , + }; + + typedef select_range this_type ; + typedef TRange range_type ; + typedef TPredicate predicate_type ; + + range_type range ; + predicate_type predicate ; + + opt cache_value ; + size_type current_index; + + CPPLINQ_INLINEMETHOD select_range ( + range_type range + , predicate_type predicate + ) CPPLINQ_NOEXCEPT + : range (std::move (range)) + , predicate (std::move (predicate)) + , current_index(0) + { + } + + CPPLINQ_INLINEMETHOD select_range (select_range const & v) + : range (v.range) + , predicate (v.predicate) + , cache_value (v.cache_value) + , current_index(v.current_index) + { + } + + CPPLINQ_INLINEMETHOD select_range (select_range && v) CPPLINQ_NOEXCEPT + : range (std::move (v.range)) + , predicate (std::move (v.predicate)) + , cache_value (std::move (v.cache_value)) + , current_index(std::move (v.current_index)) + { + } + + 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_ASSERT (cache_value); + return *cache_value; + } + + CPPLINQ_INLINEMETHOD bool next () + { + if (range.next ()) + { + cache_value = evaluate_predicate (predicate); + return true; + } + + cache_value.clear (); + + return false; + } + + template + CPPLINQ_INLINEMETHOD auto evaluate_predicate(TPredicate_& pred) -> decltype (pred (range.front ())) + { + return pred (range.front ()); + } + + template + CPPLINQ_INLINEMETHOD auto evaluate_predicate(TPredicate_& pred) -> decltype (pred (range.front (), 0)) + { + return pred (range.front (), current_index++); + } + }; + + 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 (choose (get_predicate (), + std::make_tuple (get_source ()), + std::make_tuple (get_source (), 0))) + 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 ; + size_type current_index; + + + CPPLINQ_INLINEMETHOD select_many_range ( + range_type range + , predicate_type predicate + ) CPPLINQ_NOEXCEPT + : range (std::move (range)) + , predicate (std::move (predicate)) + , current_index(0) + { + } + + CPPLINQ_INLINEMETHOD select_many_range (select_many_range const & v) + : range (v.range) + , predicate (v.predicate) + , inner_range (v.inner_range) + , current_index(v.current_index) + { + } + + 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)) + , current_index(std::move (v.current_index)) + { + } + + 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_ASSERT (inner_range); + return inner_range->front (); + } + + CPPLINQ_INLINEMETHOD bool next () + { + if (inner_range && inner_range->next ()) + { + return true; + } + + if (range.next ()) + { + inner_range = evaluate_predicate (predicate); + return inner_range && inner_range->next (); + } + + inner_range.clear (); + + return false; + } + + template + CPPLINQ_INLINEMETHOD auto evaluate_predicate(TPredicate_& pred) -> decltype (pred (range.front ())) + { + return pred (range.front ()); + } + + template + CPPLINQ_INLINEMETHOD auto evaluate_predicate(TPredicate_& pred) -> decltype (pred (range.front (), 0)) + { + return pred (range.front (), current_index++); + } + }; + + 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 + { + CPPLINQ_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 + { + CPPLINQ_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: + CPPLINQ_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; + } + + state = state_end; + return false; + case state_iterating_range: + if (range.next ()) + { + return true; + } + + if (other_range.next ()) + { + state = state_iterating_other_range; + return true; + } + + state = state_end; + return false; + case state_iterating_other_range: + if (other_range.next ()) + { + return true; + } + + state = state_end; + 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 + { + CPPLINQ_ASSERT (has_value); + CPPLINQ_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) + { + CPPLINQ_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 + { + CPPLINQ_ASSERT (state == state_iterating); + CPPLINQ_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); + } + + 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::value_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::value_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 get_transformed_type::type build (TRange range) const + { + typedef typename get_transformed_type::type value_type; + + auto sum = 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 get_transformed_type::type build (TRange range) const + { + typedef typename get_transformed_type::type value_type; + + auto current = std::numeric_limits::lowest (); + 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::lowest (); + 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 get_transformed_type::type build (TRange range) const + { + typedef typename get_transformed_type::type value_type; + + 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 get_transformed_type::type build (TRange range) const + { + typedef typename get_transformed_type::type value_type; + + auto sum = 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 + { + CPPLINQ_ASSERT (previous.has_value ()); + CPPLINQ_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; + } + + previous.clear (); + current.clear (); + + 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 + { + CPPLINQ_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 +// ---------------------------------------------------------------------------- diff --git a/CppLinq2015.UnitTest/CodeCoverage.runsettings b/CppLinq2015.UnitTest/CodeCoverage.runsettings new file mode 100644 index 0000000..af37cae --- /dev/null +++ b/CppLinq2015.UnitTest/CodeCoverage.runsettings @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + .*\.dll$ + .*\.exe$ + + + .*CPPUnitTestFramework.* + + + + + + + + ^Fabrikam\.UnitTest\..* + ^std::.* + ^ATL::.* + .*::__GetTestMethodInfo.* + ^Microsoft::VisualStudio::CppCodeCoverageFramework::.* + ^Microsoft::VisualStudio::CppUnitTestFramework::.* + ^cpplinq::.*::what$ + + + + + + + + ^System.Diagnostics.DebuggerHiddenAttribute$ + ^System.Diagnostics.DebuggerNonUserCodeAttribute$ + ^System.Runtime.CompilerServices.CompilerGeneratedAttribute$ + ^System.CodeDom.Compiler.GeneratedCodeAttribute$ + ^System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute$ + + + + + + + .*\\atlmfc\\.* + .*\\vctools\\.* + .*\\public\\sdk\\.* + .*\\microsoft sdks\\.* + .*\\vc\\include\\.* + .*\\cpplinq\\Test\\.* + .*\\cpplinq\\CppLinq2013\.UnitTest\\.* + + + + + + + .*microsoft.* + + + + + + + + ^B77A5C561934E089$ + ^B03F5F7F11D50A3A$ + ^31BF3856AD364E35$ + ^89845DCD8080CC91$ + ^71E9BCE111E9429C$ + ^8F50407C4E9E73B6$ + ^E361AF139669C375$ + + + + + + True + True + True + False + + + + + + + \ No newline at end of file diff --git a/CppLinq2015.UnitTest/CppLinq2015.UnitTest.vcxproj b/CppLinq2015.UnitTest/CppLinq2015.UnitTest.vcxproj new file mode 100644 index 0000000..0b3cbe3 --- /dev/null +++ b/CppLinq2015.UnitTest/CppLinq2015.UnitTest.vcxproj @@ -0,0 +1,179 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {081E2554-9A17-45E3-9264-DC677FCE8DA2} + Win32Proj + CppLinq2015UnitTest + + + + DynamicLibrary + true + v140 + Unicode + false + + + DynamicLibrary + true + v140 + Unicode + false + + + DynamicLibrary + false + v140 + true + Unicode + false + + + DynamicLibrary + false + v140 + true + Unicode + false + + + + + + + + + + + + + + + + + + + true + Intermediate2015\$(Configuration)\ + $(SolutionDir)Output\$(Configuration)\ + + + true + Intermediate2015\$(Configuration)\ + $(SolutionDir)Output\$(Configuration)\ + + + true + $(SolutionDir)Output\$(Configuration)\ + Intermediate2015\$(Configuration)\ + + + true + $(SolutionDir)Output\$(Configuration)\ + Intermediate2015\$(Configuration)\ + + + + Use + Level3 + Disabled + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;%(PreprocessorDefinitions) + true + + + Windows + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Use + Level3 + Disabled + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;%(PreprocessorDefinitions) + true + + + Windows + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + Use + MaxSpeed + true + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + Use + MaxSpeed + true + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + + + + Create + Create + Create + Create + + + + + + + + + + \ No newline at end of file diff --git a/CppLinq2015.UnitTest/CppLinq2015.UnitTest.vcxproj.filters b/CppLinq2015.UnitTest/CppLinq2015.UnitTest.vcxproj.filters new file mode 100644 index 0000000..cd92285 --- /dev/null +++ b/CppLinq2015.UnitTest/CppLinq2015.UnitTest.vcxproj.filters @@ -0,0 +1,19 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + + + \ No newline at end of file diff --git a/CppLinq2015.UnitTest/CppLinqTest.cpp b/CppLinq2015.UnitTest/CppLinqTest.cpp new file mode 100644 index 0000000..382866d --- /dev/null +++ b/CppLinq2015.UnitTest/CppLinqTest.cpp @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------------------------- +// 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. +// ---------------------------------------------------------------------------------------------- +#include "stdafx.h" +#include "CppUnitTest.h" +// ---------------------------------------------------------------------------------------------- +// In order to suppress code coverage of assert macros +#define CPPLINQ_ASSERT(expr) +// ---------------------------------------------------------------------------------------------- +#include "../Test/CppLinqTests.hpp" +// ---------------------------------------------------------------------------------------------- +using namespace Microsoft::VisualStudio::CppUnitTestFramework; +// ---------------------------------------------------------------------------------------------- +namespace CppLinq2013UnitTest +{ + TEST_CLASS(CppLinqTest) + { + public: + + TEST_METHOD(RunTestSuite) + { + auto failures_detected = run_all_tests (false); + Assert::AreEqual (false, failures_detected); + } + + }; +} +// ---------------------------------------------------------------------------------------------- diff --git a/CppLinq2015.UnitTest/stdafx.cpp b/CppLinq2015.UnitTest/stdafx.cpp new file mode 100644 index 0000000..4707c0d --- /dev/null +++ b/CppLinq2015.UnitTest/stdafx.cpp @@ -0,0 +1,13 @@ +// ---------------------------------------------------------------------------------------------- +// 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. +// ---------------------------------------------------------------------------------------------- +#include "stdafx.h" +// ---------------------------------------------------------------------------------------------- diff --git a/CppLinq2015.UnitTest/stdafx.h b/CppLinq2015.UnitTest/stdafx.h new file mode 100644 index 0000000..01ebd2f --- /dev/null +++ b/CppLinq2015.UnitTest/stdafx.h @@ -0,0 +1,29 @@ +// ---------------------------------------------------------------------------------------------- +// 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. +// ---------------------------------------------------------------------------------------------- +#pragma once +// ---------------------------------------------------------------------------------------------- +#include +// ---------------------------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// ---------------------------------------------------------------------------------------------- diff --git a/CppLinq2015.sln b/CppLinq2015.sln new file mode 100644 index 0000000..fcf8f3b --- /dev/null +++ b/CppLinq2015.sln @@ -0,0 +1,53 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30110.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppLinq2015", "Test\CppLinq2015.vcxproj", "{B2C5078E-E859-4BF8-A799-75653FE524AB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppLinq2015.Mini", "CppLinq.Mini\CppLinq2015.Mini.vcxproj", "{4CE7EBDE-D1A2-4B5D-853C-921668821E50}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4203A08B-EAD5-4C1C-98AA-508D6A74CEAC}" + ProjectSection(SolutionItems) = preProject + .gitignore = .gitignore + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppLinq2015.UnitTest", "CppLinq2015.UnitTest\CppLinq2015.UnitTest.vcxproj", "{081E2554-9A17-45E3-9264-DC677FCE8DA2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|Win32.ActiveCfg = Debug|Win32 + {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|Win32.Build.0 = Debug|Win32 + {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|x64.ActiveCfg = Debug|x64 + {B2C5078E-E859-4BF8-A799-75653FE524AB}.Debug|x64.Build.0 = Debug|x64 + {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|Win32.ActiveCfg = Release|Win32 + {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|Win32.Build.0 = Release|Win32 + {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|x64.ActiveCfg = Release|x64 + {B2C5078E-E859-4BF8-A799-75653FE524AB}.Release|x64.Build.0 = Release|x64 + {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|Win32.ActiveCfg = Debug|Win32 + {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|Win32.Build.0 = Debug|Win32 + {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|x64.ActiveCfg = Debug|x64 + {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Debug|x64.Build.0 = Debug|x64 + {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|Win32.ActiveCfg = Release|Win32 + {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|Win32.Build.0 = Release|Win32 + {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|x64.ActiveCfg = Release|x64 + {4CE7EBDE-D1A2-4B5D-853C-921668821E50}.Release|x64.Build.0 = Release|x64 + {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Debug|Win32.ActiveCfg = Debug|Win32 + {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Debug|Win32.Build.0 = Debug|Win32 + {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Debug|x64.ActiveCfg = Debug|x64 + {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Debug|x64.Build.0 = Debug|x64 + {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Release|Win32.ActiveCfg = Release|Win32 + {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Release|Win32.Build.0 = Release|Win32 + {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Release|x64.ActiveCfg = Release|x64 + {081E2554-9A17-45E3-9264-DC677FCE8DA2}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Test/CppLinq2015.vcxproj b/Test/CppLinq2015.vcxproj new file mode 100644 index 0000000..9e3cb05 --- /dev/null +++ b/Test/CppLinq2015.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B2C5078E-E859-4BF8-A799-75653FE524AB} + Win32Proj + CppLinq + + + + Application + true + v140 + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)Output\$(Configuration)\ + Intermediate2015\$(Configuration)\ + + + true + $(SolutionDir)Output\$(Configuration)\ + Intermediate2015\$(Configuration)\ + + + false + $(SolutionDir)Output\$(Configuration)\ + Intermediate2015\$(Configuration)\ + + + false + $(SolutionDir)Output\$(Configuration)\ + Intermediate2015\$(Configuration)\ + + + + Use + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Use + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level4 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Speed + + + Console + true + true + true + + + + + Level4 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/Test/CppLinqTests.hpp b/Test/CppLinqTests.hpp index 532faf2..75e000c 100644 --- a/Test/CppLinqTests.hpp +++ b/Test/CppLinqTests.hpp @@ -867,8 +867,8 @@ namespace } { - auto customers = empty() >> to_list (); - TEST_ASSERT (0U, customers.size ()); + auto customers_list = empty() >> to_list (); + TEST_ASSERT (0U, customers_list.size ()); } } @@ -1625,6 +1625,11 @@ namespace TEST_ASSERT (0U, select_result.size ()); } + { + std::vector select_result = from (empty_vector) >> select ([](int i, std::size_t index){return 1.0*i*index;}) >> to_vector (); + TEST_ASSERT (0U, select_result.size ()); + } + { std::vector select_result = from_array (customers) @@ -1646,6 +1651,26 @@ namespace TEST_ASSERT (count_of_customers, select_result.size ()); } + { + std::vector> select_result = + from_array (customers) + >> select ([](customer const & c, std::size_t index){return std::make_pair(c.id, index);}) + >> to_vector () + ; + + std::size_t index = 0U; + for (auto sz : select_result) + { + if (!TEST_ASSERT (customers[index].id, sz.first) || !TEST_ASSERT (index, sz.second)) + { + PRINT_INDEX (index); + } + + ++index; + } + + TEST_ASSERT (count_of_customers, select_result.size ()); + } } void test_join () @@ -1747,6 +1772,18 @@ namespace TEST_ASSERT (0U, select_many_result.size ()); } + + { + std::vector> select_many_result = + from_iterators (customers, customers) + >> select_many([](customer const & c, std::size_t index) {return from(c.last_name) + >> select([index](char c) {return std::make_pair(index, c); }); }) + >> to_vector() + ; + + TEST_ASSERT (0U, select_many_result.size ()); + } + { std::vector expected; for (auto customer : customers) @@ -1776,6 +1813,45 @@ namespace } } + { + std::vector expected; + for (auto customer : customers) + { + expected.insert ( + expected.end () + , customer.last_name.begin () + , customer.last_name.end () + ); + } + + std::vector> select_many_result = + from_array (customers) + >> select_many([](customer const & c, std::size_t index) {return from(c.last_name) + >> select([index](char c) {return std::make_pair(index, c); }); }) + >> to_vector() + ; + + std::size_t group = -1; + if (TEST_ASSERT (expected.size (), select_many_result.size ())) + { + for (std::size_t index = 0U; index < expected.size (); ++index) + { + if (TEST_ASSERT (expected[index], select_many_result[index].second)) + { + if (expected[index] >= 'A' && expected[index] <= 'Z') group++; //every name begins with an upper case character + + if (!TEST_ASSERT (group, select_many_result[index].first)) + { + PRINT_INDEX (index); + } + } + else + { + PRINT_INDEX (index); + } + } + } + } } void test_orderby () @@ -2603,9 +2679,9 @@ namespace // concat two non-empty ranges { - int set1[] = {0,1,2,3,4,5}; - int set2[] = {6,7,8,9}; - auto result = from_array (set1) >> concat (from_array (set2)) >> to_vector (); + int set3[] = {0,1,2,3,4,5}; + int set4[] = {6,7,8,9}; + auto result = from_array (set3) >> concat (from_array (set4)) >> to_vector (); TEST_ASSERT (10U, result.size ()); for (auto i = 0U; i < 10 && i < result.size (); ++i) {