/*+ ARES/HADES/BORG Package -- ./libLSS/tools/itertools.hpp Copyright (C) 2019 Guilhem Lavaux Additional contributions from: Guilhem Lavaux (2023) +*/ #ifndef __LIBLSS_ITERTOOLS_HPP #define __LIBLSS_ITERTOOLS_HPP #include #include #include namespace LibLSS { namespace itertools { template auto enumerate_base(size_t i, I j) -> decltype(boost::make_zip_iterator( boost::make_tuple(boost::counting_iterator(i), j))) { return boost::make_zip_iterator( boost::make_tuple(boost::counting_iterator(i), j)); } template struct Enumerate { public: T const &t; Enumerate(T const &t_) : t(t_) {} auto begin() const -> decltype(enumerate_base(0, t.begin())) { return enumerate_base(0, t.begin()); } auto end() const -> decltype(enumerate_base(t.size(), t.end())) { return enumerate_base(t.size(), t.end()); } }; struct Range { size_t i0, i1; Range(size_t i0_, size_t i1_) : i0(i0_), i1(i1_) {} auto begin() const -> decltype(boost::counting_iterator(i0)) { return boost::counting_iterator(i0); } auto end() const -> decltype(boost::counting_iterator(i1)) { return boost::counting_iterator(i1); } }; /** * This function creates a pseudo container (range container) over * which one can iterate upon. * A typical use is: * * for (size_t id: range(0, N)) { blabla; } * * * @param i0 start of the range * @param i1 end of the range * @return a container */ inline Range range(size_t i0, size_t i1) { return Range(i0, i1); } /** * This function creates a pseudo container made of a zip iterator binding * a range and an iterator over the provided container. * A typical use is: * * for (auto x: enumerate(some_vector)) { * size_t id = x.get<0>(); * // Some stuff * the_type_in_vector const& v = x.get<1>(); * } * * * @param t a container * @return a container with an enumeration */ template inline Enumerate enumerate(T const &t) { return Enumerate(t); } } // namespace itertools } // namespace LibLSS #endif // ARES TAG: authors_num = 1 // ARES TAG: name(0) = Guilhem Lavaux // ARES TAG: email(0) = guilhem.lavaux@iap.fr // ARES TAG: year(0) = 2019