| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- //
- // recursive_iterator.hpp
- // iterator
- //
- // Created by Sam Jaffe on 2/17/17.
- //
- #pragma once
- #include <tuple>
- #include "detail/recursive_iterator_impl.hpp"
- #include "detail/recursive_iterator_traits.hpp"
- #include "iterator_fwd.hpp"
- namespace iterator {
- /**
- * @class recursive_iterator
- * @brief An iterator type for nested collections, allowing you to treat it as
- * a single-layer collection.
- *
- * In order to provide a simple interface, if an associative container is used
- * in the chain, the type returned by operator*() is a tuple. If multiple
- * associative containers are nested, then the tuple will be of the form
- * std::tuple<key1, key2, ..., keyN, value>. To avoid copies, and allow
- * editting of underlying values, the tuple contains references.
- *
- * @tparam Iterator The iterator type of the top-level collection.
- */
- template <typename Iterator>
- class recursive_iterator : public detail::recursive_iterator_impl<Iterator> {
- public:
- using super = detail::recursive_iterator_impl<Iterator>;
- public:
- using super::super;
- recursive_iterator() = default;
- recursive_iterator & operator++() {
- (void)super::next();
- return *this;
- }
- recursive_iterator operator++(int) {
- recursive_iterator tmp{*this};
- (void)super::next();
- return tmp;
- }
- bool operator!=(recursive_iterator const & other) const {
- return !(super::operator==(other));
- }
- };
- /**
- * @class recursive_iterator_n
- * @copydoc recursive_iterator
- * This object has bounded recursive depth, so that it can be used to get
- * sub-collections, which may be used in other functions.
- *
- * For Example:
- * @code
- * using map_type = std::map<std::string, std::map<std::string,
- * std::vector<Data> > >;
- * ...
- * recursive_iterator_n<map_type::iterator, 2> iter{ ... };
- * std::vector<Data> & data = std::get<2>(*iter);
- * reload_data_from_file( std::get<1>(*iter), data );
- * @endcode
- *
- * @tparam N The maximum depth to recurse into the object
- */
- template <typename Iterator, std::size_t N>
- class recursive_iterator_n
- : public detail::bounded_recursive_iterator_impl<Iterator, 1, N> {
- public:
- using super = detail::bounded_recursive_iterator_impl<Iterator, 1, N>;
- public:
- using super::super;
- recursive_iterator_n() = default;
- recursive_iterator_n & operator++() {
- (void)super::next();
- return *this;
- }
- recursive_iterator_n operator++(int) {
- recursive_iterator_n tmp{*this};
- (void)super::next();
- return tmp;
- }
- bool operator!=(recursive_iterator_n const & other) const {
- return !(super::operator==(other));
- }
- };
- }
- namespace std {
- template <std::size_t I, typename It>
- auto get(::iterator::recursive_iterator<It> const & iter) ->
- typename ::iterator::detail::accessor<
- I, ::iterator::recursive_iterator<It>>::type {
- return iter;
- }
- template <std::size_t I, typename It, std::size_t N>
- auto get(::iterator::recursive_iterator_n<It, N> const & iter) ->
- typename ::iterator::detail::accessor<
- I, ::iterator::recursive_iterator_n<It, N>>::type {
- static_assert(I < N, "Cannot get past bounding level");
- return iter;
- }
- }
- template <typename C>
- auto make_recursive_iterator(C & collect)
- -> iterator::recursive_iterator<decltype(std::begin(collect))> {
- return {make_end_aware_iterator(collect)};
- }
- template <typename C>
- auto make_recursive_iterator(C const & collect)
- -> iterator::recursive_iterator<decltype(std::begin(collect))> {
- return {make_end_aware_iterator(collect)};
- }
- template <std::size_t Max, typename C>
- auto make_recursive_iterator(C & collect)
- -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
- return {make_end_aware_iterator(collect)};
- }
- template <std::size_t Max, typename C>
- auto make_recursive_iterator(C const & collect)
- -> iterator::recursive_iterator_n<decltype(std::begin(collect)), Max> {
- return {make_end_aware_iterator(collect)};
- }
|