userver: userver/utils/enumerate.hpp Source File
Loading...
Searching...
No Matches
enumerate.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/enumerate.hpp
4/// @brief @copybrief utils::enumerate
5/// @ingroup userver_universal
6
7#include <tuple>
8#include <utility>
9
10USERVER_NAMESPACE_BEGIN
11
12namespace utils::impl {
13
14template <typename Iter>
15struct IteratorWrapper {
16 Iter iterator;
17 size_t pos{0};
18
19 constexpr auto& operator++() {
20 ++pos;
21 ++iterator;
22 return *this;
23 }
24 constexpr std::tuple<const size_t, decltype(*iterator)> operator*() const {
25 return {pos, *iterator};
26 }
27 constexpr std::tuple<const size_t, decltype(*iterator)> operator*() {
28 return {pos, *iterator};
29 }
30
31 constexpr bool operator==(const IteratorWrapper& other) const {
32 return iterator == other.iterator;
33 }
34 constexpr bool operator!=(const IteratorWrapper& other) const {
35 return !(iterator == other.iterator);
36 }
37};
38
39template <typename Container,
40 typename Iter = decltype(std::begin(std::declval<Container>())),
41 typename = decltype(std::end(std::declval<Container>()))>
42struct ContainerWrapper {
43 using Iterator = IteratorWrapper<Iter>;
44 Container container;
45
46 constexpr auto begin() { return Iterator{std::begin(container), 0}; }
47 constexpr auto end() { return Iterator{std::end(container), 0}; }
48 constexpr auto begin() const { return Iterator{std::begin(container), 0}; }
49 constexpr auto end() const { return Iterator{std::end(container), 0}; }
50};
51} // namespace utils::impl
52
53namespace utils {
54
55/// @brief Implementation of python-style enumerate function for range-for loops
56/// @param iterable: Container to iterate
57/// @returns ContainerWrapper, which iterator after dereference returns tuple
58/// of index and (!!!)non-const reference to element(it seems impossible to make
59/// this reference const). It can be used in "range based for loop" with
60/// "structured binding" like this
61/// @code
62/// for (auto [pos, elem] : enumerate(someContainer)) {...}
63/// @endcode
64template <typename Container>
65constexpr auto enumerate(Container&& iterable) {
66 return impl::ContainerWrapper<Container>{std::forward<Container>(iterable)};
67}
68
69} // namespace utils
70
71USERVER_NAMESPACE_END