MySQL 8.0.33
Source Code Documentation
template_utils.h
Go to the documentation of this file.
1/* Copyright (c) 2013, 2023, 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 also distributed 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 included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23#ifndef TEMPLATE_UTILS_INCLUDED
24#define TEMPLATE_UTILS_INCLUDED
25
26#include <assert.h>
27#include <ctype.h>
28#include <stddef.h>
29#include <algorithm>
30#include <iterator>
31#include <optional>
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>
74inline T pointer_cast(void *p) {
75 return static_cast<T>(p);
76}
77
78template <typename T>
79inline const 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(
98 Source>::value,
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(
122 Source>::value,
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 (until we have std::optional).
149 */
150template <class VALUE_TYPE>
152 /** Value returned from function in the normal case. */
153 VALUE_TYPE value;
154
155 /** True if an error occurred. */
156 bool error;
157};
158
159/**
160 Number of elements in a constant C array.
161 */
162template <class T, size_t N>
163constexpr size_t array_elements(T (&)[N]) noexcept {
164 return N;
165}
166
167namespace myu {
168/**
169 Split a range into sub ranges delimited by elements satisfying a predicate.
170 Examines the elements from first to last, exclusive. Each time an element
171 which satisfies the splitting predicate is encountered, the action argument's
172 operator() is invoked with the starting and past-the-end iterators for the
173 current sub-range, even if this is empty. When iteration is complete, action()
174 is called on the range between the start of the last subrange and last.
175
176 It must be possible to pass a single element with type const
177 InputIt::value_type to is_split_element. It must be possible to pass two
178 InputIt arguments to action.
179
180 @param first Beginning of the range to split.
181 @param last End of the range to split.
182 @param pred Callable which will be invoked on each element in
183 turn to determine if it is a splitting element.
184 @param action Callable which will be invoked with the beginning
185 and one-past-the-end iterators for each subrange.
186 */
187template <class InputIt, class Pred, class Action>
188inline void Split(InputIt first, InputIt last, Pred &&pred, Action &&action) {
189 while (first != last) {
190 InputIt split = std::find_if(first, last, std::forward<Pred>(pred));
191 action(first, split); // Called even for empty subranges, action must
192 // discard if not wanted
193 if (split == last) return;
194 first = split + 1;
195 }
196}
197
198/**
199 Search backwards for the first occurrence of an element which does not satisfy
200 the trimming predicate, and return an InputIt to the element after it.
201
202 @param first Beginning of the range to search.
203 @param last End of the range to search.
204 @param pred Callable which can be applied to a dereferenced InputIt and which
205 returns true if the element should be trimmed.
206
207 @returns InputIt referencing the first element of sub range satisfying the
208 trimming predicate at the end of the range. last if no elements
209 satisfy the trimming predicate.
210 */
211template <class InputIt, class Pred>
212inline InputIt FindTrimmedEnd(InputIt first, InputIt last, Pred &&pred) {
213 return std::find_if_not(std::make_reverse_iterator(last),
214 std::make_reverse_iterator(first),
215 std::forward<Pred>(pred))
216 .base();
217}
218
219/**
220 Searches for a sub range such that no elements before or after fail to
221 satisfy the trimming predicate.
222
223 @param first Beginning of the range to search.
224 @param last End of the range to search.
225 @param pred Callable which can be applied to a dereferenced InputIt and which
226 returns true if the element should be trimmed.
227
228 @returns Pair of iterators denoting the sub range which does not include the
229 leading and trailing sub ranges matching the trimming predicate.
230 {last, last} if all elements match the trimming predicate.
231 */
232template <class InputIt, class Pred>
233inline std::pair<InputIt, InputIt> FindTrimmedRange(InputIt first, InputIt last,
234 Pred &&pred) {
235 InputIt f = std::find_if_not(first, last, std::forward<Pred>(pred));
236 return {f, FindTrimmedEnd(f, last, std::forward<Pred>(pred))};
237}
238
239/** Convenience lambdas for common predicates. */
240const auto IsSpace = [](char c) { return isspace(c); };
241const auto IsComma = [](char c) { return c == ','; };
242
243} // namespace myu
244#endif // TEMPLATE_UTILS_INCLUDED
const char * p
Definition: ctype-mb.cc:1236
void my_free(void *ptr)
Frees the memory pointed by the ptr.
Definition: my_memory.cc:80
std::atomic< Type > N
Definition: ut0counter.h:224
Definition: atomics_array.h:38
Definition: template_utils.h:167
const auto IsSpace
Convenience lambdas for common predicates.
Definition: template_utils.h:240
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:188
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:212
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:233
const auto IsComma
Definition: template_utils.h:241
message Source
Definition: replication_asynchronous_connection_failover.proto:29
message Action
Definition: replication_group_member_actions.proto:29
required string type
Definition: replication_group_member_actions.proto:33
repeated Action action
Definition: replication_group_member_actions.proto:42
Utility to allow returning values from functions which can fail (until we have std::optional).
Definition: template_utils.h:151
VALUE_TYPE value
Value returned from function in the normal case.
Definition: template_utils.h:153
bool error
True if an error occurred.
Definition: template_utils.h:156
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:163
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
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