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
value_type operator*()
const
{
return
{pos, *iterator}; }
40
41
template
<
typename
OtherIter>
42
constexpr
bool
operator==(
const
IteratorWrapper<OtherIter>& other)
const
{
43
return
iterator == other.iterator;
44
}
45
46
template
<
typename
OtherIter>
47
constexpr
bool
operator!=(
const
IteratorWrapper<OtherIter>& other)
const
{
48
return
!(iterator == other.iterator);
49
}
50
};
51
52
template
<
typename
Range>
53
using
IteratorTypeOf =
decltype
(std::begin(std::declval<Range&>()));
54
55
template
<
typename
Range>
56
using
SentinelTypeOf =
decltype
(std::end(std::declval<Range&>()));
57
58
template
<
typename
Container>
59
struct
ContainerWrapper {
60
constexpr
IteratorWrapper<IteratorTypeOf<Container>> begin() {
61
return
{.iterator = std::begin(container), .pos = 0};
62
}
63
64
constexpr
IteratorWrapper<SentinelTypeOf<Container>> end() {
return
{.iterator = std::end(container), .pos = 0}; }
65
66
constexpr
IteratorWrapper<IteratorTypeOf<
const
Container>> begin()
const
{
67
return
{.iterator = std::begin(container), .pos = 0};
68
}
69
70
constexpr
IteratorWrapper<SentinelTypeOf<
const
Container>> end()
const
{
71
return
{.iterator = std::end(container), .pos = 0};
72
}
73
74
Container container;
75
};
76
77
}
// namespace utils::impl
78
79
namespace
utils
{
80
81
/// @brief Implementation of python-style enumerate function for range-for loops
82
/// @param iterable: Container to iterate
83
/// @returns ContainerWrapper, which iterator after dereference returns pair
84
/// of index and (!!!)non-const reference to element(it seems impossible to make
85
/// this reference const). It can be used in "range based for loop" with
86
/// "structured binding" like this
87
/// @code
88
/// for (auto [pos, elem] : enumerate(someContainer)) {...}
89
/// @endcode
90
template
<
typename
Container>
91
constexpr
auto
enumerate
(Container&& iterable) {
// NOLINT(readability-identifier-naming)
92
return
impl::ContainerWrapper<Container>{std::forward<Container>(iterable)};
93
}
94
95
}
// namespace utils
96
97
USERVER_NAMESPACE_END
userver
utils
enumerate.hpp
Generated on
for userver by
Doxygen
1.17.0