MySQL 9.6.0
Source Code Documentation
basic_container_wrapper.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_CONTAINERS_BASIC_CONTAINER_WRAPPER_H
25#define MYSQL_CONTAINERS_BASIC_CONTAINER_WRAPPER_H
26
27/// @file
28/// Experimental API header
29
30#include <concepts> // derived_from
31#include <type_traits> // is_nothrow_move_assignable
32#include <utility> // move
33#include "mysql/meta/not_decayed.h" // Not_decayed
34#include "mysql/ranges/collection_interface.h" // Collection_interface
35#include "mysql/utils/call_and_catch.h" // call_and_catch
36#include "mysql/utils/is_same_object.h" // is_same_object
37#include "mysql/utils/return_status.h" // Return_status
38
39/// @addtogroup GroupLibsMysqlContainers
40/// @{
41
43
44/// CRTP base class (mixin) to define a wrapper around a container.
45///
46/// This defines the `clear` and `assign` member modifiers based on the wrapped
47/// container, as well as `get_memory_resource` and all the
48/// `Collection_interface` members.
49///
50/// @tparam Self_tp The wrapper class that inherits from this class.
51///
52/// @tparam Wrapped_tp The wrapped class.
53///
54/// @tparam shall_catch If `yes`, `assign` will use
55/// `mysql::utils::call_and_catch` to convert exceptions to return values.
56template <class Self_tp, class Wrapped_tp,
57 mysql::utils::Shall_catch shall_catch = mysql::utils::Shall_catch::no>
59 : public mysql::ranges::Collection_interface<Self_tp> {
60 using Self_t = Self_tp;
62
63 public:
64 using Wrapped_t = Wrapped_tp;
65
66 /// Constructor that delegates all parameters to the constructor of the
67 /// wrapped class.
68 template <class... Args_t>
69 requires mysql::meta::Not_decayed<This_t, Args_t...>
70 explicit Basic_container_wrapper(Args_t &&...args) noexcept(
71 noexcept(Wrapped_t(std::forward<Args_t>(args)...)))
72 : m_wrapped(std::forward<Args_t>(args)...) {}
73
74 /// Assign a range defined by the two iterators to the wrapped object.
75 ///
76 /// This is enabled provided that the wrapped class defines an `assign` member
77 /// taking two iterators.
78 template <std::input_iterator First_iterator_t,
79 std::sentinel_for<First_iterator_t> Sentinel_t>
80 requires requires(Wrapped_t w, First_iterator_t f, Sentinel_t s) {
81 w.assign(f, s);
82 }
83 [[nodiscard]] auto assign(const First_iterator_t &first,
84 const Sentinel_t &last)
85 // this comment helps clang-format
86 noexcept(shall_catch == mysql::utils::Shall_catch::yes ||
87 noexcept(std::declval<Wrapped_t>().assign(first, last))) {
89 shall_catch>([&]() DEDUCED_NOEXCEPT_FUNCTION(
90 m_wrapped.assign(first, last)));
91 }
92
93 /// Copy-assign the other object to the wrapped object.
94 ///
95 /// This is enabled provided that the subclass defines an `assign` member
96 /// taking two iterators.
97 template <class Other_t>
98 [[nodiscard]] auto assign(const Other_t &other) noexcept(
99 shall_catch == mysql::utils::Shall_catch::yes ||
100 noexcept(std::declval<Self_t>().assign(other.begin(), other.end()))) {
101 if (mysql::utils::is_same_object(other, *this)) {
102 // Must return the same type as the call to `assign` below.
103 if constexpr (std::same_as<decltype(self().assign(other.begin(),
104 other.end())),
105 void>) {
106 return;
107 } else {
109 }
110 }
111 return self().assign(other.begin(), other.end());
112 }
113
114 /// Move-assign the other object to the wrapped object.
115 ///
116 /// This is enabled provided that the wrapped class is
117 /// nothrow-move-assignable.
118 void assign(Self_t &&other) noexcept
119 requires std::is_nothrow_move_assignable_v<Wrapped_t>
120 {
121 if (&other == &self()) return;
122 m_wrapped = std::move(other).m_wrapped;
123 }
124
125 /// Clear the wrapped object.
126 ///
127 /// This invokes the `clear` member of the wrapped object.
128 void clear() noexcept { m_wrapped.clear(); }
129
130 /// Return the memory resource used by the wrapped object.
131 ///
132 /// This invokes the `get_memory_resource` member of the wrapped object, if it
133 /// exists; otherwise invokes the `get_memory_resource` member of the object
134 /// returned by the `get_allocator` member of the wrapped object, if both
135 /// those exists. If none of these two is possible, this member cannot be
136 /// used.
137 [[nodiscard]] auto get_memory_resource() const noexcept {
138 constexpr bool has_memory_resource =
139 requires { m_wrapped.get_memory_resource(); };
140 constexpr bool has_allocator =
141 requires { m_wrapped.get_allocator().get_memory_resource(); };
142 if constexpr (has_memory_resource) {
143 return m_wrapped.get_memory_resource();
144 } else if constexpr (has_allocator) {
145 return m_wrapped.get_allocator().get_memory_resource();
146 } else {
147 static_assert(
148 has_memory_resource || has_allocator,
149 "Wrapped class has neither a get_allocator() member function that "
150 "returns an object having a get_memory_resource() function, nor a "
151 "get_memory_resource() member function of its own.");
152 }
153 }
154
155 /// Return the allocator used by the wrapped object.
156 ///
157 /// This invokes the `get_allocator` member of the wrapped object, if it
158 /// exists. Otherwise, this member cannot be used.
159 [[nodiscard]] auto get_allocator() const noexcept {
160 return m_wrapped.get_allocator();
161 }
162
163 /// @return iterator to the first element
164 [[nodiscard]] auto begin() noexcept { return m_wrapped.begin(); }
165
166 /// @return iterator to one-after-last element
167 [[nodiscard]] auto end() noexcept { return m_wrapped.end(); }
168
169 /// @return const iterator to the first element
170 [[nodiscard]] auto begin() const noexcept { return m_wrapped.begin(); }
171
172 /// @return const iterator to one-after-last element
173 [[nodiscard]] auto end() const noexcept { return m_wrapped.end(); }
174
175 /// @return const iterator to the first element
176 [[nodiscard]] auto empty() const noexcept { return m_wrapped.empty(); }
177
178 /// @return const iterator to one-after-last element
179 [[nodiscard]] auto size() const noexcept { return m_wrapped.size(); }
180
181 protected:
182 /// @return non-const lvalue reference to the wrapped object.
183 [[nodiscard]] auto &wrapped() &noexcept { return m_wrapped; }
184
185 /// @return const lvalue reference to the wrapped object.
186 [[nodiscard]] const auto &wrapped() const &noexcept { return m_wrapped; }
187
188 /// @return rvalue reference to the wrapped object.
189 [[nodiscard]] auto &&wrapped() &&noexcept { return std::move(m_wrapped); }
190
191 private:
192 /// Return a non-const reference to the subclass.
193 [[nodiscard]] auto &self() noexcept { return static_cast<Self_t &>(*this); }
194
195 /// Return a const reference to the subclass.
196 [[nodiscard]] const auto &self() const noexcept {
197 return static_cast<const Self_t &>(*this);
198 }
199
200 /// Wrapped object.
202}; // class Basic_container_wrapper
203
204} // namespace mysql::containers
205
206// addtogroup GroupLibsMysqlContainers
207/// @}
208
209#endif // ifndef MYSQL_CONTAINERS_BASIC_CONTAINER_WRAPPER_H
Experimental API header.
#define DEDUCED_NOEXCEPT_FUNCTION(X)
Helper macro to define a function that returns the result of a single expression, and has a condition...
Definition: call_and_catch.h:151
CRTP base class (mixin) to define a wrapper around a container.
Definition: basic_container_wrapper.h:59
auto begin() noexcept
Definition: basic_container_wrapper.h:164
Wrapped_t m_wrapped
Wrapped object.
Definition: basic_container_wrapper.h:201
Wrapped_tp Wrapped_t
Definition: basic_container_wrapper.h:64
void clear() noexcept
Clear the wrapped object.
Definition: basic_container_wrapper.h:128
const auto & wrapped() const &noexcept
Definition: basic_container_wrapper.h:186
auto get_memory_resource() const noexcept
Return the memory resource used by the wrapped object.
Definition: basic_container_wrapper.h:137
auto assign(const First_iterator_t &first, const Sentinel_t &last) noexcept(shall_catch==mysql::utils::Shall_catch::yes||noexcept(std::declval< Wrapped_t >().assign(first, last)))
Assign a range defined by the two iterators to the wrapped object.
Definition: basic_container_wrapper.h:83
auto begin() const noexcept
Definition: basic_container_wrapper.h:170
auto empty() const noexcept
Definition: basic_container_wrapper.h:176
auto end() noexcept
Definition: basic_container_wrapper.h:167
Self_tp Self_t
Definition: basic_container_wrapper.h:60
void assign(Self_t &&other) noexcept
Move-assign the other object to the wrapped object.
Definition: basic_container_wrapper.h:118
auto & wrapped() &noexcept
Definition: basic_container_wrapper.h:183
auto end() const noexcept
Definition: basic_container_wrapper.h:173
auto size() const noexcept
Definition: basic_container_wrapper.h:179
auto && wrapped() &&noexcept
Definition: basic_container_wrapper.h:189
auto get_allocator() const noexcept
Return the allocator used by the wrapped object.
Definition: basic_container_wrapper.h:159
auto assign(const Other_t &other) noexcept(shall_catch==mysql::utils::Shall_catch::yes||noexcept(std::declval< Self_t >().assign(other.begin(), other.end())))
Copy-assign the other object to the wrapped object.
Definition: basic_container_wrapper.h:98
Basic_container_wrapper(Args_t &&...args) noexcept(noexcept(Wrapped_t(std::forward< Args_t >(args)...)))
Constructor that delegates all parameters to the constructor of the wrapped class.
Definition: basic_container_wrapper.h:70
Basic_container_wrapper< Self_t, Wrapped_tp, shall_catch > This_t
Definition: basic_container_wrapper.h:61
CRTP base class to provide members of a collection based on an implementation that provides begin/end...
Definition: collection_interface.h:90
Experimental API header.
false if Args is exactly one type, say A, and std::decay_t<A> equals Type.
Definition: not_decayed.h:84
Experimental API header.
Definition: basic_container_wrapper.h:42
@ ok
operation succeeded
decltype(auto) conditional_call_and_catch(const Function_t &function, Args_t &&...args) noexcept(noexcept(function(std::forward< Args_t >(args)...))||shall_catch==Shall_catch::yes)
Call function, and if shall_catch is true, catch exceptions and wrap them in the return value.
Definition: call_and_catch.h:112
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76
bool is_same_object(const Obj1_t &obj1, const Obj2_t &obj2)
Return true if the types of the two objects are either equal or one derived from the other,...
Definition: is_same_object.h:40
Experimental API header.
Experimental API header.