MySQL 9.1.0
Source Code Documentation
template_utils.h
Go to the documentation of this file.
1/* Copyright (c) 2013, 2024, 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 TEMPLATE_UTILS_INCLUDED
25#define TEMPLATE_UTILS_INCLUDED
26
27#include <assert.h>
28#include <ctype.h>
29#include <stddef.h>
30#include <algorithm>
31#include <iterator>
32#include <optional>
33#include <type_traits>
34
35/**
36 @file include/template_utils.h
37*/
38
39/**
40 Clears a container, but deletes all objects that the elements point to first.
41 @tparam Container_type Container of pointers.
42 */
43template <typename Container_type>
44void delete_container_pointers(Container_type &container) {
45 typename Container_type::iterator it1 = container.begin();
46 typename Container_type::iterator it2 = container.end();
47 for (; it1 != it2; ++it1) {
48 delete (*it1);
49 }
50 container.clear();
51}
52
53/**
54 Clears a container, but frees all objects that the elements point to first.
55 @tparam Container_type Container of pointers.
56 */
57template <typename Container_type>
59 typename Container_type::iterator it1 = container.begin();
60 typename Container_type::iterator it2 = container.end();
61 for (; it1 != it2; ++it1) {
62 my_free(*it1);
63 }
64 container.clear();
65}
66
67/**
68 Casts from one pointer type, to another, without using
69 reinterpret_cast or C-style cast:
70 foo *f; bar *b= pointer_cast<bar*>(f);
71 This avoids having to do:
72 foo *f; bar *b= static_cast<bar*>(static_cast<void*>(f));
73 */
74template <typename T>
75constexpr T pointer_cast(void *p) {
76 return static_cast<T>(p);
77}
78
79template <typename T>
80constexpr T pointer_cast(const void *p) {
81 return static_cast<T>(p);
82}
83
84/**
85 Casts from one pointer type to another in a type hierarchy.
86 In debug mode, we verify the cast is indeed legal.
87
88 @tparam Target The descendent type, must be a pointer type.
89 @tparam Source The parent type.
90
91 @param arg The pointer to be down-cast.
92
93 @return A pointer of type Target.
94*/
95template <typename Target, typename Source>
96inline Target down_cast(Source *arg) {
97 static_assert(
99 Source>::value,
100 "Do not use down_cast for upcasts; use implicit_cast or nothing");
101 assert(nullptr != dynamic_cast<Target>(arg));
102 return static_cast<Target>(arg);
103}
104
105/**
106 Casts from one reference type to another in a type hierarchy.
107 In debug mode, we verify the cast is indeed legal.
108
109 @tparam Target The descendent type, must be a reference type.
110 @tparam Source The parent type.
111
112 @param arg The reference to be down-cast.
113
114 @return A reference of type Target.
115*/
116template <typename Target, typename Source>
117inline Target down_cast(Source &arg) {
118 // We still use the pointer version of dynamic_cast, as the
119 // reference-accepting version throws exceptions, and we don't want to deal
120 // with that.
121 static_assert(
123 Source>::value,
124 "Do not use down_cast for upcasts; use implicit_cast or nothing");
125 assert(dynamic_cast<typename std::remove_reference<Target>::type *>(&arg) !=
126 nullptr);
127 return static_cast<Target>(arg);
128}
129
130/**
131 Sometimes the compiler insists that types be the same and does not do any
132 implicit conversion. For example:
133 Derived1 *a;
134 Derived2 *b; // Derived1 and 2 are children classes of Base
135 Base *x= cond ? a : b; // Error, need to force a cast.
136
137 Use:
138 Base *x= cond ? implicit_cast<Base*>(a) : implicit_cast<Base*>(b);
139 static_cast would work too, but would be less safe (allows any
140 pointer-to-pointer conversion, not only up-casts).
141*/
142template <typename To>
143inline To implicit_cast(To x) {
144 return x;
145}
146
147/**
148 Utility to allow returning values from functions which can fail
149 (until we have std::optional).
150 */
151template <class VALUE_TYPE>
153 /** Value returned from function in the normal case. */
154 VALUE_TYPE value;
155
156 /** True if an error occurred. */
157 bool error;
158};
159
160/**
161 Number of elements in a constant C array.
162 */
163template <class T, size_t N>
164constexpr size_t array_elements(T (&)[N]) noexcept {
165 return N;
166}
167
168namespace myu {
169/**
170 Split a range into sub ranges delimited by elements satisfying a predicate.
171 Examines the elements from first to last, exclusive. Each time an element
172 which satisfies the splitting predicate is encountered, the action argument's
173 operator() is invoked with the starting and past-the-end iterators for the
174 current sub-range, even if this is empty. When iteration is complete, action()
175 is called on the range between the start of the last subrange and last.
176
177 It must be possible to pass a single element with type const
178 InputIt::value_type to is_split_element. It must be possible to pass two
179 InputIt arguments to action.
180
181 @param first Beginning of the range to split.
182 @param last End of the range to split.
183 @param pred Callable which will be invoked on each element in
184 turn to determine if it is a splitting element.
185 @param action Callable which will be invoked with the beginning
186 and one-past-the-end iterators for each subrange.
187 */
188template <class InputIt, class Pred, class Action>
189inline void Split(InputIt first, InputIt last, Pred &&pred, Action &&action) {
190 while (first != last) {
191 InputIt split = std::find_if(first, last, std::forward<Pred>(pred));
192 action(first, split); // Called even for empty subranges, action must
193 // discard if not wanted
194 if (split == last) return;
195 first = split + 1;
196 }
197}
198
199/**
200 Search backwards for the first occurrence of an element which does not satisfy
201 the trimming predicate, and return an InputIt to the element after it.
202
203 @param first Beginning of the range to search.
204 @param last End of the range to search.
205 @param pred Callable which can be applied to a dereferenced InputIt and which
206 returns true if the element should be trimmed.
207
208 @returns InputIt referencing the first element of sub range satisfying the
209 trimming predicate at the end of the range. last if no elements
210 satisfy the trimming predicate.
211 */
212template <class InputIt, class Pred>
213inline InputIt FindTrimmedEnd(InputIt first, InputIt last, Pred &&pred) {
214 return std::find_if_not(std::make_reverse_iterator(last),
215 std::make_reverse_iterator(first),
216 std::forward<Pred>(pred))
217 .base();
218}
219
220/**
221 Searches for a sub range such that no elements before or after fail to
222 satisfy the trimming predicate.
223
224 @param first Beginning of the range to search.
225 @param last End of the range to search.
226 @param pred Callable which can be applied to a dereferenced InputIt and which
227 returns true if the element should be trimmed.
228
229 @returns Pair of iterators denoting the sub range which does not include the
230 leading and trailing sub ranges matching the trimming predicate.
231 {last, last} if all elements match the trimming predicate.
232 */
233template <class InputIt, class Pred>
234inline std::pair<InputIt, InputIt> FindTrimmedRange(InputIt first, InputIt last,
235 Pred &&pred) {
236 InputIt f = std::find_if_not(first, last, std::forward<Pred>(pred));
237 return {f, FindTrimmedEnd(f, last, std::forward<Pred>(pred))};
238}
239
240/** Convenience lambdas for common predicates. */
241const auto IsSpace = [](char c) { return isspace(c); };
242const auto IsComma = [](char c) { return c == ','; };
243
244} // namespace myu
245#endif // TEMPLATE_UTILS_INCLUDED
const char * p
Definition: ctype-mb.cc:1225
void my_free(void *ptr)
Frees the memory pointed by the ptr.
Definition: my_memory.cc:81
std::atomic< Type > N
Definition: ut0counter.h:225
Definition: atomics_array.h:39
Container::const_iterator find_if(const Container &c, Find_if &&find_if)
Definition: generic.h:54
bool isspace(const char &ch)
Definition: parsing_helpers.h:34
Definition: template_utils.h:168
const auto IsSpace
Convenience lambdas for common predicates.
Definition: template_utils.h:241
void Split(InputIt first, InputIt last, Pred &&pred, Action &&action)
Split a range into sub ranges delimited by elements satisfying a predicate.
Definition: template_utils.h:189
InputIt FindTrimmedEnd(InputIt first, InputIt last, Pred &&pred)
Search backwards for the first occurrence of an element which does not satisfy the trimming predicate...
Definition: template_utils.h:213
std::pair< InputIt, InputIt > FindTrimmedRange(InputIt first, InputIt last, Pred &&pred)
Searches for a sub range such that no elements before or after fail to satisfy the trimming predicate...
Definition: template_utils.h:234
const auto IsComma
Definition: template_utils.h:242
message Source
Definition: replication_asynchronous_connection_failover.proto:30
message Action
Definition: replication_group_member_actions.proto:30
required string type
Definition: replication_group_member_actions.proto:34
repeated Action action
Definition: replication_group_member_actions.proto:43
Utility to allow returning values from functions which can fail (until we have std::optional).
Definition: template_utils.h:152
VALUE_TYPE value
Value returned from function in the normal case.
Definition: template_utils.h:154
bool error
True if an error occurred.
Definition: template_utils.h:157
To implicit_cast(To x)
Sometimes the compiler insists that types be the same and does not do any implicit conversion.
Definition: template_utils.h:143
Target down_cast(Source *arg)
Casts from one pointer type to another in a type hierarchy.
Definition: template_utils.h:96
constexpr size_t array_elements(T(&)[N]) noexcept
Number of elements in a constant C array.
Definition: template_utils.h:164
void delete_container_pointers(Container_type &container)
Clears a container, but deletes all objects that the elements point to first.
Definition: template_utils.h:44
constexpr T pointer_cast(void *p)
Casts from one pointer type, to another, without using reinterpret_cast or C-style cast: foo f; bar *...
Definition: template_utils.h:75
void my_free_container_pointers(Container_type &container)
Clears a container, but frees all objects that the elements point to first.
Definition: template_utils.h:58