userver: userver/formats/common/items.hpp Source File
Loading...
Searching...
No Matches
items.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/formats/common/items.hpp
4/// @brief @copybrief formats::common::Items()
5/// @ingroup userver_universal
6
7#include <cstddef>
8#include <iterator>
9#include <string>
10#include <type_traits>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace formats::common {
15
16/// @brief Wrapper for handy python-like iteration over a map.
17///
18/// See formats::common::Items() for usage example
19template <typename Value>
20class ItemsWrapper final {
21 public:
22 class Iterator {
23 public:
24 using RawIterator = decltype(std::declval<Value>().begin());
25
26 struct ItValue {
27 std::string key;
28 typename RawIterator::reference value;
29 };
30
31 using iterator_category = std::forward_iterator_tag;
32 using difference_type = std::ptrdiff_t;
33 using value_type = ItValue;
34 using reference = ItValue;
35
36 explicit Iterator(RawIterator it) : it_(it) {}
37 Iterator(const Iterator& other) = default;
38 Iterator(Iterator&& other) noexcept = default;
39
40 Iterator& operator=(const Iterator& other) = default;
41 Iterator& operator=(Iterator&& other) noexcept = default;
42
43 ItValue operator*() const { return {it_.GetName(), *it_}; }
44
45 Iterator operator++(int) {
46 auto it = *this;
47 ++it_;
48 return it;
49 }
50
51 Iterator& operator++() {
52 ++it_;
53 return *this;
54 }
55
56 bool operator==(const Iterator& other) const { return it_ == other.it_; }
57
58 bool operator!=(const Iterator& other) const { return !(*this == other); }
59
60 private:
61 RawIterator it_;
62 };
63
64 ItemsWrapper(Value&& value) : value_(static_cast<Value&&>(value)) {}
65
66 auto begin() const { return cbegin(); }
67 auto end() const { return cend(); }
68 auto cbegin() const { return Iterator(value_.begin()); }
69 auto cend() const { return Iterator(value_.end()); }
70
71 private:
72 Value value_;
73};
74
75/// @brief Wrapper for handy python-like iteration over a map
76///
77/// @code
78/// for (const auto& [name, value]: Items(map)) ...
79/// @endcode
80///
81/// To move out values:
82/// @code
83/// for (auto [name, value]: Items(map)) {
84/// vector.push_back(std::move(name));
85/// // value is a const reference and can not be moved
86/// }
87/// @endcode
88template <typename Value>
89ItemsWrapper<Value> Items(Value&& value) {
90 // when passed an lvalue, store by reference
91 // when passed an rvalue, store by value
92 return ItemsWrapper<Value>(static_cast<Value&&>(value));
93}
94
95} // namespace formats::common
96
97USERVER_NAMESPACE_END