/*============================================================================= Copyright (c) 2011-2019 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_ITERATOR_GENERATOR_ITERATOR_HPP #define SPROUT_ITERATOR_GENERATOR_ITERATOR_HPP #include #include #include #include #include #include #include #include #include #include namespace sprout { // // generator_iterator // template class generator_iterator : public sprout::iterator< std::forward_iterator_tag, typename std::remove_reference()))>::type, std::ptrdiff_t, typename std::remove_reference()))>::type*, decltype(sprout::generators::generated_value(std::declval())) > { public: typedef Generator generator_type; typedef std::forward_iterator_tag iterator_category; typedef typename sprout::identity()))>::type reference; typedef typename std::remove_reference::type value_type; typedef std::ptrdiff_t difference_type; typedef value_type* pointer; private: generator_type gen_; difference_type index_; public: SPROUT_CONSTEXPR generator_iterator() : gen_(), index_() {} explicit SPROUT_CONSTEXPR generator_iterator( generator_type const& gen, difference_type index = sprout::numeric_limits::max() ) : gen_(gen), index_(index) {} SPROUT_CXX14_CONSTEXPR generator_type& generator() { return gen_; } SPROUT_CONSTEXPR generator_type const& generator() const { return gen_; } SPROUT_CONSTEXPR difference_type index() const { return index_; } SPROUT_CONSTEXPR generator_iterator operator()() const { return generator_iterator(sprout::generators::next_generator(gen_)(), index_ - 1); } SPROUT_CONSTEXPR generator_iterator next() const { return (*this)(); } SPROUT_CONSTEXPR reference generated_value() const { return sprout::generators::generated_value(gen_); } SPROUT_CONSTEXPR generator_iterator next_generator() const { return (*this)(); } SPROUT_CONSTEXPR operator reference() const { return generated_value(); } SPROUT_CXX14_CONSTEXPR void swap(generator_iterator& other) SPROUT_NOEXCEPT_IF_EXPR(sprout::swap(gen_, other.gen_)) { sprout::swap(gen_, other.gen_); sprout::swap(index_, other.index_); } SPROUT_CONSTEXPR reference operator*() const { return sprout::generators::generated_value(gen_); } SPROUT_CONSTEXPR pointer operator->() const { return &*(*this); } SPROUT_CXX14_CONSTEXPR generator_iterator& operator++() { generator_iterator temp((*this)()); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR generator_iterator operator++(int) { generator_iterator result(*this); ++*this; return result; } }; template inline SPROUT_CONSTEXPR bool operator==(sprout::generator_iterator const& lhs, sprout::generator_iterator const& rhs) { return lhs.index() == rhs.index(); } template inline SPROUT_CONSTEXPR bool operator!=(sprout::generator_iterator const& lhs, sprout::generator_iterator const& rhs) { return !(lhs == rhs); } template inline SPROUT_CONSTEXPR bool operator<(sprout::generator_iterator const& lhs, sprout::generator_iterator const& rhs) { return rhs.index() < lhs.index(); } template inline SPROUT_CONSTEXPR bool operator>(sprout::generator_iterator const& lhs, sprout::generator_iterator const& rhs) { return rhs < lhs; } template inline SPROUT_CONSTEXPR bool operator<=(sprout::generator_iterator const& lhs, sprout::generator_iterator const& rhs) { return !(rhs < lhs); } template inline SPROUT_CONSTEXPR bool operator>=(sprout::generator_iterator const& lhs, sprout::generator_iterator const& rhs) { return !(lhs < rhs); } template inline SPROUT_CONSTEXPR typename sprout::generator_iterator::difference_type operator-(sprout::generator_iterator const& lhs, sprout::generator_iterator const& rhs) { return rhs.index() - lhs.index(); } // // swap // template inline SPROUT_CXX14_CONSTEXPR void swap(sprout::generator_iterator& lhs, sprout::generator_iterator& rhs) SPROUT_NOEXCEPT_IF_EXPR(lhs.swap(rhs)) { lhs.swap(rhs); } // // iterator_next // template inline SPROUT_CONSTEXPR sprout::generator_iterator iterator_next(sprout::generator_iterator const& it) { return it.next(); } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_GENERATOR_ITERATOR_HPP