MySQL 9.6.0
Source Code Documentation
nested_container.h
Go to the documentation of this file.
1// Copyright (c) 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24#ifndef MYSQL_SETS_NESTED_CONTAINER_H
25#define MYSQL_SETS_NESTED_CONTAINER_H
26
27/// @file
28/// Experimental API header
29
30#include <cassert> // assert
31#include <utility> // forward
32#include "mysql/allocators/memory_resource.h" // Memory_resource
33#include "mysql/meta/not_decayed.h" // Not_decayed
34#include "mysql/sets/binary_operation.h" // Binary_operation
35#include "mysql/sets/nested_set_category.h" // Nested_set_category_tag
36#include "mysql/sets/nested_set_interface.h" // Nested_set_interface
37#include "mysql/sets/nested_set_meta.h" // Is_nested_set_over_traits
38#include "mysql/sets/set_container_helpers.h" // handle_inplace_op_trivial_cases
39#include "mysql/utils/forward_like.h" // forward_like
40#include "mysql/utils/return_status.h" // void_to_ok
41
42/// @addtogroup GroupLibsMysqlSets
43/// @{
44
45namespace mysql::sets {
46
47/// Represents the subset of a Cartesian product "L x R" of two sets, using a
48/// map data structure that maps elements of type L to containers holding values
49/// of type R.
50///
51/// This never throws exceptions. All member functions that can fail, return a
52/// status and have the [[nodiscard]] attribute.
53///
54/// @tparam Storage_tp Underlying storage
55template <Is_nested_storage Storage_tp>
57 : public Basic_nested_container_wrapper<Nested_container<Storage_tp>,
58 Storage_tp> {
59 public:
60 using Storage_t = Storage_tp;
62 using Base_t =
64
66
67 using typename Base_t::Const_iterator_t;
68 using typename Base_t::Iterator_t;
69 using typename Base_t::Iterator_value_t;
70 using typename Base_t::Key_t;
71 using typename Base_t::Mapped_t;
72 using typename Base_t::Set_traits_t;
73
77
78 /// Construct a new, empty Nested_container.
79 ///
80 /// @param args any arguments are passed to the base class.
81 template <class... Args_t>
82 requires mysql::meta::Not_decayed<This_t, Args_t...>
83 explicit Nested_container(Args_t &&...args) noexcept
84 : Base_t(std::forward<Args_t>(args)...) {}
85
86 /// Return non-const reference to the underlying storage.
87 [[nodiscard]] auto &storage() noexcept { return this->wrapped(); }
88
89 /// Return const reference to the underlying storage.
90 [[nodiscard]] const auto &storage() const noexcept { return this->wrapped(); }
91
92 /// Return const iterator to the pair having the given key in the first
93 /// component, or end() if the key is not in the set.
94 ///
95 /// @param key Key to look for.
96 [[nodiscard]] Const_iterator_t find(const Key_t &key) const noexcept {
97 return storage().find(key);
98 }
99
100 /// Return iterator to the pair having the given key in the first component,
101 /// or end() if the key is not in the set.
102 ///
103 /// @param key Key to look for.
104 [[nodiscard]] Iterator_t find(const Key_t &key) noexcept {
105 return storage().find(key);
106 }
107
108 /// Return const iterator to the pair having the given key in the first
109 /// component, or end() if the key is not in the set.
110 ///
111 /// @param key Key to look for.
112 ///
113 /// @param[in,out] cursor Iterator hint. If this is greater than the lower
114 /// bound for key, the behavior is undefined. It will be updated to the upper
115 /// bound for the key. Thus, it is suitable to use in successive calls to this
116 /// function with increasing keys. This is not nodiscard because someone may
117 /// want to only advance the cursor.
119 const Key_t &key) const noexcept {
120 return storage().find(cursor, key);
121 }
122
123 /// Return iterator to the pair having the given key in the first component,
124 /// or end() if the key is not in the set.
125 ///
126 /// @param key Key to look for.
127 ///
128 /// @param[in,out] cursor Iterator hint. If this is greater than the lower
129 /// bound for key, the behavior is undefined. It will be updated to the upper
130 /// bound for the key. Thus, it is suitable to use in successive calls to this
131 /// function with increasing keys. This is not nodiscard because someone may
132 /// want to only advance the cursor.
133 Iterator_t find(Iterator_t &cursor, const Key_t &key) noexcept {
134 return storage().find(cursor, key);
135 }
136
137 /// Insert the given element (inplace union).
138 ///
139 /// This will create the value pair with the given key and an empty mapped
140 /// container if it does not exist. Then it will invoke the `insert` member
141 /// function of the mapped container.
142 ///
143 /// @param key Key of the element to insert.
144 ///
145 /// @param mapped_args Arguments passed to the `insert` member function of the
146 /// mapped container.
147 ///
148 /// @return Return_status::ok on success, or Return_status::error if an
149 /// out-of-memory condition occurred. This can either when inserting into the
150 /// storage for this object, or when inserting into the mapped container. On
151 /// error, the container is left unchanged: in particular, if an error
152 /// occurred after inserting the value pair into the map, the value pair is
153 /// removed again.
154 template <class... Mapped_args_t>
155 [[nodiscard]] Return_status_t insert(
156 const Key_t &key, Mapped_args_t &&...mapped_args) noexcept {
157 return insert_or_union(
158 [](Mapped_t &mapped_set, Mapped_args_t &&...mapped_args_fwd) {
159 return mapped_set.insert(
160 std::forward<Mapped_args_t>(mapped_args_fwd)...);
161 },
162 storage().emplace(key), std::forward<Mapped_args_t>(mapped_args)...);
163 }
164
165 /// Remove the given element from the set, if it is there.
166 ///
167 /// This will lookup the value pair in this set. If the key was found, remove
168 /// the element from the mapped container by invoking its `remove` member
169 /// function. If the resulting mapped container becomes empty, the value pair
170 /// is removed from this container.
171 ///
172 /// @param key Key of the element to insert.
173 ///
174 /// @param value Arguments passed to the `remove` member function of the
175 /// mapped container.
176 ///
177 /// @return Return_status::ok on success, or Return_status::error if an
178 /// out-of-memory condition occurred. This can happen if removing from the
179 /// mapped container required an allocation, for example, to split an
180 /// interval. On error, the container is left unchanged.
181 Return_status_t remove(const Key_t &key, const auto &...value) noexcept {
182 auto it = find(key);
183 if (it != this->end()) {
184 auto ret = it->second.remove(value...);
185 if (ret != return_ok) return ret;
186 if (!it->second) {
187 storage().erase(it);
188 }
189 }
190 return return_ok;
191 }
192
193 /// Insert the given set (inplace union).
194 ///
195 /// This will create the value pair with the given key and an empty mapped
196 /// container if it does not exist. Then it will invoke the `inplace_union`
197 /// member function of the mapped container.
198 ///
199 /// @param key Key of the element to insert.
200 ///
201 /// @param mapped_args Arguments passed to the `inplace_union` member function
202 /// of the mapped container.
203 ///
204 /// @return Return_status::ok on success, or Return_status::error if an
205 /// out-of-memory condition occurred. This can either when inserting into the
206 /// storage for this object, or when invoking `inplace_union` for the mapped
207 /// container. This may leave the container as a superset of the previous set
208 /// and a subset of the union.
209 template <class... Mapped_args_t>
210 [[nodiscard]] auto inplace_union(const Key_t &key,
211 Mapped_args_t &&...mapped_args) noexcept {
212 return insert_or_union(
213 [](Mapped_t &mapped_set, Mapped_args_t &&...mapped_args_fwd) {
214 return mapped_set.inplace_union(
215 std::forward<Mapped_args_t>(mapped_args_fwd)...);
216 },
217 storage().emplace(key), std::forward<Mapped_args_t>(mapped_args)...);
218 }
219
220 /// Insert the given set (inplace union), reading and updating the given
221 /// cursor.
222 ///
223 /// This will create the value pair with the given key and an empty mapped
224 /// container if it does not exist. Then it will invoke the `inplace_union`
225 /// member function of the mapped container.
226 ///
227 /// @param[in,out] cursor Hint for the insertion position. If this is greater
228 /// than the lower bound for key, the behavior is undefined. It will be
229 /// updated to the element after the inserted one, which makes it good to
230 /// reuse for future calls to this function, with keys following this one.
231 ///
232 /// @param key Key of the element to insert.
233 ///
234 /// @param mapped_args Arguments passed to the `inplace_union` member function
235 /// of the mapped container.
236 ///
237 /// @return Return_status::ok on success, or Return_status::error if an
238 /// out-of-memory condition occurred. This can either when inserting into the
239 /// storage for this object, or when invoking `inplace_union` for the mapped
240 /// container. This may leave the container as a superset of the previous set
241 /// and a subset of the union.
242 template <class... Mapped_args_t>
243 [[nodiscard]] auto inplace_union(Iterator_t &cursor, const Key_t &key,
244 Mapped_args_t &&...mapped_args) noexcept {
245 return insert_or_union(
246 [](Mapped_t &mapped_set, Mapped_args_t &&...mapped_args_fwd) {
247 return mapped_set.inplace_union(
248 std::forward<Mapped_args_t>(mapped_args_fwd)...);
249 },
250 storage().emplace(cursor, key),
251 std::forward<Mapped_args_t>(mapped_args)...);
252 }
253
254 /// Inplace-insert the given set (inplace union) into this container.
255 ///
256 /// This will iterate over the input set and repeatedly invoke
257 /// inplace_union(cursor, key, mapped).
258 ///
259 /// If other_set is an rvalue reference, and its allocator compares equal with
260 /// this Nested_container's allocator, and the set types satisfy
261 /// Can_donate_set_elements, this steals elements from other and does not
262 /// allocate elements in the Nested_set. The same applies on all levels of
263 /// nested containers, i.e., the mapped sets may steal if their allocators
264 /// compare equal and their types satisfy Can_donate_set_elements; and so on
265 /// on all nesting levels. If stealing is possible on all levels, this cannot
266 /// fail.
267 ///
268 /// @param other_set Arguments passed to the `inplace_union` member function
269 /// of the mapped container.
270 ///
271 /// @return Return_status::ok on success, or Return_status::error if an
272 /// out-of-memory condition occurred, either when inserting into the storage
273 /// for this object, or when invoking `inplace_union` for the mapped
274 /// container. This may leave the container as a superset of the previous set
275 /// and a subset of the union.
276 template <Is_nested_set_over_traits_unqualified<Set_traits_t> Other_set_t>
277 [[nodiscard]] auto inplace_union(Other_set_t &&other_set) noexcept {
278 if (detail::handle_inplace_op_trivial_cases<Binary_operation::op_union>(
279 *this, std::forward<Other_set_t>(other_set)))
280 return return_ok;
281 constexpr bool types_allow_donation =
283 This_t>;
284 bool can_donate = false;
285 if constexpr (types_allow_donation) {
286 can_donate = (this->get_allocator() == other_set.get_allocator());
287 }
288
289 auto this_cursor = this->begin();
290 auto other_it = other_set.begin();
291 while (other_it != other_set.end()) {
292 auto &&[other_key, other_mapped] = *other_it;
293 auto next_other_it = std::next(other_it);
294 auto this_it = this->find(this_cursor, other_key);
295 if (this_it == this->end()) {
296 // Key not found in `this`. Then move or copy "mapped" from source.
297 if (can_donate) {
298 // Use move semantics.
299 // Guard by `if constexpr (types_allow_donation)` since the call to
300 // `steal_and_insert` may not compile otherwise.
301 if constexpr (types_allow_donation) {
302 this_cursor = storage().steal_and_insert(
303 this_cursor, other_set.storage(), other_it);
304 }
305 } else {
306 // Use copy semantics.
307 auto ret = inplace_union(this_cursor, other_key, other_mapped);
308 if (ret != return_ok) return ret;
309 }
310 } else {
311 // Key found in `this`. Use Mapped_t::inplace_union.
312 auto ret = this_it->second.inplace_union(
313 mysql::utils::forward_like<Other_set_t>(*other_it).second);
314 if (ret != return_ok) return ret;
315 }
316 other_it = next_other_it;
317 }
318 return return_ok;
319 }
320
321 /// Inplace-remove the given key and associated mapped set.
322 ///
323 /// @param key Key to remove.
324 ///
325 /// This operation cannot fail.
326 void inplace_subtract(const Key_t &key) noexcept {
327 auto it = find(key);
328 if (it != this->end()) {
329 storage().erase(it);
330 }
331 }
332
333 /// Inplace-remove the given mapped set from the mapped set associated with
334 /// the given key.
335 ///
336 /// @param key Key to find.
337 ///
338 /// @param mapped_args Arguments passed to `inplace_subtract` of the mapped
339 /// set.
340 ///
341 /// @return Return_status::ok on success, or Return_status::error on
342 /// out-of-memory error. This can occur if the `inplace_subtract` member
343 /// function of the mapped container type can fail. It may leave this set as a
344 /// subset of the old set and a superset of the difference set.
345 template <class... Mapped_args_t>
346 [[nodiscard]] auto inplace_subtract(const Key_t &key,
347 Mapped_args_t &&...mapped_args) noexcept {
348 auto cursor = this->begin();
349 return inplace_subtract(cursor, key,
350 std::forward<Mapped_args_t>(mapped_args)...);
351 }
352
353 /// Inplace-remove the given mapped set from the mapped set associated with
354 /// the given key, reading and updating the given cursor.
355 ///
356 /// @param[in,out] cursor Hint for the position of the key. If this is greater
357 /// than the lower bound for key, the behavior is undefined. It will be
358 /// updated to point to the element following key, which makes it good to
359 /// reuse for future calls to this function, with keys following this one.
360 ///
361 /// @param key Key to find.
362 ///
363 /// @param mapped_args Arguments passed to `inplace_subtract` of the mapped
364 /// set.
365 ///
366 /// @return Return_status::ok on success, or Return_status::error on
367 /// out-of-memory error. This can occur if the `inplace_subtract` member
368 /// function of the mapped container type can fail. It may leave this set as a
369 /// subset of the old set and a superset of the difference set.
370 template <class... Mapped_args_t>
371 [[nodiscard]] auto inplace_subtract(Iterator_t &cursor, const Key_t &key,
372 Mapped_args_t &&...mapped_args) noexcept {
373 // The call to inplace_subtract may return void or Return_t, depending on
374 // Mapped_args_t. Deduce which is the case adn propagate the same return
375 // type from this function.
376 using Return_t = decltype(std::declval<Mapped_t>().inplace_subtract(
377 std::declval<Mapped_args_t &&>()...));
378 constexpr bool can_fail = !std::same_as<Return_t, void>;
379
380 auto ret = return_ok;
381 auto it = find(cursor, key);
382 if (it != this->end()) {
383 ret = mysql::utils::void_to_ok([&it, &mapped_args...] {
384 return it->second.inplace_subtract(
385 std::forward<Mapped_args_t>(mapped_args)...);
386 });
388 cursor = it;
389 }
390 if constexpr (can_fail) {
391 return ret;
392 } else {
393 assert(ret == return_ok);
394 }
395 }
396
397 /// Inplace-remove the given set from this container.
398 ///
399 /// This iterates over value pairs of this container and value pairs of the
400 /// other set, where the key part of the two pairs are equal. In each step, it
401 /// invokes `inplace_subtract` on the mapped container, passing the mapped
402 /// other set as parameter. The number of iterations over value pairs is
403 /// bounded by min(this->size, other_set.size()).
404 ///
405 /// If other_set is an rvalue reference, any time this function makes a
406 /// recursive call to inplace_subtract on the mapped sets, it will pass an
407 /// rvalue reference to a mapped set in other_set. This possibly enables
408 /// stealing, if allowed by the types and allocators of those sets. If
409 /// stealing is possible on all nesting levels, this cannot fail.
410 ///
411 /// @param other_set Set to subtract
412 ///
413 /// @return Return_status::ok on success, or Return_status::error if an
414 /// out-of-memory condition occurred. This can happen if the
415 /// `inplace_subtract` member of the mapped set fails. This may leave the
416 /// container as a subset of the previous set and a superset of the
417 /// difference.
418 template <Is_nested_set_over_traits_unqualified<Set_traits_t> Other_set_t>
419 [[nodiscard]] auto inplace_subtract(Other_set_t &&other_set) noexcept {
422 *this, std::forward<Other_set_t>(other_set)))
423 return return_ok;
424 // Given iterators to this and other, pointing to the same key, subtract
425 // the other iterator's mapped set from this operator's mapped set.
426 auto do_subtract = [this](auto &this_it, auto &other_it) {
427 auto ret = this_it->second.inplace_subtract(
428 mysql::utils::forward_like<Other_set_t>(*other_it).second);
429 this->advance_and_erase_if_empty(this_it);
430 return ret;
431 };
432
433 auto other_cursor = other_set.begin();
434 auto cursor = this->begin();
435 while (cursor != this->end()) {
436 auto other_it = other_set.find(other_cursor, cursor->first);
437 if (other_it != other_set.end()) {
438 // Found `cursor`'s key in other. Subtract the mapped set.
439 auto ret = do_subtract(cursor, other_it);
440 if (ret != return_ok) return ret;
441 } else {
442 // Did not find `cursor`'s key in `other`.
443
444 // `cursor`'s key is greater than all keys in `other`. I.e., we have
445 // exhausted `other` already and are done.
446 if (other_cursor == other_set.end()) return return_ok;
447
448 // `other_cursor` is the next-greater key in `other`. Try to find the
449 // same key in this.
450 auto it = this->find(cursor, other_cursor->first);
451 if (it != this->end()) {
452 auto ret = do_subtract(it, other_cursor);
453 if (ret != return_ok) return ret;
454 cursor = it;
455 }
456 }
457 }
458 return return_ok;
459 }
460
461 /// Inplace-remove all value pairs, except the one for the given key.
462 ///
463 /// @param key Key to keep.
464 ///
465 /// This operation cannot fail.
466 void inplace_intersect(const Key_t &key) noexcept {
467 auto it = storage().find(key);
468 if (it == storage().end()) {
469 storage().clear();
470 } else {
471 storage().erase(std::ranges::next(it), storage().end());
472 storage().erase(storage().begin(), it);
473 }
474 }
475
476 /// Inplace-remove all value pairs, except the one for the given key, and
477 /// inplace-intersect the mapped container for the given key with the given
478 /// mapped set.
479 ///
480 /// @param key Key to keep.
481 ///
482 /// @param mapped_args Arguments to pass to inplace_intersect on the mapped
483 /// set.
484 ///
485 /// @return Return_status::ok if the operation succeeds, or
486 /// Return_status::error if an out-of-memory condition occurs. This can happen
487 /// if the inplace_intersect operation of the mapped container fails. This
488 /// may leave the container as a subset of the previous set and a superset of
489 /// the intersection.
490 template <class... Mapped_args_t>
491 [[nodiscard]] auto inplace_intersect(
492 const Key_t &key, Mapped_args_t &&...mapped_args) noexcept {
493 // The call to inplace_intersect may return void or Return_t, depending on
494 // Mapped_args_t. Deduce which is the case adn propagate the same return
495 // type from this function.
496 using Return_t = decltype(std::declval<Mapped_t>().inplace_intersect(
497 std::declval<Mapped_args_t>()...));
498 constexpr bool can_fail = !std::same_as<Return_t, void>;
499
501 auto ret = return_ok;
502 if (!storage().empty()) {
503 auto &&mapped = storage().begin()->second;
504 ret = mysql::utils::void_to_ok([&mapped, &mapped_args...] {
505 return mapped.inplace_intersect(
506 std::forward<Mapped_args_t>(mapped_args)...);
507 });
508 if (mapped.empty()) storage().clear();
509 }
510 if constexpr (can_fail) {
511 return ret;
512 } else {
513 assert(ret == return_ok);
514 }
515 }
516
517 /// Inplace-intersect this set with the given set.
518 ///
519 /// If other_set is an rvalue reference, any time this function makes a
520 /// recursive call to inplace_intersect on the mapped sets, it will pass an
521 /// rvalue reference to a mapped set in other_set. This possibly enables
522 /// stealing, if allowed by the types and allocators of those sets. If
523 /// stealing is possible on all nesting levels, this cannot fail.
524 ///
525 /// @param other_set Set to intersect with.
526 ///
527 /// @return Return_status::ok on success, or Return_status::error if an
528 /// out-of-memory condition occurred. This can happen if the
529 /// `inplace_intersect` member of the mapped set fails. This may leave the
530 /// container as a subset of the previous set and a superset of the
531 /// intersection.
532 template <Is_nested_set_over_traits_unqualified<Set_traits_t> Other_set_t>
533 [[nodiscard]] auto inplace_intersect(Other_set_t &&other_set) noexcept {
536 *this, std::forward<Other_set_t>(other_set)))
537 return return_ok;
538 // Iterate over all key-mapped pairs of this set.
539 auto it = this->begin();
540 auto other_cursor = other_set.begin();
541 while (it != this->end()) {
542 auto other_it = other_set.find(other_cursor, it->first);
543 if (other_it == other_set.end()) {
544 // If other_set does not have any element with this key, just erase
545 // the key from this set.
546 it = storage().erase(it);
547 } else {
548 // If other_set has an element with this key, intersect the mapped
549 // sets.
550 auto ret = it->second.inplace_intersect(
551 mysql::utils::forward_like<Other_set_t>(*other_it).second);
553 if (ret != return_ok) return ret;
554 }
555 }
556 return return_ok;
557 }
558
559 private:
560 /// Common implementation for `insert` and several of the `inplace_union`
561 /// operations: it performs the insertion operation, given an iterator to the
562 /// key-value pair and a mapped set.
563 ///
564 /// @tparam Mapped_args_t Type of parameters passed to the lambda.
565 ///
566 /// @param func Callable that will perform the insert or inplace_union
567 /// operation in the mapped set. It will be passed the mapped set, followed by
568 /// the arguments in `mapped_args`.
569 ///
570 /// @param opt_it std::optional that may hold an iterator to the value pair on
571 /// which the `insert` or `inplace_union` operation should operate. If this
572 /// does not hold a value, this function returns Return_status::error
573 /// immediately; otherwise it attempts to insert into the mapped container it
574 /// points to.
575 ///
576 /// @param mapped_args Parameters to pass to `func`.
577 ///
578 /// @return Return_status::ok on success; Return_status::error if either
579 /// `opt_it` does not hold a value, or `func` fails.
580 template <class... Mapped_args_t>
581 [[nodiscard]] auto insert_or_union(const auto &func, const auto &opt_it,
582 Mapped_args_t &&...mapped_args) noexcept {
583 if (!opt_it.has_value()) return Return_status_t::error;
584 auto &it = opt_it.value();
585 auto &mapped_set = it->second;
586 auto ret = mysql::utils::void_to_ok(
587 func, mapped_set, std::forward<Mapped_args_t>(mapped_args)...);
588 if (mapped_set.empty()) {
589 // Can happen if emplace had to insert a new mapped_set, and then
590 // mapped_set.insert caused an out-of-memory condition.
591 storage().erase(it);
592 }
593 return ret;
594 }
595
596 /// Helper that will erase the value pair that the iterator points to *if* it
597 /// is empty, and, regardless if it erased or not, make the iterator point to
598 /// the next element.
599 ///
600 /// This will point to the next element even if an erase operation was
601 /// performed which invalidated iterators.
602 ///
603 /// @param iterator Iterator to operate on.
604 void advance_and_erase_if_empty(Iterator_t &iterator) noexcept {
605 if (iterator->second.empty()) {
606 iterator = storage().erase(iterator);
607 } else {
608 ++iterator;
609 }
610 }
611}; // class Nested_container
612
613} // namespace mysql::sets
614
615// addtogroup GroupLibsMysqlSets
616/// @}
617
618#endif // ifndef MYSQL_SETS_NESTED_CONTAINER_H
Experimental API header.
Polymorphism-free memory resource class with custom allocator and deallocator functions.
Definition: memory_resource.h:88
CRTP base class (mixin) to define a wrapper around a container.
Definition: basic_container_wrapper.h:59
auto get_allocator() const noexcept
Return the allocator used by the wrapped object.
Definition: basic_container_wrapper.h:159
CRTP base class/mixin, used to implement Nested Sets that are container wrappers.
Definition: nested_set_interface.h:156
Definition: basic_set_container_wrapper.h:47
Represents the subset of a Cartesian product "L x R" of two sets, using a map data structure that map...
Definition: nested_container.h:58
void inplace_subtract(const Key_t &key) noexcept
Inplace-remove the given key and associated mapped set.
Definition: nested_container.h:326
auto inplace_intersect(Other_set_t &&other_set) noexcept
Inplace-intersect this set with the given set.
Definition: nested_container.h:533
Nested_container< Storage_t > This_t
Definition: nested_container.h:61
auto inplace_union(Iterator_t &cursor, const Key_t &key, Mapped_args_t &&...mapped_args) noexcept
Insert the given set (inplace union), reading and updating the given cursor.
Definition: nested_container.h:243
Iterator_t find(Iterator_t &cursor, const Key_t &key) noexcept
Return iterator to the pair having the given key in the first component, or end() if the key is not i...
Definition: nested_container.h:133
Const_iterator_t find(Const_iterator_t &cursor, const Key_t &key) const noexcept
Return const iterator to the pair having the given key in the first component, or end() if the key is...
Definition: nested_container.h:118
Storage_tp Storage_t
Definition: nested_container.h:60
Const_iterator_t find(const Key_t &key) const noexcept
Return const iterator to the pair having the given key in the first component, or end() if the key is...
Definition: nested_container.h:96
Iterator_t find(const Key_t &key) noexcept
Return iterator to the pair having the given key in the first component, or end() if the key is not i...
Definition: nested_container.h:104
void advance_and_erase_if_empty(Iterator_t &iterator) noexcept
Helper that will erase the value pair that the iterator points to if it is empty, and,...
Definition: nested_container.h:604
auto & storage() noexcept
Return non-const reference to the underlying storage.
Definition: nested_container.h:87
Basic_nested_container_wrapper< Nested_container< Storage_tp >, Storage_tp > Base_t
Definition: nested_container.h:63
const auto & storage() const noexcept
Return const reference to the underlying storage.
Definition: nested_container.h:90
auto inplace_union(const Key_t &key, Mapped_args_t &&...mapped_args) noexcept
Insert the given set (inplace union).
Definition: nested_container.h:210
auto inplace_union(Other_set_t &&other_set) noexcept
Inplace-insert the given set (inplace union) into this container.
Definition: nested_container.h:277
Return_status_t remove(const Key_t &key, const auto &...value) noexcept
Remove the given element from the set, if it is there.
Definition: nested_container.h:181
Nested_container(Args_t &&...args) noexcept
Construct a new, empty Nested_container.
Definition: nested_container.h:83
auto insert_or_union(const auto &func, const auto &opt_it, Mapped_args_t &&...mapped_args) noexcept
Common implementation for insert and several of the inplace_union operations: it performs the inserti...
Definition: nested_container.h:581
auto inplace_subtract(Iterator_t &cursor, const Key_t &key, Mapped_args_t &&...mapped_args) noexcept
Inplace-remove the given mapped set from the mapped set associated with the given key,...
Definition: nested_container.h:371
Return_status_t insert(const Key_t &key, Mapped_args_t &&...mapped_args) noexcept
Insert the given element (inplace union).
Definition: nested_container.h:155
void inplace_intersect(const Key_t &key) noexcept
Inplace-remove all value pairs, except the one for the given key.
Definition: nested_container.h:466
auto inplace_subtract(const Key_t &key, Mapped_args_t &&...mapped_args) noexcept
Inplace-remove the given mapped set from the mapped set associated with the given key.
Definition: nested_container.h:346
auto inplace_intersect(const Key_t &key, Mapped_args_t &&...mapped_args) noexcept
Inplace-remove all value pairs, except the one for the given key, and inplace-intersect the mapped co...
Definition: nested_container.h:491
auto inplace_subtract(Other_set_t &&other_set) noexcept
Inplace-remove the given set from this container.
Definition: nested_container.h:419
static constexpr Return_status_t return_ok
Definition: nested_container.h:76
Set_traits_tp Set_traits_t
Definition: nested_set_interface.h:69
typename Key_traits_t::Element_t Key_t
Definition: nested_set_interface.h:71
Iterator_tp Iterator_t
Definition: nested_set_interface.h:64
typename Iterator_value_t::second_type Mapped_t
Definition: nested_set_interface.h:74
mysql::ranges::Iterator_value_type< Iterator_t > Iterator_value_t
Definition: nested_set_interface.h:67
Const_iterator_tp Const_iterator_t
Definition: nested_set_interface.h:65
false if Args is exactly one type, say A, and std::decay_t<A> equals Type.
Definition: not_decayed.h:84
True if move-semantics has been declared as enabled for inplace_union/inplace_intersect/inplace_subtr...
Definition: meta.h:114
Experimental API header.
Class that wraps resources in a polymorphic manner.
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
bool handle_inplace_op_trivial_cases(Target_t &target, Source_t &&source)
Handle the trivial cases of inplace union/intersection/subtraction where either both operands refer t...
Definition: set_container_helpers.h:45
Definition: gtid_set.h:183
decltype(call_function()) Return_t
Definition: call_and_catch.h:80
Return_status
Simple, strongly-typed enumeration to indicate internal status: ok, error.
Definition: return_status.h:40
@ ok
operation succeeded
@ error
operation failed
Return_t void_to_ok(const Func_t &func, Args_t &&...args)
Helper that calls the given function and returns its result, or returns Return_status::ok if the func...
Definition: return_status.h:113
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76
Experimental API header.
Experimental API header.
Experimental API header.
Experimental API header.
required string key
Definition: replication_asynchronous_connection_failover.proto:60
Experimental API header.
Experimental API header.
Tag to identify a class as a Nested set.
Definition: nested_set_category.h:41