userver: userver/utils/enumerate.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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