userver
C++ Async Framework
Toggle main menu visibility
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
<
cstddef
>
8
#
include
<
cstdint
>
9
#
include
<
iterator
>
10
#
include
<
type_traits
>
11
#
include
<
utility
>
12
13
USERVER_NAMESPACE_BEGIN
14
15
namespace
utils
::impl {
16
17
template
<
typename
Iter>
18
auto
DetectEnumerateValueType() -> std::pair<
const
std::size_t,
decltype
(*std::declval<Iter>())>;
19
20
template
<
typename
Iter,
typename
... Args>
21
auto
DetectEnumerateValueType(Args&&...) ->
void
;
22
23
template
<
typename
Iter>
24
struct
IteratorWrapper {
25
using
difference_type = std::ptrdiff_t;
26
using
value_type =
decltype
(DetectEnumerateValueType<Iter>());
27
using
reference = value_type;
28
using
iterator_category = std::input_iterator_tag;
29
30
Iter iterator;
31
std::size_t pos{0};
32
33
constexpr
IteratorWrapper& operator++() {
34
++pos;
35
++iterator;
36
return
*
this
;
37
}
38
39
constexpr
IteratorWrapper operator++(
int
) {
40
IteratorWrapper copy{*
this
};
41
++*
this
;
42
return
copy;
43
}
44
45
constexpr
value_type operator*()
const
{
return
{pos, *iterator}; }
46
47
template
<
typename
OtherIter>
48
constexpr
bool
operator==(
const
IteratorWrapper<OtherIter>& other)
const
{
49
return
iterator == other.iterator;
50
}
51
};
52
53
template
<
typename
Iter>
54
constexpr
IteratorWrapper<Iter> MakeIteratorWrapper(Iter iterator) {
55
return
IteratorWrapper<Iter>{.iterator = std::move(iterator), .pos = 0};
56
}
57
58
template
<
typename
Container>
59
struct
ContainerWrapper {
60
constexpr
auto
begin() {
return
MakeIteratorWrapper(std::begin(container)); }
61
62
constexpr
auto
end() {
return
MakeIteratorWrapper(std::end(container)); }
63
64
constexpr
auto
begin()
const
{
return
MakeIteratorWrapper(std::begin(std::as_const(container))); }
65
66
constexpr
auto
end()
const
{
return
MakeIteratorWrapper(std::end(std::as_const(container))); }
67
68
Container container;
69
};
70
71
}
// namespace utils::impl
72
73
namespace
utils
{
74
75
/// @brief Implementation of python-style enumerate function for range-for loops
76
/// @param iterable: Container to iterate
77
/// @returns ContainerWrapper, which iterator after dereference returns pair
78
/// of index and reference to element. The reference is const-qualified if either
79
/// the wrapper itself or the underlying container is const; otherwise, it is non-const.
80
/// It can be used in "range based for loop" with "structured binding" like this
81
/// @code
82
/// for (auto [pos, elem] : enumerate(someContainer)) {...}
83
/// @endcode
84
template
<
typename
Container>
85
constexpr
auto
enumerate
(Container&& iterable) {
// NOLINT(readability-identifier-naming)
86
return
impl::ContainerWrapper<Container>{std::forward<Container>(iterable)};
87
}
88
89
}
// namespace utils
90
91
USERVER_NAMESPACE_END
userver
utils
enumerate.hpp
Generated on
for userver by
Doxygen
1.17.0