enumerate.h 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #pragma once
  2. #if __cplusplus >= 202302L
  3. #include <ranges>
  4. #if __cpp_lib_ranges_enumerate >= 202302L
  5. #define JVALIDATE_USE_STD_RANGES_ENUMERATE
  6. #endif
  7. #endif
  8. #ifdef JVALIDATE_USE_STD_RANGES_ENUMERATE
  9. namespace jvalidate::detail {
  10. using std::ranges::views::enumerate;
  11. }
  12. #else
  13. #include <cstdlib>
  14. #include <iterator>
  15. #include <utility>
  16. #include <jvalidate/detail/deref_proxy.h>
  17. namespace jvalidate::detail {
  18. /**
  19. * @brief A replacement for std::ranges::views::enumerate in C++20 (as enumerate
  20. * is a C++23 feature).
  21. * Much like python's enumerate() function, this is an iterator adapter that
  22. * attaches the "index" of the iteration to each element - incrementing it as
  23. * we go.
  24. */
  25. template <typename It> class enumurate_iterator { // NOLINT(readability-identifier-naming)
  26. public:
  27. using traits_t = std::iterator_traits<It>;
  28. using value_type = std::pair<size_t, typename traits_t::value_type>;
  29. using reference = std::pair<size_t const &, typename traits_t::reference>;
  30. using pointer = DerefProxy<reference>;
  31. using difference_type = traits_t::difference_type;
  32. using iterator_category = std::forward_iterator_tag;
  33. private:
  34. size_t index_ = 0;
  35. It iter_;
  36. public:
  37. explicit(false) enumurate_iterator(It iter) : iter_(std::move(iter)) {}
  38. reference operator*() const { return {index_, *iter_}; }
  39. pointer operator->() const { return operator*(); }
  40. enumurate_iterator & operator++() {
  41. ++index_;
  42. ++iter_;
  43. return *this;
  44. }
  45. friend bool operator==(enumurate_iterator<It> const & rhs, enumurate_iterator<It> const & lhs) {
  46. return rhs.iter_ == lhs.iter_;
  47. }
  48. friend bool operator!=(enumurate_iterator<It> const & rhs, enumurate_iterator<It> const & lhs) {
  49. return rhs.iter_ != lhs.iter_;
  50. }
  51. };
  52. template <typename C> auto enumerate(C && container) {
  53. struct {
  54. auto begin() const { return enumurate_iterator(c.begin()); }
  55. auto end() const { return enumurate_iterator(c.end()); }
  56. C c;
  57. } rval{std::forward<C>(container)};
  58. return rval;
  59. }
  60. }
  61. #endif