unkeyed_iterator.hpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. //
  2. // unkeyed_iterator.hpp
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/20/17.
  6. //
  7. #pragma once
  8. #include <iterator>
  9. namespace iterator {
  10. /**
  11. * At first glance, this class seems like it acts as an iterator that would be
  12. * used in the C++ equivalent of Java's Map::values() function. However,
  13. * notices that we do not assume that the input iterator is a map iterator.
  14. * The useful feature of this iterator - and the source of its name - is its
  15. * ability to be composed with recursive_iterator. This means that you can
  16. * have something crazy like a four-level map and then do:
  17. * \code
  18. * std::map<int, std::map<std::string, std::map<int, BigType>>> object;
  19. * auto const rit = make_recursive_iterator(object);
  20. * for (unkeyed_iterator<decltype(rit)> it = rit, end = {}; it != end; ++it) {
  21. * // Process only BigType, discarding all of the keys that we need to walk
  22. * }
  23. * \endcode
  24. */
  25. template <typename Iterator> class unkeyed_iterator {
  26. private:
  27. using impl_value_type = typename std::iterator_traits<Iterator>::value_type;
  28. using impl_reference = typename std::iterator_traits<Iterator>::reference;
  29. static constexpr std::size_t const value_index =
  30. std::tuple_size<impl_value_type>::value - 1;
  31. public:
  32. using value_type = typename std::remove_reference<decltype(
  33. std::get<value_index>(std::declval<impl_value_type>()))>::type;
  34. using reference =
  35. decltype(std::get<value_index>(std::declval<impl_reference>()));
  36. using pointer = value_type *;
  37. using difference_type =
  38. typename std::iterator_traits<Iterator>::difference_type;
  39. using iterator_category =
  40. typename std::iterator_traits<Iterator>::iterator_category;
  41. unkeyed_iterator() = default;
  42. unkeyed_iterator(Iterator it) : base(it) {}
  43. reference operator*() const { return std::get<value_index>(*base); }
  44. pointer operator->() const { return std::addressof(operator*()); }
  45. unkeyed_iterator & operator++() {
  46. ++base;
  47. return *this;
  48. }
  49. unkeyed_iterator operator++(int) {
  50. unkeyed_iterator tmp{*this};
  51. operator++();
  52. return tmp;
  53. }
  54. unkeyed_iterator & operator--() {
  55. --base;
  56. return *this;
  57. }
  58. unkeyed_iterator operator--(int) {
  59. unkeyed_iterator tmp{*this};
  60. operator--();
  61. return tmp;
  62. }
  63. bool operator==(unkeyed_iterator const & other) const {
  64. return base == other.base;
  65. }
  66. bool operator!=(unkeyed_iterator const & other) const {
  67. return base != other.base;
  68. }
  69. private:
  70. Iterator base;
  71. };
  72. }