Maipa's Standard Library Extension 1.5.6
mstd
Loading...
Searching...
No Matches
macros.hpp
1/*
2 * mstd - Maipa's Standard Library
3 *
4 * Licensed under the BSD 3-Clause License with Attribution Requirement.
5 * See the LICENSE file for details: https://github.com/MAIPA01/mstd/blob/main/LICENSE
6 *
7 * Copyright (c) 2025, Patryk Antosik (MAIPA01)
8 */
9
10#pragma once
11#ifndef _MSTD_MACROS_HPP_
12 #define _MSTD_MACROS_HPP_
13
14 #include <mstd/config.hpp>
15
17_MSTD_WARNING("this is only available for c++17 and greater!");
18 #else
19
20 // define MSTD_ENABLE_FOR_EACH_MACROS or MSTD_ENABLE_ENUMS_MACROS or MSTD_ENABLE_CLONE_FUNC_MACROS to use macros in for each region
21 #pragma region FOR_EACH
22
23 #if defined(MSTD_ENABLE_FOR_EACH_MACROS) || defined(MSTD_ENABLE_ENUMS_MACROS) || defined(MSTD_ENABLE_CLONE_FUNC_MACROS)
24
25 #define _RESCAN(...) _RESCAN1(_RESCAN1(_RESCAN1(_RESCAN1(__VA_ARGS__))))
26 #define _RESCAN1(...) _RESCAN2(_RESCAN2(_RESCAN2(_RESCAN2(__VA_ARGS__))))
27 #define _RESCAN2(...) _RESCAN3(_RESCAN3(_RESCAN3(_RESCAN3(__VA_ARGS__))))
28 #define _RESCAN3(...) _RESCAN4(_RESCAN4(_RESCAN4(_RESCAN4(__VA_ARGS__))))
29 #define _RESCAN4(...) __VA_ARGS__
30
31 #define _INVOKE(macro, args) macro args
32
33 #pragma region TUPLES
34
35 #define MAKE_TUPLE(...) (__VA_ARGS__)
36
37 #define _BREAK_TUPLE_HELPER(...) __VA_ARGS__
38 #define BREAK_TUPLE(tuple) _BREAK_TUPLE_HELPER tuple
39
40 #define APPEND_TUPLE_FRONT(tuple, value) (value, BREAK_TUPLE(tuple))
41 #define APPEND_TUPLE_BACK(tuple, value) (BREAK_TUPLE(tuple), value)
42
43 #define _POP_TUPLE_FRONT_HELPER(value, ...) MAKE_TUPLE(__VA_ARGS__)
44 #define POP_TUPLE_FRONT(tuple) _INVOKE(_POP_TUPLE_FRONT_HELPER, (BREAK_TUPLE(tuple)))
45
46 #pragma endregion
47
48 #pragma region FOR_EACH
49
50 #define _PARENS ()
51 #define _NEXT_ELEM ,
52
53 #define _FOR_EACH(func, helper, value, ...) _RESCAN(helper(func, value __VA_OPT__(, __VA_ARGS__)))
54 #define _FOR_EACH_HELPER(func, again, separator, value, ...)
55 func(value) __VA_OPT__(separator again _PARENS(func, __VA_ARGS__))
56
57 #define DO_FOR_EACH(func, value, ...) _FOR_EACH(func, _DO_FOR_EACH_HELPER, value __VA_OPT__(, __VA_ARGS__))
58 #define _DO_FOR_EACH_HELPER(func, value, ...)
59 _FOR_EACH_HELPER(func, _DO_FOR_EACH_AGAIN, , value __VA_OPT__(, __VA_ARGS__))
60 #define _DO_FOR_EACH_AGAIN() _DO_FOR_EACH_HELPER
61
62 #define DO_FOR_EACH_WITH_CONST(func, const_value, value, ...)
63 _FOR_EACH(func, _DO_FOR_EACH_WITH_CONST_HELPER, const_value, value __VA_OPT__(, __VA_ARGS__))
64 #define _DO_FOR_EACH_WITH_CONST_HELPER(func, const_value, value, ...)
65 func(const_value, value) __VA_OPT__(_DO_FOR_EACH_WITH_CONST_AGAIN _PARENS(func, const_value, __VA_ARGS__))
66 #define _DO_FOR_EACH_WITH_CONST_AGAIN() _DO_FOR_EACH_WITH_CONST_HELPER
67
68 #define LIST_DO_FOR_EACH(func, value, ...) _FOR_EACH(func, _LIST_DO_FOR_EACH_HELPER, value __VA_OPT__(, __VA_ARGS__))
69 #define _LIST_DO_FOR_EACH_HELPER(func, value, ...)
70 _FOR_EACH_HELPER(func, _LIST_DO_FOR_EACH_AGAIN, _NEXT_ELEM, value __VA_OPT__(, __VA_ARGS__))
71 #define _LIST_DO_FOR_EACH_AGAIN() _LIST_DO_FOR_EACH_HELPER
72
73 #pragma endregion
74
75 #endif
76
77 #pragma endregion
78
79 // define MSTD_ENABLE_ENUMS_MACROS to use macros in enums region
80 #pragma region ENUMS
81
82 #ifdef MSTD_ENABLE_ENUMS_MACROS
83
84 #define _ENUM_ELEMENT_COUNT(tuple) +1ull
85 #define _ENUM_TO_STRING_CASE_HELPER(enum_name, name, ...)
86 case enum_name::name: return #name;
87 #define _ENUM_TO_STRING_CASE(enum_name, tuple) _INVOKE(_ENUM_TO_STRING_CASE_HELPER, (enum_name, BREAK_TUPLE(tuple)))
88 #define _ENUM_FROM_STRING_IF_HELPER(enum_name, name, ...)
89 if (s == #name) return enum_name::name;
90 #define _ENUM_FROM_STRING_IF(enum_name, tuple) _INVOKE(_ENUM_FROM_STRING_IF_HELPER, (enum_name, BREAK_TUPLE(tuple)))
91
92 #define _ENUM_DECLARATION(type, name, base, elem_func, ...)
93 type name base { LIST_DO_FOR_EACH(elem_func, __VA_ARGS__) };
94
95 #define _ENUM_SIZE_FUNC(name, ...)
96 template<class T>
97 inline _MSTD_CONSTEXPR20 size_t size() noexcept;
98 template<>
99 inline _MSTD_CONSTEXPR20 size_t size<name>() noexcept {
100 return DO_FOR_EACH(_ENUM_ELEMENT_COUNT, __VA_ARGS__);
101 }
102
103 #define _ENUM_TO_STRING_FUNC(name, case_func, ...)
104 inline const ::std::string to_string(const name& v) {
105 switch (v) {
106 DO_FOR_EACH_WITH_CONST(case_func, name, __VA_ARGS__)
107 default: return "UNKNOWN";
108 }
109 }
110
111 #define _ENUM_STREAM_OPERATOR(name)
112 inline ::std::ostream& operator<<(::std::ostream& os, const name& v) { return os << to_string(v); }
113
114 #define _ENUM_FROM_STRING_FUNC(name, case_func, ...)
115 template<class T>
116 inline T from_string(const std::string&);
117 template<>
118 inline name from_string<name>(const std::string& s) {
119 DO_FOR_EACH_WITH_CONST(case_func, name, __VA_ARGS__)
120 throw std::invalid_argument("Unknown enum string: " + s);
121 }
122
123 #define _ENUM_TEMPLATE(type, name, base, declaration_func, size_func, to_string_func, from_string_func, ...)
124 declaration_func(type, name, base, __VA_ARGS__) size_func(name, __VA_ARGS__) to_string_func(name, __VA_ARGS__)
125 _ENUM_STREAM_OPERATOR(name) from_string_func(name, __VA_ARGS__)
126
127 #pragma region STANDARD_ENUMS
128
129 #define _STANDARD_ENUM_ELEMENT_HELPER(name, ...) name
130 #define _STANDARD_ENUM_ELEMENT(tuple) _INVOKE(_STANDARD_ENUM_ELEMENT_HELPER, (BREAK_TUPLE(tuple)))
131 #define _STANDARD_ENUM_STRING_TO_STRING_CASE_HELPER(enum_name, name, string)
132 case enum_name::name: return string;
133 #define _STANDARD_ENUM_STRING_TO_STRING_CASE(enum_name, tuple)
134 _INVOKE(_STANDARD_ENUM_STRING_TO_STRING_CASE_HELPER, (enum_name, BREAK_TUPLE(tuple)))
135 #define _STANDARD_ENUM_STRING_FROM_STRING_IF_HELPER(enum_name, name, string)
136 if (s == string) return enum_name::name;
137 #define _STANDARD_ENUM_STRING_FROM_STRING_IF(enum_name, tuple)
138 _INVOKE(_STANDARD_ENUM_STRING_FROM_STRING_IF_HELPER, (enum_name, BREAK_TUPLE(tuple)))
139
140 #define _STANDARD_ENUM_DECLARATION(type, name, base, ...)
141 _ENUM_DECLARATION(type, name, base, _STANDARD_ENUM_ELEMENT, __VA_ARGS__)
142
143 #define _STANDARD_ENUM_SIZE_FUNC(name, ...) _ENUM_SIZE_FUNC(name, __VA_ARGS__)
144
145 #define _STANDARD_ENUM_TO_STRING_FUNC(name, ...) _ENUM_TO_STRING_FUNC(name, _ENUM_TO_STRING_CASE, __VA_ARGS__)
146
147 #define _STANDARD_ENUM_STRING_TO_STRING_FUNC(name, ...)
148 _ENUM_TO_STRING_FUNC(name, _STANDARD_ENUM_STRING_TO_STRING_CASE, __VA_ARGS__)
149
150 #define _STANDARD_ENUM_FROM_STRING_FUNC(name, ...) _ENUM_FROM_STRING_FUNC(name, _ENUM_FROM_STRING_IF, __VA_ARGS__)
151
152 #define _STANDARD_ENUM_STRING_FROM_STRING_FUNC(name, ...)
153 _ENUM_FROM_STRING_FUNC(name, _STANDARD_ENUM_STRING_FROM_STRING_IF, __VA_ARGS__)
154
155 #define _STANDARD_ENUM_FUNC_TEMPLATE(type, name, base, declaration_func, size_func, to_string_func,
156 from_string_func, ...)
157 _ENUM_TEMPLATE(type, name, base, declaration_func, size_func, to_string_func, from_string_func, __VA_ARGS__)
158
159 #define _STANDARD_ENUM_TEMPLATE(type, name, base, ...)
160 _STANDARD_ENUM_FUNC_TEMPLATE(type, name, base, _STANDARD_ENUM_DECLARATION, _STANDARD_ENUM_SIZE_FUNC,
161 _STANDARD_ENUM_TO_STRING_FUNC, _STANDARD_ENUM_FROM_STRING_FUNC, __VA_ARGS__)
162 #define _STANDARD_ENUM_STRING_TEMPLATE(type, name, base, ...)
163 _STANDARD_ENUM_FUNC_TEMPLATE(type, name, base, _STANDARD_ENUM_DECLARATION, _STANDARD_ENUM_SIZE_FUNC,
164 _STANDARD_ENUM_STRING_TO_STRING_FUNC, _STANDARD_ENUM_STRING_FROM_STRING_FUNC, __VA_ARGS__)
165
166 #define _STANDARD_ENUM(name, base, ...) _STANDARD_ENUM_TEMPLATE(enum, name, base, __VA_ARGS__)
167 #define _STANDARD_ENUM_CLASS(name, base, ...) _STANDARD_ENUM_TEMPLATE(enum class, name, base, __VA_ARGS__)
168
169 #define _STANDARD_ENUM_STRING(name, base, ...) _STANDARD_ENUM_STRING_TEMPLATE(enum, name, base, __VA_ARGS__)
170 #define _STANDARD_ENUM_CLASS_STRING(name, base, ...)
171 _STANDARD_ENUM_STRING_TEMPLATE(enum class, name, base, __VA_ARGS__)
172
173 #define ENUM(name, ...) _STANDARD_ENUM(name, , __VA_ARGS__)
174 #define ENUM_BASE(name, base, ...) _STANDARD_ENUM(name, : base, __VA_ARGS__)
175 #define ENUM_CLASS(name, ...) _STANDARD_ENUM_CLASS(name, , __VA_ARGS__)
176 #define ENUM_CLASS_BASE(name, base, ...) _STANDARD_ENUM_CLASS(name, : base, __VA_ARGS__)
177
178 #define ENUM_STRING(name, ...) _STANDARD_ENUM_STRING(name, , __VA_ARGS__)
179 #define ENUM_BASE_STRING(name, base, ...) _STANDARD_ENUM_STRING(name, : base, __VA_ARGS__)
180 #define ENUM_CLASS_STRING(name, ...) _STANDARD_ENUM_CLASS_STRING(name, , __VA_ARGS__)
181 #define ENUM_CLASS_BASE_STRING(name, base, ...) _STANDARD_ENUM_CLASS_STRING(name, : base, __VA_ARGS__)
182
183 #pragma endregion
184
185 #pragma region ENUMS_WITH_VALUE
186
187 #define _VALUE_ENUM_ELEMENT_HELPER(name, value, ...) name = value
188 #define _VALUE_ENUM_ELEMENT(tuple) _INVOKE(_VALUE_ENUM_ELEMENT_HELPER, (BREAK_TUPLE(tuple)))
189 #define _VALUE_ENUM_STRING_TO_STRING_CASE_HELPER(enum_name, name, value, string)
190 case enum_name::name: return string;
191 #define _VALUE_ENUM_STRING_TO_STRING_CASE(enum_name, tuple)
192 _INVOKE(_VALUE_ENUM_STRING_TO_STRING_CASE_HELPER, (enum_name, BREAK_TUPLE(tuple)))
193 #define _VALUE_ENUM_STRING_FROM_STRING_IF_HELPER(enum_name, name, value, string)
194 if (s == string) return enum_name::name;
195 #define _VALUE_ENUM_STRING_FROM_STRING_IF(enum_name, tuple)
196 _INVOKE(_VALUE_ENUM_STRING_FROM_STRING_IF_HELPER, (enum_name, BREAK_TUPLE(tuple)))
197
198 #define _VALUE_ENUM_DECLARATION(type, name, base, ...)
199 _ENUM_DECLARATION(type, name, base, _VALUE_ENUM_ELEMENT, __VA_ARGS__)
200
201 #define _VALUE_ENUM_SIZE_FUNC(name, ...) _ENUM_SIZE_FUNC(name, __VA_ARGS__)
202
203 #define _VALUE_ENUM_TO_STRING_FUNC(name, ...) _ENUM_TO_STRING_FUNC(name, _ENUM_TO_STRING_CASE, __VA_ARGS__)
204 #define _VALUE_ENUM_STRING_TO_STRING_FUNC(name, ...)
205 _ENUM_TO_STRING_FUNC(name, _VALUE_ENUM_STRING_TO_STRING_CASE, __VA_ARGS__)
206
207 #define _VALUE_ENUM_FROM_STRING_FUNC(name, ...) _ENUM_FROM_STRING_FUNC(name, _ENUM_FROM_STRING_IF, __VA_ARGS__)
208 #define _VALUE_ENUM_STRING_FROM_STRING_FUNC(name, ...)
209 _ENUM_FROM_STRING_FUNC(name, _VALUE_ENUM_STRING_FROM_STRING_IF, __VA_ARGS__)
210
211 #define _VALUE_ENUM_FUNC_TEMPLATE(type, name, base, declaration, size_func, to_string_func, from_string_func, ...)
212 _ENUM_TEMPLATE(type, name, base, declaration, size_func, to_string_func, from_string_func, __VA_ARGS__)
213
214 #define _VALUE_ENUM_TEMPLATE(type, name, base, ...)
215 _VALUE_ENUM_FUNC_TEMPLATE(type, name, base, _VALUE_ENUM_DECLARATION, _VALUE_ENUM_SIZE_FUNC,
216 _VALUE_ENUM_TO_STRING_FUNC, _VALUE_ENUM_FROM_STRING_FUNC, __VA_ARGS__)
217 #define _VALUE_ENUM_STRING_TEMPLATE(type, name, base, ...)
218 _VALUE_ENUM_FUNC_TEMPLATE(type, name, base, _VALUE_ENUM_DECLARATION, _VALUE_ENUM_SIZE_FUNC,
219 _VALUE_ENUM_STRING_TO_STRING_FUNC, _VALUE_ENUM_STRING_FROM_STRING_FUNC, __VA_ARGS__)
220
221 #define _VALUE_ENUM(name, base, ...) _VALUE_ENUM_TEMPLATE(enum, name, base, __VA_ARGS__)
222 #define _VALUE_ENUM_CLASS(name, base, ...) _VALUE_ENUM_TEMPLATE(enum class, name, base, __VA_ARGS__)
223
224 #define _VALUE_ENUM_STRING(name, base, ...) _VALUE_ENUM_STRING_TEMPLATE(enum, name, base, __VA_ARGS__)
225 #define _VALUE_ENUM_CLASS_STRING(name, base, ...) _VALUE_ENUM_STRING_TEMPLATE(enum class, name, base, __VA_ARGS__)
226
227 #define ENUM_VALUE(name, ...) _VALUE_ENUM(name, , __VA_ARGS__)
228 #define ENUM_BASE_VALUE(name, base, ...) _VALUE_ENUM(name, : base, __VA_ARGS__)
229 #define ENUM_CLASS_VALUE(name, ...) _VALUE_ENUM_CLASS(name, , __VA_ARGS__)
230 #define ENUM_CLASS_BASE_VALUE(name, base, ...) _VALUE_ENUM_CLASS(name, : base, __VA_ARGS__)
231
232 #define ENUM_VALUE_STRING(name, ...) _VALUE_ENUM_STRING(name, , __VA_ARGS__)
233 #define ENUM_BASE_VALUE_STRING(name, base, ...) _VALUE_ENUM_STRING(name, : base, __VA_ARGS__)
234 #define ENUM_CLASS_VALUE_STRING(name, ...) _VALUE_ENUM_CLASS_STRING(name, , __VA_ARGS__)
235 #define ENUM_CLASS_BASE_VALUE_STRING(name, base, ...) _VALUE_ENUM_CLASS_STRING(name, : base, __VA_ARGS__)
236
237 #pragma endregion
238
239 #endif
240
241 #pragma endregion
242
243 // define USE_CLONE_FUNC_MACROS to use macros in clone func region
244 #pragma region CLONE_FUNC
245
246 #ifdef MSTD_ENABLE_CLONE_FUNC_MACROS
247
248 #pragma region CLONE_FUNC_DECLARATION
249
250 #define _DECLARE_CLONE_FUNC_TEMPLATE(class_name, base_class_operator)
251 virtual class_name* Clone() const base_class_operator;
252 void CloneTo(class_name* cloned) const;
253
254 #define DECLARE_CLONE_FUNC(class_name) _DECLARE_CLONE_FUNC_TEMPLATE(class_name, )
255 #define DECLARE_OVERRIDED_CLONE_FUNC(class_name) _DECLARE_CLONE_FUNC_TEMPLATE(class_name, override)
256 #define DECLARE_ABSTRACT_CLONE_FUNC(class_name) _DECLARE_CLONE_FUNC_TEMPLATE(class_name, = 0)
257
258 #pragma endregion
259
260 #pragma region CLONE_FUNC_DECLARATION_WITH_DEFINITION
261
262 #define _FIELD_CLONE_HELPER(fieldName, value) cloned->fieldName = value;
263 #define FIELD_CLONE(tuple) _INVOKE(_FIELD_CLONE_HELPER, (BREAK_TUPLE(tuple)))
264
265 #define _DECLARE_CLONE_FUNC_WITH_DEFINITION_TEMPLATE(class_name, base_class_func, base_class_operator, ...)
266 virtual class_name* Clone() const base_class_operator {
267 class_name* cloned = new class_name();
268 CloneTo(cloned);
269 return cloned;
270 }
271 void CloneTo(class_name* cloned) const { base_class_func __VA_OPT__(DO_FOR_EACH(FIELD_CLONE, __VA_ARGS__)) }
272
273 #define STANDARD_CLONE(fieldName) MAKE_TUPLE(fieldName, fieldName)
274 #define POINTER_DEEP_CLONE(fieldName, valueType) MAKE_TUPLE(fieldName, new valueType(*fieldName))
275
276 #define DECLARE_CLONE_FUNC_WITH_DEFINITION_ADVANCED(class_name, ...)
277 _DECLARE_CLONE_FUNC_WITH_DEFINITION_TEMPLATE(class_name, , __VA_OPT__(, __VA_ARGS__))
278 #define DECLARE_CLONE_BASE_FUNC_WITH_DEFINITION_ADVANCED(class_name, base_class_name, ...)
279 _DECLARE_CLONE_FUNC_WITH_DEFINITION_TEMPLATE(class_name, base_class_name::CloneTo(cloned);
280 , override __VA_OPT__(, __VA_ARGS__))
281
282 #define DECLARE_CLONE_FUNC_WITH_DEFINITION(class_name, ...)
283 DECLARE_CLONE_FUNC_WITH_DEFINITION_ADVANCED(class_name __VA_OPT__(,
284 LIST_DO_FOR_EACH(STANDARD_CLONE, __VA_ARGS__)))
285 #define DECLARE_CLONE_BASE_FUNC_WITH_DEFINITION(class_name, base_class_name, ...)
286 DECLARE_CLONE_BASE_FUNC_WITH_DEFINITION_ADVANCED(class_name,
287 base_class_name __VA_OPT__(, LIST_DO_FOR_EACH(STANDARD_CLONE, __VA_ARGS__)))
288
289 #pragma endregion
290
291 #pragma region CLONE_FUNC_DEFINITION
292
293 #define _CLONE_FUNC_DEFINITION_TEMPLATE(class_name, base_class_func, ...)
294 class_name* class_name::Clone() const {
295 class_name* cloned = new class_name();
296 CloneTo(cloned);
297 return cloned;
298 }
299 void class_name::CloneTo(class_name* cloned) const {
300 base_class_func __VA_OPT__(DO_FOR_EACH(FIELD_CLONE, __VA_ARGS__))
301 }
302
303 #define CLONE_FUNC_DEFINITION_ADVANCED(class_name, ...)
304 _CLONE_FUNC_DEFINITION_TEMPLATE(class_name, __VA_OPT__(, __VA_ARGS__))
305 #define CLONE_BASE_FUNC_DEFINITION_ADVANCED(class_name, base_class_name, ...)
306 _CLONE_FUNC_DEFINITION_TEMPLATE(class_name, base_class_name::CloneTo(cloned); __VA_OPT__(, __VA_ARGS__))
307
308 #define CLONE_FUNC_DEFINITION(class_name, ...)
309 CLONE_FUNC_DEFINITION_ADVANCED(class_name __VA_OPT__(, LIST_DO_FOR_EACH(STANDARD_CLONE, __VA_ARGS__)))
310 #define CLONE_BASE_FUNC_DEFINITION(class_name, base_class_name, ...)
311 CLONE_BASE_FUNC_DEFINITION_ADVANCED(class_name,
312 base_class_name __VA_OPT__(, LIST_DO_FOR_EACH(STANDARD_CLONE, __VA_ARGS__)))
313
314 #pragma endregion
315
316 #endif
317
318 #pragma endregion
319
320 // define MSTD_USE_EXTRA_MACROS to use macros in extra region
321 #pragma region EXTRA
322
323 #ifdef MSTD_ENABLE_EXTRA_MACROS
324
325 #define VAR_TO_STRING(var) #var
326
327 #endif
328
329 #pragma endregion
330
331 #endif
332#endif
#define _MSTD_HAS_CXX17
Definition config.hpp:45