OXYGENHUB
◆ main openmsx / src / utils / enumerate.hh
1.4 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef ENUMERATE_HH
2
#define ENUMERATE_HH
3
4
/** Heavily inspired by Nathan Reed's blog post:
5
  * Python-Like enumerate() In C++17
6
  * http://reedbeta.com/blog/python-like-enumerate-in-cpp17/
7
  *
8
  * Can be used to simplify loops like:
9
  *    for (size_t i = 0; i < std::size(my_array); ++i) {
10
  *        auto& elem = my_array[i];
11
  *        ... do stuff with 'i' and 'elem'
12
  *    }
13
  *
14
  * With enumerate() that becomes:
15
  *    for (auto [i, elem] : enumerate(my_array)) {
16
  *        ... do stuff with 'i' and 'elem'
17
  *    }
18
  */
19
20
#include <cstddef>
21
#include <iterator>
22
#include <tuple>
23
#include <utility>
24
25
template<typename Iterable,
26
         typename Iter = decltype(std::begin(std::declval<Iterable>())),
27
         typename      = decltype(std::end  (std::declval<Iterable>()))>
28
constexpr auto enumerate(Iterable&& iterable)
29
{
30
	struct iterator {
31
		size_t i;
32
		Iter iter;
33
34
		[[nodiscard]] constexpr bool operator==(const iterator& other) const {
35
			return iter == other.iter;
36
		}
37
38
		[[nodiscard]] constexpr bool operator==(const Iter& other) const {
39
			return iter == other;
40
		}
41
42
		constexpr void operator++() {
43
			++i;
44
			++iter;
45
		}
46
		constexpr auto operator*() const {
47
			return std::tie(i, *iter);
48
		}
49
	};
50
51
	struct iterable_wrapper {
52
		Iterable iterable;
53
54
		constexpr auto begin() {
55
			return iterator{0, std::begin(iterable)};
56
		}
57
		constexpr auto end() {
58
			return std::end(iterable);
59
		}
60
	};
61
62
	return iterable_wrapper{std::forward<Iterable>(iterable)};
63
}
64
65
#endif