// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. #if !defined(CPPLINQ_LINQ_ITERATORS_HPP) #define CPPLINQ_LINQ_ITERATORS_HPP #pragma once #include namespace cpplinq { // if a member, provides the straightforward implementation of various redundant operators. For example, // providing -> for any iterator providing *, and so forth. struct use_default_iterator_operators {}; #define CPPLINQ_USE_DEFAULT_ITERATOR_OPERATORS \ operator ::cpplinq::use_default_iterator_operators() const { return ::cpplinq::use_default_iterator_operators(); } template typename std::enable_if< std::is_convertible::value, Iter >::type operator+(const Iter& it, typename std::iterator_traits::distance_type n) { return it += n; } template typename std::enable_if< std::is_convertible::value, Iter >::type operator-(const Iter& it, typename std::iterator_traits::distance_type n) { return it -= n; } template typename std::enable_if< std::is_convertible::value, Iter >::type operator-=(const Iter& it, typename std::iterator_traits::distance_type n) { return it += (-n); } template typename std::enable_if< std::is_convertible::value, bool >::type operator!=(const Iter& it, const Iter& it2) { return !(it == it2); } template typename std::enable_if< std::is_convertible::value, bool >::type operator>(const Iter& it, const Iter& it2) { return it2 < it; } template typename std::enable_if< std::is_convertible::value, bool >::type operator<=(const Iter& it, const Iter& it2) { return !(it2 < it); } template typename std::enable_if< std::is_convertible::value, bool >::type operator>=(const Iter& it, const Iter& it2) { return !(it < it2); } namespace util { template typename std::iterator_traits::pointer deref_iterator(const Iter& it) { return deref_iterator(it, util::identity::reference>()); } template T* deref_iterator(const Iter& it, util::identity) { return &*it; } template util::value_ptr deref_iterator(const Iter& it, util::identity) { return util::value_ptr(*it); } } template class iter_range { Iter start, finish; public: CPPLINQ_USE_DEFAULT_ITERATOR_OPERATORS typedef Iter iterator; typedef typename iterator::value_type value_type; explicit iter_range(Iter start, Iter finish) : start(start), finish(finish) {} iterator begin() const { return start; } iterator end() const { return finish; } }; template iter_range make_range(Iter start, Iter finish) { return iter_range(start, finish); } // decays into a onepass/forward iterator template class cursor_iterator : public std::iterator::value, typename std::add_pointer::type, util::value_ptr>::type, typename Cursor::reference_type> { public: CPPLINQ_USE_DEFAULT_ITERATOR_OPERATORS; cursor_iterator(Cursor cur) : cur(cur) { } cursor_iterator() : cur() { } bool operator==(const cursor_iterator& other) const { return !cur && !other.cur; } typename Cursor::reference_type operator*() const { return cur->get(); } typename cursor_iterator::pointer operator->() const { auto& v = **this; return &v; } cursor_iterator& operator++() { cur->inc(); if (cur->empty()) { cur.reset(); } return *this; } cursor_iterator& operator+=(std::ptrdiff_t n) { cur->skip(n); if (cur->empty()) { cur.reset(); } return *this; } private: bool empty() const { !cur || cur->empty(); } util::maybe cur; }; template class container_range { Container c; public: typedef cursor_iterator iterator; container_range(Container c) : c(c) { } iterator begin() const { return iterator(c.get_cursor()); } iterator end() const { return iterator(); } }; } #endif