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