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 return {it++};
48 }
49
50 Iterator& operator++() {
51 ++it_;
52 return *this;
53 }
54
55 bool operator==(const Iterator& other) const { return it_ == other.it_; }
56
57 bool operator!=(const Iterator& other) const { return !(*this == other); }
58
59 private:
60 RawIterator it_;
61 };
62
63 ItemsWrapper(Value&& value) : value_(static_cast<Value&&>(value)) {}
64
65 auto begin() const { return cbegin(); }
66 auto end() const { return cend(); }
67 auto cbegin() const { return Iterator(value_.begin()); }
68 auto cend() const { return Iterator(value_.end()); }
69
70 private:
71 Value value_;
72};
73
74/// @brief Wrapper for handy python-like iteration over a map
75///
76/// @code
77/// for (const auto& [name, value]: Items(map)) ...
78/// @endcode
79template <typename Value>
80ItemsWrapper<Value> Items(Value&& value) {
81 // when passed an lvalue, store by reference
82 // when passed an rvalue, store by value
83 return ItemsWrapper<Value>(static_cast<Value&&>(value));
84}
85
86} // namespace formats::common
87
88USERVER_NAMESPACE_END