Github   Telegram
Loading...
Searching...
No Matches
items.hpp
1#pragma once
2
3#include <cstddef>
4#include <iterator>
5#include <string>
6#include <type_traits>
7
8USERVER_NAMESPACE_BEGIN
9
10namespace formats::common {
11
12template <typename Value>
13class ItemsWrapper final {
14 public:
15 class Iterator {
16 public:
17 using RawIterator = decltype(std::declval<Value>().begin());
18
19 struct ItValue {
20 std::string key;
21 typename RawIterator::reference value;
22 };
23
24 using iterator_category = std::forward_iterator_tag;
25 using difference_type = std::ptrdiff_t;
26 using value_type = ItValue;
27 using reference = ItValue;
28
29 explicit Iterator(RawIterator it) : it_(it) {}
30 Iterator(const Iterator& other) = default;
31 Iterator(Iterator&& other) noexcept = default;
32
33 Iterator& operator=(const Iterator& other) = default;
34 Iterator& operator=(Iterator&& other) noexcept = default;
35
36 ItValue operator*() const { return {it_.GetName(), *it_}; }
37
38 Iterator operator++(int) {
39 auto it = *this;
40 return {it++};
41 }
42
43 Iterator& operator++() {
44 ++it_;
45 return *this;
46 }
47
48 bool operator==(const Iterator& other) const { return it_ == other.it_; }
49
50 bool operator!=(const Iterator& other) const { return !(*this == other); }
51
52 private:
53 RawIterator it_;
54 };
55
56 ItemsWrapper(Value&& value) : value_(static_cast<Value&&>(value)) {}
57
58 auto begin() const { return cbegin(); }
59 auto end() const { return cend(); }
60 auto cbegin() const { return Iterator(value_.begin()); }
61 auto cend() const { return Iterator(value_.end()); }
62
63 private:
64 Value value_;
65};
66
67template <typename Value>
68inline auto Items(Value&& value) {
69 // when passed an lvalue, store by reference
70 // when passed an rvalue, store by value
71 return ItemsWrapper<Value>(static_cast<Value&&>(value));
72}
73
74} // namespace formats::common
75
76USERVER_NAMESPACE_END