MySQL 9.6.0
Source Code Documentation
map_or_set_assign.h
Go to the documentation of this file.
1// Copyright (c) 2024, 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_CONTAINERS_MAP_OR_SET_ASSIGN_H
25#define MYSQL_CONTAINERS_MAP_OR_SET_ASSIGN_H
26
27/// @file
28/// Experimental API header
29
30#include "mysql/ranges/meta.h" // Iterator_value_type
31#include "mysql/utils/call_and_catch.h" // call_and_catch
32
33/// @addtogroup GroupLibsMysqlContainers
34/// @{
35
36namespace mysql::containers {
37
38/// For a `node_handle` retrieved from the `extract` member of one of the
39/// `std::[unordered_][multi]{set|map}` containers, and an iterator over a
40/// container with the same value_type, copy the value pointed to by the
41/// iterator to the node_handle.
42///
43/// The purpose is to provide a uniform API, since node_handle objects of sets
44/// and maps are different.
45///
46/// @param node_handle Node handle to copy to.
47///
48/// @param iterator Iterator to the value to copy from.
49void node_handle_assign(auto &node_handle, auto &iterator) noexcept {
50 // True for set-like types (set, multiset), false for map-like types (map,
51 // multimap).
52 constexpr bool has_value_member = requires { node_handle.value(); };
53
54 if constexpr (has_value_member) {
55 node_handle.value() = *iterator;
56 } else {
57 node_handle.key() = iterator->first;
58 node_handle.mapped() = iterator->second;
59 }
60}
61
62/// Return a new object of the same type as the parameter, without any elements,
63/// with the same allocator, and if the object type has key comparison, the same
64/// comparison object.
65template <class Map_or_set_t>
66auto make_empty_map_or_set_and_copy_metadata(const Map_or_set_t &map_or_set) {
67 constexpr bool has_key_comparison_member =
68 requires { map_or_set.key_comp(); };
69 if constexpr (has_key_comparison_member) {
70 // For (ordered) [multi]{map|set}, copy the key comparison function
71 // object and the allocator.
72 return Map_or_set_t(map_or_set.key_comp(), map_or_set.get_allocator());
73 } else {
74 // For unordered_[multi]{map|set}, there is no key comparison function
75 // object. Copy just the allocator.
76 return Map_or_set_t(map_or_set.get_allocator());
77 }
78}
79
80} // namespace mysql::containers
81
83
84/// Replace the contents of `container` with that of the range given by the two
85/// iterators, minimizing memory allocations.
86///
87/// This reuses existing nodes of the target container as far as possible, and
88/// allocates new ones only if the source has more nodes than the target
89/// container.
90///
91/// It does not copy the allocator.
92///
93/// Informally, this is to std::map what std::vector:assign is to std::vector.
94///
95/// @param map_or_set Container to overwrite.
96///
97/// @param first Iterator to first element of new contents.
98///
99/// @param last Iterator to last element of new contents.
100///
101/// @throws std::bad_alloc Out of memory. This can only occur if the
102/// source range has more elements than the container.
103template <class Map_or_set_t, class Source_iterator_t>
104 requires std::convertible_to<
107void map_or_set_assign(Map_or_set_t &map_or_set, const Source_iterator_t &first,
108 const std::sentinel_for<Source_iterator_t> auto &last) {
109 Map_or_set_t tmp = make_empty_map_or_set_and_copy_metadata(map_or_set);
110 auto it = first;
111
112 // Reuse nodes by moving them one by one from map_or_set to tmp.
113 for (; it != last && !map_or_set.empty(); ++it) {
114 auto node_handle = map_or_set.extract(map_or_set.begin());
116 tmp.insert(tmp.cend(), std::move(node_handle));
117 }
118
119 // Replace map_or_set by the result.
120 map_or_set = std::move(tmp);
121
122 // Allocate any remaining nodes.
123 for (; it != last; ++it) {
124 map_or_set.insert(map_or_set.cend(), *it);
125 }
126}
127
128} // namespace mysql::containers::throwing
129
130namespace mysql::containers {
131
132/// Replace the contents of `container` with that of the range given by the two
133/// iterators, minimizing memory allocations.
134///
135/// This reuses existing nodes of the target container as far as possible, and
136/// allocates new ones only if the source has more nodes than the target
137/// container.
138///
139/// It does not copy the allocator.
140///
141/// Informally, this is to std::map what std::vector:assign is to std::vector.
142///
143/// @param map_or_set Container to overwrite.
144///
145/// @param first Iterator to first element of new contents.
146///
147/// @param last Iterator to last element of new contents.
148///
149/// @retval Return_status::ok Success
150///
151/// @retval Return_status::error Out of memory. This can only occur if the
152/// source range has more elements than the container.
153template <class Source_iterator_t>
154[[nodiscard]] auto map_or_set_assign(
155 auto &map_or_set, const Source_iterator_t &first,
156 const std::sentinel_for<Source_iterator_t> auto &last) noexcept {
157 return mysql::utils::call_and_catch(
158 [&] { throwing::map_or_set_assign(map_or_set, first, last); });
159}
160
161} // namespace mysql::containers
162
163// addtogroup GroupLibsMysqlContainers
164/// @}
165
166#endif // ifndef MYSQL_CONTAINERS_MAP_OR_SET_ASSIGN_H
Experimental API header.
Experimental API header.
Definition: map_or_set_assign.h:82
void map_or_set_assign(Map_or_set_t &map_or_set, const Source_iterator_t &first, const std::sentinel_for< Source_iterator_t > auto &last)
Replace the contents of container with that of the range given by the two iterators,...
Definition: map_or_set_assign.h:107
Definition: basic_container_wrapper.h:42
void node_handle_assign(auto &node_handle, auto &iterator) noexcept
For a node_handle retrieved from the extract member of one of the std::[unordered_][multi]{set|map} c...
Definition: map_or_set_assign.h:49
auto make_empty_map_or_set_and_copy_metadata(const Map_or_set_t &map_or_set)
Return a new object of the same type as the parameter, without any elements, with the same allocator,...
Definition: map_or_set_assign.h:66
auto map_or_set_assign(auto &map_or_set, const Source_iterator_t &first, const std::sentinel_for< Source_iterator_t > auto &last) noexcept
Replace the contents of container with that of the range given by the two iterators,...
Definition: map_or_set_assign.h:154
std::remove_cvref_t< decltype(*std::declval< Iterator_t >())> Iterator_value_type
Gives the value type for any iterator type, deduced from operator *.
Definition: meta.h:63
Iterator_value_type< Range_iterator_type< Range_t > > Range_value_type
Gives the value type for any collection, deduced from *begin().
Definition: meta.h:67