#ifndef PYTHONIC_ITERTOOLS_PRODUCT_HPP #define PYTHONIC_ITERTOOLS_PRODUCT_HPP #include "pythonic/include/itertools/product.hpp" #include "pythonic/utils/int_.hpp" #include "pythonic/utils/seq.hpp" #include "pythonic/utils/iterator.hpp" #include "pythonic/itertools/common.hpp" #include "pythonic/utils/functor.hpp" PYTHONIC_NS_BEGIN namespace itertools { namespace details { /// product iterator implementation template template product_iterator::product_iterator( std::tuple &_iters, utils::index_sequence const &) : it_begin(std::get(_iters).begin()...), it_end(std::get(_iters).end()...), it(std::get(_iters).begin()...), end(it_begin == it_end) { } template template product_iterator::product_iterator( npos, std::tuple &_iters, utils::index_sequence const &) : it_begin(std::get(_iters).end()...), it_end(std::get(_iters).end()...), it(std::get(_iters).end()...), end(true) { } template template types::make_tuple_t product_iterator::get_value( utils::index_sequence const &) const { return types::make_tuple(*std::get(it)...); } template types::make_tuple_t product_iterator::operator*() const { return get_value(utils::make_index_sequence{}); } template template void product_iterator::advance(utils::int_) { if (++std::get(it) == std::get(it_end)) { std::get(it) = std::get(it_begin); advance(utils::int_()); } } template void product_iterator::advance(utils::int_<0>) { if (++std::get<0>(it) == std::get<0>(it_end)) end = true; } template product_iterator &product_iterator::operator++() { advance(utils::int_{}); return *this; } template bool product_iterator:: operator==(product_iterator const &other) const { return end == other.end; } template bool product_iterator:: operator!=(product_iterator const &other) const { return end != other.end; } template bool product_iterator:: operator<(product_iterator const &other) const { return end != other.end; } /// details product implementation // FIXME: Iterators need to be evaluated as they may be used multiple // times template product::product(Iters const &... _iters) : utils::iterator_reminder(_iters...), iterator(this->values, utils::make_index_sequence{}), end_iter(npos(), this->values, utils::make_index_sequence{}) { } template typename product::iterator &product::begin() { return *this; } template typename product::iterator const &product::begin() const { return *this; } template typename product::iterator const &product::end() const { return end_iter; } } template details::product::type>::type...> product(Iter &&... iters) { return {std::forward(iters)...}; } } PYTHONIC_NS_END #endif