AUI Framework  master
Cross-platform module-based framework for developing C++20 desktop applications
AMap.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12#pragma once
13#include <map>
14#include <unordered_map>
15#include "AUI/Core.h"
16#include "AException.h"
17#include <AUI/Common/AVector.h>
18#include <AUI/Traits/containers.h>
19#include <AUI/Reflect/AClass.h>
20#include "AContainerPrototypes.h"
21
26template <class KeyType, class ValueType, class Parent>
27class ABaseMap: public Parent
28{
29public:
30 using iterator = typename Parent::iterator;
31 using const_iterator = typename Parent::const_iterator;
32
33 using Parent::Parent;
34
35 ValueType& operator[](KeyType&& k)
36 {
37 return Parent::operator[](std::move(k));
38 }
39
40 ValueType& operator[](const KeyType& k)
41 {
42 return Parent::operator[](k);
43 }
44
45 const ValueType& operator[](KeyType&& k) const
46 {
47 return Parent::at(std::move(k));
48 }
49
50 const ValueType& operator[](const KeyType& k) const
51 {
52 return Parent::at(k);
53 }
54
55 // ================
56
58 {
59 private:
60 iterator mIterator;
61 bool mValid;
62
63 public:
64 contains_iterator(const iterator& p, bool valid):
65 mIterator(p),
66 mValid(valid)
67 {
68
69 }
71 mIterator(c.mIterator),
72 mValid(c.mValid)
73 {
74
75 }
76
77 operator bool() const noexcept {
78 return mValid;
79 }
80
81 iterator operator->() const noexcept
82 {
83 return mIterator;
84 }
85 iterator operator*() const noexcept
86 {
87 return mIterator;
88 }
89 };
91 {
92 private:
93 const_iterator mIterator;
94 bool mValid;
95
96 public:
97 const_contains_iterator(const const_iterator& p, bool valid):
98 mIterator(p),
99 mValid(valid)
100 {
101
102 }
104 mIterator(c.mIterator),
105 mValid(c.mValid)
106 {
107
108 }
109
110 operator bool() const noexcept {
111 return mValid;
112 }
113
114 const_iterator operator->() const noexcept
115 {
116 return mIterator;
117 }
118 const_iterator operator*() const noexcept
119 {
120 return mIterator;
121 }
122 };
123
124 ValueType& at(const KeyType& key) {
125 auto it = Parent::find(key);
126 if (it == Parent::end())
127 throw AException("no such element: " + AClass<KeyType>::toString(key));
128 return it->second;
129 }
130 const ValueType& at(const KeyType& key) const {
131 auto it = Parent::find(key);
132 if (it == Parent::end())
133 throw AException("no such element: " + AClass<KeyType>::toString(key));
134 return it->second;
135 }
136
137 [[nodiscard]]
138 const_contains_iterator contains(const KeyType& key) const noexcept
139 {
140 auto it = Parent::find(key);
141 return const_contains_iterator(it, it != Parent::end());
142 }
143
144 [[nodiscard]]
145 contains_iterator contains(const KeyType& key) noexcept
146 {
147 auto it = Parent::find(key);
148 return contains_iterator(it, it != Parent::end());
149 }
150
151 [[nodiscard]]
152 AOptional<ValueType> optional(const KeyType& key) const noexcept {
153 auto it = Parent::find(key);
154 if (it == Parent::end()) {
155 return std::nullopt;
156 }
157 return it->second;
158 }
159
160 AVector<KeyType> keyVector() {
162 r.reserve(Parent::size());
163 for (auto& p : *this) {
164 r << p.first;
165 }
166 return r;
167 }
168 AVector<ValueType> valueVector() {
170 r.reserve(Parent::size());
171 for (auto& p : *this) {
172 r << p.second;
173 }
174 return r;
175 }
176
184 template<typename Factory>
185 ValueType& getOrInsert(const KeyType& keyType, Factory&& factory) noexcept(noexcept(factory())) {
186 static_assert(std::is_constructible_v<ValueType>, "ValueType is expected to be default-constructible");
187 auto[it, isElementCreated] = Parent::insert(typename Parent::value_type(keyType, ValueType{}));
188 static_assert(std::is_same_v<decltype(it), typename Parent::iterator>, "govno");
189 if (isElementCreated) {
190 it->second = factory();
191 }
192 return it->second;
193 }
194
195 template<typename BinaryOperation>
196 auto toVector(BinaryOperation&& transformer) const -> AVector<decltype(transformer(std::declval<KeyType>(), std::declval<ValueType>()))> {
197 AVector<decltype(transformer(std::declval<KeyType>(), std::declval<ValueType>()))> result;
198 result.reserve(Parent::size());
199 std::transform(Parent::begin(), Parent::end(), std::back_inserter(result), [transformer = std::forward<BinaryOperation>(transformer)](const typename Parent::value_type& p){
200 return transformer(p.first, p.second);
201 });
202 return result;
203 }
204
206 return toVector([](const KeyType& k, const ValueType& v) {
207 return std::make_tuple(k, v);
208 });
209 }
210};
211
216template <class KeyType, class ValueType, class Predicate, class Allocator>
217class AMap: public ABaseMap<KeyType, ValueType, std::map<KeyType, ValueType, Predicate, Allocator>>
218{
220
221 using parent::parent;
222};
223
228template <class KeyType, class ValueType, class Hasher, class Comparer, class Allocator>
229class AUnorderedMap: public ABaseMap<KeyType, ValueType, std::unordered_map<KeyType, ValueType, Hasher, Comparer, Allocator>>
230{
232
233 using parent::parent;
234};
235
236template<typename Iterator, typename UnaryOperation>
237inline auto aui::container::to_map(Iterator begin,
238 Iterator end,
239 UnaryOperation&& transformer) {
240 AMap<decltype(transformer(*begin).first),
241 decltype(transformer(*begin).second)> result;
242
243 for (auto it = begin; it != end; ++it) {
244 auto[key, value] = transformer(*it);
245 result[std::move(key)] = std::move(value);
246 }
247 return result;
248}
249
250template<typename Iterator, typename UnaryOperation>
251inline auto aui::container::to_unordered_map(Iterator begin,
252 Iterator end,
253 UnaryOperation&& transformer) {
254 AUnorderedMap<decltype(transformer(*begin).first),
255 decltype(transformer(*begin).second)> result;
256
257 for (auto it = begin; it != end; ++it) {
258 auto[key, value] = transformer(*it);
259 result[std::move(key)] = std::move(value);
260 }
261 return result;
262}
Base class for maps with AUI extensions.
Definition: AMap.h:28
ValueType & getOrInsert(const KeyType &keyType, Factory &&factory) noexcept(noexcept(factory()))
Definition: AMap.h:185
Definition: AClass.h:18
Abstract AUI exception.
Definition: AException.h:29
A std::map with AUI extensions.
Definition: AMap.h:218
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition: AOptional.h:32
A std::unordered_map with AUI extensions.
Definition: AMap.h:230
A std::vector with AUI extensions.
Definition: AVector.h:38
StoredType & first() noexcept
Definition: AVector.h:228
Definition: Factory.h:18
auto to_unordered_map(Iterator begin, Iterator end, UnaryOperation &&transformer)
Transforms sequence to unordered_map.
Definition: AMap.h:251
auto to_map(Iterator begin, Iterator end, UnaryOperation &&transformer)
Transforms sequence to map.
Definition: AMap.h:237
Definition: AMap.h:58