add support for range based for loop iteration (without need to create explicit container)

Sep 19, 2013 at 7:16 AM
A proposal to add something like this to allow lazy evaluation of LINQ query.

So that one could write:
    using namespace cpplinq;
    int ints[] = {3,1,4,1,5,9,2,6,5,4};

    // Computes the sum of all even numbers in the sequence above
    auto res = from_array (ints) >> where ([](int i) {return i%2 ==0;}) >> take(2);

    for(auto& val: res) {
        // Do whatever is needed - val is evaluated only during iteration
    }
namespace cpplinq {
namespace detail {
       template<typename T>
        struct range_iterator:
            public std::iterator<std::input_iterator_tag, typename T::value_type, void, void, typename T::value_type const &> {

            static_assert(std::is_base_of<cpplinq::detail::base_range, T>::value, "This iterator is suitable only for cpplinq range classes");
            typedef typename std::iterator<std::input_iterator_tag, typename T::value_type, void, void, typename T::value_type const &> base_type;
            typedef typename base_type::reference reference;

            // use for constructing end iterator
            CPPLINQ_INLINEMETHOD range_iterator() throw()
                :   linq_range_   (nullptr)
                ,   is_end_       (true)
            {
            }

            CPPLINQ_INLINEMETHOD range_iterator(T* linq_range) throw()
                :   linq_range_   (linq_range)
                ,   is_end_       (!linq_range_->next())
            {
            }

            CPPLINQ_INLINEMETHOD range_iterator& operator++()
            {
                if (!is_end_)
                    is_end_ = !linq_range_->next();
                return (*this);
            }

            CPPLINQ_INLINEMETHOD reference operator*()
            {
                assert(!is_end_);
                return linq_range_->front();
            }

            CPPLINQ_INLINEMETHOD bool operator== (const range_iterator& rhs)
            {
                return (this->is_end_ && rhs.is_end_) || this->linq_range_ == rhs.linq_range_;
            }

            CPPLINQ_INLINEMETHOD bool operator!= (const range_iterator& rhs)
            {
                return !(this->operator==(rhs));
            }

        private:
            T* linq_range_;
            bool is_end_;
        };

        template<typename T>
        CPPLINQ_INLINEMETHOD range_iterator<T> begin(T& linq_range)
        {
            return range_iterator<T>(&linq_range);
        }

        template<typename T>
        CPPLINQ_INLINEMETHOD range_iterator<T> end(T& linq_range)
        {
            return range_iterator<T>();
        }

} // end namespace detail
} // end namespace linq
NOTE: provided implementation does not work with from_range.
Coordinator
Sep 24, 2013 at 5:54 AM
Hi.

Do you mind making this into a pull request?
Sep 24, 2013 at 11:41 AM
I will try to, but so far all my attempts to commit to codeplex failed drastically.
Sep 24, 2013 at 11:55 AM
Ok - got it working. Will create pull request as soon as cover functionality with tests and eliminate compilation warnings
Coordinator
Sep 25, 2013 at 12:24 PM
Sounds good!