jaulib v1.4.1-17-gd77ace3-dirty
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
cpp_lang_util.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Gothel Software e.K.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25#ifndef JAU_CPP_LANG_EXT_HPP_
26#define JAU_CPP_LANG_EXT_HPP_
27
28#include <climits>
29#include <cstdint>
30#include <string_view>
31#include <type_traits>
32#include <string>
33#include <cstring>
34#include <ostream>
35#if __cplusplus > 201703L
36 // C++20
37 #include <bit>
38#endif
39#if __cplusplus > 202002L
40 // C++23
41 #include <stdbit>
42#endif
43
45
46namespace jau {
47
48 /** @defgroup CppLang C++ Language Utilities
49 * C++ language utilities, language feature alignment, type trails, data alignment and intrinsics.
50 *
51 * Used predefined `__cplusplus` macro identifier for C++ language specs:
52 * - `199711L`: pre C++11
53 * - `201103L`: C++11
54 * - `201402L`: C++14
55 * - `201703L`: C++17
56 * - `202002L`: C++20
57 * - `202302L`: C++23
58 * - `??????L`: C++26 ??
59 *
60 * Used predefined macros denoting the compiler:
61 * - `__clang__` : LLVM's clang, clang++
62 * - `__GNUC__` : GNU Compiler Collection (GCC)'s gcc, g++
63 * - `_MSC_VER` : Microsoft Compiler
64 * - `__MINGW32__` : MinGW 32
65 * - `__MINGW64__` : MinGW 64
66 * - `__EMSCRIPTEN__`: emscripten for asm.js and WebAssembly
67 *
68 * Further infos:
69 * - [Unix standards](https://sourceforge.net/p/predef/wiki/Standards/)
70 * - [GNU glibc](https://sourceforge.net/p/predef/wiki/Libraries/)
71 * - [glibc 1.3.4 Feature Test Macros](https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html)
72 * - [Architectures](https://sourceforge.net/p/predef/wiki/Architectures/)
73 *
74 * @{
75 */
76
77 /**
78 * `consteval` qualifier replacement for C++20 `consteval`.
79 *
80 * > A `consteval` specifier implies `inline`.
81 * > At most one of the `constexpr`, `consteval`, and `constinit` specifiers is allowed to appear within the same sequence of declaration specifiers.
82 * > ...
83 * > An immediate function is a `constexpr` function,
84 * > and must satisfy the requirements applicable to `constexpr` functions or `constexpr` constructors, as the case may be.
85 *
86 * <p>
87 * Evaluated using the alternative qualifier `constexpr` for C++ < 20,
88 * as it is almost contained within `consteval` but lacks the `immediate function` constraint.
89 * </p>
90 * <p>
91 * Evaluated as `consteval` for C++20.
92 * </p>
93 */
94#if __cplusplus > 201703L
95 #define consteval_cxx20 consteval
96#else
97 #define consteval_cxx20 constexpr
98#endif
99
100 /** Returns true if compiled with >= C++17 */
101 consteval_cxx20 bool is_cxx17() noexcept {
102 #if __cplusplus > 201402L
103 return true;
104 #else
105 return false;
106 #endif
107 }
108 /** Returns true if compiled with >= C++20 */
109 consteval_cxx20 bool is_cxx20() noexcept {
110 #if __cplusplus > 201703L
111 return true;
112 #else
113 return false;
114 #endif
115 }
116 /** Returns true if compiled with >= C++23 */
117 consteval_cxx20 bool is_cxx23() noexcept {
118 #if __cplusplus > 202002L
119 return true;
120 #else
121 return false;
122 #endif
123 }
124 /** Returns true if compiled with >= C++26 */
125 consteval_cxx20 bool is_cxx26() noexcept {
126 #if __cplusplus > 202302L
127 return true;
128 #else
129 return false;
130 #endif
131 }
132
133 /**
134 * `constinit` qualifier replacement for C++20 `constinit`.
135 *
136 * > `constinit` cannot be used together with `constexpr` or `consteval`.
137 * > When the declared variable is a reference, `constinit` is equivalent to `constexpr`.
138 * > When the declared variable is an object,
139 * > `constexpr` mandates that the object must have static initialization and constant destruction
140 * > and makes the object const-qualified, however, `constinit` does not mandate constant destruction and const-qualification.
141 *
142 * <p>
143 * Evaluated using the alternative qualifier `constexpr` for C++ < 20,
144 * as it is almost contained within `constinit` but lacks the loosening of not mandating constant destruction and const-qualification.<br>
145 * FIXME: Due to the above, this replacement might not be suitable: TBD!
146 * </p>
147 * <p>
148 * Evaluated as `constinit` for C++20.
149 * </p>
150 */
151#if __cplusplus > 201703L
152 #define constinit_cxx20 constinit
153#else
154 #define constinit_cxx20 constexpr
155#endif
156
157 /**
158 * `constexpr` qualifier replacement for C++20 `constexpr`.
159 *
160 * > A `constexpr` specifier used in a function or static member variable (since C++17) declaration implies `inline`.
161 *
162 * <p>
163 * Evaluated using the alternative qualifier `inline` for C++ < 20,
164 * as it is implied for `constexpr` functions or static member variables, see above.
165 * </p>
166 * <p>
167 * Evaluated as `constexpr` for C++20, i.e. std::string literals, virtual functions, etc.
168 * </p>
169 */
170#if __cplusplus > 201703L
171 #define constexpr_cxx20 constexpr
172#else
173 #define constexpr_cxx20 inline
174#endif
175
176#if __cplusplus > 202002L
177 #define constexpr_cxx23 constexpr
178#else
179 #define constexpr_cxx23 inline
180#endif
181
182#if __cplusplus > 202302L
183 #define constexpr_cxx26 constexpr
184#else
185 #define constexpr_cxx26 inline
186#endif
187
188
189 /**
190 * Used when designed to declare a function `constexpr`,
191 * but prohibited by its specific implementation.
192 * <p>
193 * Evaluated using the alternative qualifier `inline` for C++ < 23,
194 * as it is implied for `constexpr` functions or static member variables, see constexpr_cxx23.
195 * </p>
196 * <p>
197 * Here it but uses non-literal variables, such as std::lock_guard etc.
198 * As these can't be evaluated at compile time, the standard does
199 * not allow using `constexpr` here.
200 * </p>
201 * <p>
202 * Empty until standard defines otherwise.
203 * </p>
204 * @see constexpr_cxx23
205 */
206 #define constexpr_non_literal_var constexpr_cxx23
207
208 /**
209 * Used when designed to declare a function `constexpr`,
210 * but prohibited by its specific implementation.
211 * <p>
212 * Evaluated using the alternative qualifier `inline` for C++ < 23,
213 * as it is implied for `constexpr` functions or static member variables, see constexpr_cxx23.
214 * </p>
215 * <p>
216 * Here it uses thread-safety related measures like atomic storage
217 * or mutex locks, which are non-literal variables and hence
218 * prohibit the use of `constexpr`.
219 * </p>
220 * @see constexpr_cxx23
221 * @see constexpr_non_literal_var
222 */
223 #define constexpr_atomic constexpr_cxx23
224
225 /**
226 * Wrap C++ extension `__restrict__` covering C99's `restrict` feature keyword.
227 */
228 #if defined(__clang__)
229 #define __restrict_cxx__ __restrict__
230 #elif defined(__GNUC__) && !defined(__clang__)
231 #define __restrict_cxx__ __restrict__
232 #elif defined(_MSC_VER)
233 #define __restrict_cxx__ __restrict
234 #else
235 #define __restrict_cxx__
236 #endif
237
238 #if defined(__clang__)
239 /** Consider using [jau::ctti_name<R, L, A...>()](@ref ctti_name_lambda). */
240 #define JAU_PRETTY_FUNCTION __PRETTY_FUNCTION__
241 #elif defined(__GNUC__) && !defined(__clang__)
242 /** Consider using [jau::ctti_name<R, L, A...>()](@ref ctti_name_lambda). */
243 #define JAU_PRETTY_FUNCTION __PRETTY_FUNCTION__
244 #elif defined(_MSC_VER)
245 /** Consider using [jau::ctti_name<R, L, A...>()](@ref ctti_name_lambda). */
246 #define JAU_PRETTY_FUNCTION __FUNCSIG__
247 #else
248 #error "JAU_PRETTY_FUNCTION not available"
249 #endif
250
251 /**
252 * Returns the demangled given mangled_name if successful,
253 * otherwise the mangled_name.
254 *
255 * Implementation utilizes the [cross-vendor C++ ABI abi::__cxa_demangle()](https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html)
256 * as supported at least on on `gcc` and `clang`.
257 *
258 * May be used to demangle the result of jau::type_name() or jau::type_info::name() if jau::type_info::rtti_available == true,
259 * i.e. RTTI typeif(T) symbols are being used.
260 *
261 * See also [gcc libstdc++ FAQ, Chapter 28](https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html).
262 *
263 * Further, implementation also checks whether the mangled_name results from [jau::ctti_name<T>()](@ref ctti_name_type)
264 * and cleans up the known `gcc` and `clang` variant of JAU_PRETTY_FUNCTION.
265 *
266 * @param mangled_name mangled name
267 */
268 std::string demangle_name(const char* mangled_name) noexcept;
269
270 #if defined(__clang__)
271 /** Optional generic usage of final keyword w/o negative performance impact. (Disabled) */
272 #define final_opt
273 #elif defined(__GNUC__) && !defined(__clang__)
274 /** Optional generic usage of final keyword w/o negative performance impact. (Enabled) */
275 #define final_opt final
276 #elif defined(_MSC_VER)
277 /** Optional generic usage of final keyword w/o negative performance impact. (Enabled, OK?) */
278 #define final_opt final
279 #else
280 /** Optional generic usage of final keyword w/o negative performance impact. (Enabled, OK?) */
281 #define final_opt final
282 #endif
283
284 /**
285 // *************************************************
286 // *************************************************
287 // *************************************************
288 */
289
290 /**
291 * Convenience type trait for `__has_builtin(__builtin_bit_cast)`.
292 * @tparam Dummy_type just to make template `SFINAE` happy
293 * @see jau::has_builtin_bit_cast()
294 * @see jau::bit_cast()
295 * @see jau::pointer_cast()
296 */
297 template <typename Dummy_type>
299 #if defined __has_builtin && __has_builtin(__builtin_bit_cast)
300 : std::true_type
301 #else
302 : std::false_type
303 #endif
304 {};
305 /**
306 * Value access of has_builtin_bit_cast type trait for convenience ..
307 * @tparam Dummy_type just to make template `SFINAE` happy
308 * @see has_builtin_bit_cast
309 */
310 template <typename Dummy_type> constexpr bool has_builtin_bit_cast_v = has_builtin_bit_cast_t<Dummy_type>::value;
311
312 /**
313 * Query whether `__builtin_bit_cast(Dest_type, arg)` is available
314 * via `__has_builtin(__builtin_bit_cast)`.
315 *
316 * - - - - - - - - - - - - - - -
317 *
318 * Availability of `__builtin_bit_cast(Dest_type, arg)`
319 *
320 * Reflecting my manual platform tests using `test_basictypeconv.cpp`
321 *
322 * Compiler | Version | Architecture | Available |
323 * :--------- | -------: | :------------------ | :-------- |
324 * GCC | 8.3.0 | amd64, arm64, arm32 | no |
325 * GCC | 10.2.1 | amd64 | no |
326 * GCC | 12.2.0 | amd64 | yes |
327 * clang | 9.0.1 | amd64, arm64 | yes |
328 * clang | 11.0.1 | amd64 | yes |
329 *
330 * @return `true` if query subject is available, otherwise not.
331 * @see has_builtin_bit_cast_t
332 * @see bit_cast()
333 * @see pointer_cast()
334 */
336 #if defined __has_builtin && __has_builtin(__builtin_bit_cast)
337 return true;
338 #else
339 return false;
340 #endif
341 }
342
343 /**
344 * A `constexpr` pointer cast implementation for C++17,
345 * inspired by C++20 `bit_cast<>(arg)`.
346 * <p>
347 * If is_builtin_bit_cast_available() evaluates `true`,
348 * implementation uses `__builtin_bit_cast(Dest, src)`.<br>
349 *
350 * Otherwise a simple `reinterpret_cast<Dest>(src)` is utilized,
351 * which officially is questionable to deliver a `constexpr`.
352 * </p>
353 * @tparam Dest the target pointer type
354 * @tparam Source the source pointer argument type
355 * @param src the pointer to convert to Dest pointer type
356 * @return the converted Dest pointer type value
357 * @see jau::has_builtin_bit_cast
358 * @see is_builtin_bit_cast_available()
359 * @see bit_cast()
360 */
361 template <class Dest, class Source>
362 constexpr
363 typename std::enable_if_t<
364 sizeof(Dest) == sizeof(Source) && // NOLINT(bugprone-sizeof-expression): Intended, same pointer size
365 std::is_pointer_v<Source> &&
366 std::is_pointer_v<Dest>,
367 Dest>
368 pointer_cast(const Source& src) noexcept
369 {
370 if constexpr ( is_cxx20() ) {
371 return std::bit_cast<Dest, Source>(src);
372 } else if constexpr ( has_builtin_bit_cast() ) {
373 return __builtin_bit_cast(Dest, src);
374 } else {
375 // not 'really' constexpr .. oops, working though
376 return reinterpret_cast<Dest>( const_cast< std::remove_const_t< std::remove_pointer_t<Source> >* >( src ) );
377 }
378 }
379
380 /**
381 * C++20 `bit_cast<>(arg)` implementation for C++17.
382 * <p>
383 * Utilizing native bit_cast if is_builtin_bit_cast_available(), otherwise `pointer_cast<const packed_t<Dest>*>( &src )->store`.
384 * </p>
385 * @tparam Dest the target type
386 * @tparam Source the source argument type
387 * @param src the value to convert to Dest type
388 * @return the converted Dest type value
389 * @see jau::has_builtin_bit_cast
390 * @see is_builtin_bit_cast_available()
391 * @see pointer_cast()
392 */
393 template <class Dest, class Source>
394 constexpr
395 typename std::enable_if_t<
396 sizeof(Dest) == sizeof(Source) &&
397 std::is_trivially_copyable_v<Dest> &&
398 std::is_trivially_copyable_v<Source>,
399 Dest>
400 bit_cast(const Source& src) noexcept
401 {
402 if constexpr ( is_cxx20() ) {
403 return std::bit_cast<Dest, Source>(src);
404 } else if constexpr ( has_builtin_bit_cast() ) {
405 return __builtin_bit_cast(Dest, src);
406 } else {
407 return pointer_cast<const packed_t<Dest>*>( &src )->store;
408 }
409 }
410
412 #if defined(__SIZEOF_INT128__)
413 return true;
414 #else
415 return false;
416 #endif
417 }
418
419 #if defined(__SIZEOF_INT128__)
420 // Prefer TI mode over __int128 as GCC rejects the latter in pendantic mode
421 #if defined(__GNUG__)
422 typedef int int128_t __attribute__((mode(TI)));
423 typedef unsigned int uint128_t __attribute__((mode(TI)));
424 #else
425 typedef __int128 int128_t;
426 typedef unsigned __int128 uint128_t;
427 #endif
428 #endif
429
430 /** Returns true if compiled with debug information and w/o optimization, i.e. not `defined(NDEBUG) && !defined(DEBUG)`. */
432 #if defined(NDEBUG) && !defined(DEBUG)
433 return false;
434 #else
435 return true;
436 #endif
437 }
438
439 #if defined(__clang__)
440 #define __attrdecl_no_optimize__ __attribute__ ((optnone))
441 #define __attrdef_no_optimize__ __attribute__ ((optnone))
442 #elif defined(__GNUC__) && !defined(__clang__)
443 #define __attrdecl_no_optimize__ __attribute__((optimize("O0")))
444 // #define __attrdecl_no_optimize__ [[gnu::optimize("O0")]]
445 #define __attrdef_no_optimize__
446 #else
447 #define __attrdecl_no_optimize__
448 #define __attrdef_no_optimize__
449 #endif
450
451 /**
452 * Simple unary function wrapper which ensures function call to happen in order and not optimized away.
453 */
454 template <typename UnaryFunc>
456 // asm asm-qualifiers ( AssemblerTemplate : OutputOperands [ : InputOperands [ : Clobbers ] ] )
457 asm volatile("" : "+r,m"(f) : : "memory"); // a nop asm, usually guaranteeing synchronized order and non-optimization
458 f();
459 }
460
461 /// Boolean type without implicit conversion, safe for function parameter
462 enum class Bool : bool {
463 False = false,
464 True = true
465 };
466 constexpr Bool True() noexcept { return Bool::True; }
467 constexpr Bool False() noexcept { return Bool::False; }
468 constexpr Bool makeBool(bool v) noexcept { return v ? Bool::True : Bool::False; }
469
470 constexpr bool value(const Bool rhs) noexcept {
471 return static_cast<bool>(rhs);
472 }
473 constexpr bool operator*(const Bool rhs) noexcept {
474 return static_cast<bool>(rhs);
475 }
476 constexpr Bool operator!(const Bool rhs) noexcept {
477 return Bool(!*rhs);
478 }
479 constexpr Bool operator&&(const Bool lhs, const Bool rhs) noexcept {
480 return Bool(*lhs && *rhs);
481 }
482 constexpr Bool operator||(const Bool lhs, const Bool rhs) noexcept {
483 return Bool(*lhs || *rhs);
484 }
485 constexpr Bool operator^(const Bool lhs, const Bool rhs) noexcept {
486 return Bool(*lhs ^ *rhs);
487 }
488 constexpr Bool operator|(const Bool lhs, const Bool rhs) noexcept {
489 return Bool(*lhs || *rhs);
490 }
491 constexpr Bool operator&(const Bool lhs, const Bool rhs) noexcept {
492 return Bool(*lhs && *rhs);
493 }
494 constexpr Bool& operator|=(Bool& lhs, const Bool rhs) noexcept {
495 lhs = lhs | rhs;
496 return lhs;
497 }
498 constexpr Bool& operator&=(Bool& lhs, const Bool rhs) noexcept {
499 lhs = lhs & rhs;
500 return lhs;
501 }
502 constexpr Bool& operator^=(Bool& lhs, const Bool rhs) noexcept {
503 lhs = lhs ^ rhs;
504 return lhs;
505 }
506 constexpr bool operator==(const Bool lhs, const Bool rhs) noexcept {
507 return *lhs == *rhs;
508 }
509 constexpr std::string_view name(const Bool v) noexcept {
510 if( *v ) {
511 return "true";
512 } else {
513 return "false";
514 }
515 }
516 constexpr std::string to_string(const Bool v) noexcept { return std::string(name(v)); }
517 inline std::ostream & operator << (std::ostream &out, const Bool c) {
518 out << to_string(c);
519 return out;
520 }
521
522 //
523 //
524 //
525
526 /** Simple pre-defined value pair [size_t, bool] for structured bindings to multi-values. */
528 /** a size_t value, e.g. index, length, etc */
529 size_t s;
530 /** a boolean value, e.g. success, etc */
531 bool b;
532 };
533
534 /** Simple pre-defined value tuple [uint64_t, size_t, bool] for structured bindings to multi-values. */
536 /** a uint64_t value, e.g. compute result value, etc */
537 uint64_t v;
538 /** a size_t value, e.g. index, length, etc */
539 size_t s;
540 /** a boolean value, e.g. success, etc */
541 bool b;
542 };
543
544 /** Simple pre-defined value tuple [int64_t, size_t, bool] for structured bindings to multi-values. */
546 /** a int64_t value, e.g. compute result value, etc */
547 int64_t v;
548 /** a size_t value, e.g. index, length, etc */
549 size_t s;
550 /** a boolean value, e.g. success, etc */
551 bool b;
552 };
553
554 //
555 //
556 //
557
558 namespace impl {
559 inline bool runtime_eval(bool v) { return v; }
560 }
561
563 [[maybe_unused]] bool r = v ? true : impl::runtime_eval(v);
564 }
565
566 /**@}*/
567
568} // namespace jau
569
570/** \addtogroup CppLang
571 *
572 * @{
573 */
574
575#define E_FILE_LINE __FILE__, __LINE__
576
577//
578// JAU_FOR_EACH macros inspired by David Mazières, June 2021
579// <https://www.scs.stanford.edu/~dm/blog/va-opt.html>
580//
581// All hacks below to circumvent lack of C++26 reflection.
582//
583
584// Note space before (), so object-like macro
585#define JAU_PARENS ()
586
587#define JAU_EXPAND(...) JAU_EXPAND4(JAU_EXPAND4(JAU_EXPAND4(JAU_EXPAND4(__VA_ARGS__))))
588#define JAU_EXPAND4(...) JAU_EXPAND3(JAU_EXPAND3(JAU_EXPAND3(JAU_EXPAND3(__VA_ARGS__))))
589#define JAU_EXPAND3(...) JAU_EXPAND2(JAU_EXPAND2(JAU_EXPAND2(JAU_EXPAND2(__VA_ARGS__))))
590#define JAU_EXPAND2(...) JAU_EXPAND1(JAU_EXPAND1(JAU_EXPAND1(JAU_EXPAND1(__VA_ARGS__))))
591#define JAU_EXPAND1(...) __VA_ARGS__
592
593// Macro w/ 1 arguments
594
595#define JAU_FOR_EACH1_LIST(macro, ...) \
596 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH1_LIST_HELPER(macro, __VA_ARGS__)))
597#define JAU_FOR_EACH1_LIST_HELPER(macro, a1, ...) \
598 macro(a1) \
599 __VA_OPT__(, JAU_FOR_EACH1_LIST_AGAIN JAU_PARENS (macro, __VA_ARGS__))
600#define JAU_FOR_EACH1_LIST_AGAIN() JAU_FOR_EACH1_LIST_HELPER
601
602#define JAU_DECLTYPE_VALUE(type) decltype(type)
603
604// Macro w/ 2 arguments
605
606#define JAU_FOR_EACH2(macro, type, ...) \
607 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH2_HELPER(macro, type, __VA_ARGS__)))
608#define JAU_FOR_EACH2_HELPER(macro, type, a1, ...) \
609 macro(type, a1) \
610 __VA_OPT__(JAU_FOR_EACH2_AGAIN JAU_PARENS (macro, type, __VA_ARGS__))
611#define JAU_FOR_EACH2_AGAIN() JAU_FOR_EACH2_HELPER
612
613#define JAU_FOR_EACH2_LIST(macro, type, ...) \
614 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH2_LIST_HELPER(macro, type, __VA_ARGS__)))
615#define JAU_FOR_EACH2_LIST_HELPER(macro, type, a1, ...) \
616 macro(type, a1) \
617 __VA_OPT__(, JAU_FOR_EACH2_LIST_AGAIN JAU_PARENS (macro, type, __VA_ARGS__))
618#define JAU_FOR_EACH2_LIST_AGAIN() JAU_FOR_EACH2_LIST_HELPER
619
620#define JAU_FOR_EACH2_VALUE(macro, type, value, ...) \
621 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH2_VALUE_HELPER(macro, type, value, __VA_ARGS__)))
622#define JAU_FOR_EACH2_VALUE_HELPER(macro, type, value, a1, ...) \
623 macro(type, a1, value) \
624 __VA_OPT__(JAU_FOR_EACH2_VALUE_AGAIN JAU_PARENS (macro, type, value, __VA_ARGS__))
625#define JAU_FOR_EACH2_VALUE_AGAIN() JAU_FOR_EACH2_VALUE_HELPER
626
627/**@}*/
628
629#endif /* JAU_CPP_LANG_EXT_HPP_ */
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
std::ostream & operator<<(std::ostream &out, const bitfield_t< StorageType, BitSize > &v)
Definition bitfield.hpp:486
consteval_cxx20 bool is_builtin_int128_available() noexcept
constexpr bool value(const Bool rhs) noexcept
constexpr bool operator*(const Bool rhs) noexcept
constexpr Bool & operator&=(Bool &lhs, const Bool rhs) noexcept
constexpr Bool makeBool(bool v) noexcept
constexpr Bool & operator^=(Bool &lhs, const Bool rhs) noexcept
consteval_cxx20 bool is_cxx23() noexcept
Returns true if compiled with >= C++23.
void callNotOptimize(UnaryFunc f) __attrdef_no_optimize__
Simple unary function wrapper which ensures function call to happen in order and not optimized away.
consteval_cxx20 bool is_cxx20() noexcept
Returns true if compiled with >= C++20.
constexpr bool has_builtin_bit_cast_v
Value access of has_builtin_bit_cast type trait for convenience .
constexpr Bool False() noexcept
constexpr Bool operator^(const Bool lhs, const Bool rhs) noexcept
consteval_cxx20 bool is_cxx17() noexcept
Returns true if compiled with >= C++17.
constexpr Bool operator|(const Bool lhs, const Bool rhs) noexcept
constexpr Bool True() noexcept
constexpr std::enable_if_t< sizeof(Dest)==sizeof(Source) &&std::is_trivially_copyable_v< Dest > &&std::is_trivially_copyable_v< Source >, Dest > bit_cast(const Source &src) noexcept
C++20 bit_cast<>(arg) implementation for C++17.
consteval_cxx20 bool is_debug_enabled() noexcept
Returns true if compiled with debug information and w/o optimization, i.e.
constexpr Bool operator&(const Bool lhs, const Bool rhs) noexcept
constexpr Bool operator&&(const Bool lhs, const Bool rhs) noexcept
constexpr Bool & operator|=(Bool &lhs, const Bool rhs) noexcept
consteval_cxx20 bool has_builtin_bit_cast() noexcept
Query whether __builtin_bit_cast(Dest_type, arg) is available via __has_builtin(__builtin_bit_cast).
constexpr std::enable_if_t< sizeof(Dest)==sizeof(Source) &&std::is_pointer_v< Source > &&std::is_pointer_v< Dest >, Dest > pointer_cast(const Source &src) noexcept
A constexpr pointer cast implementation for C++17, inspired by C++20 bit_cast<>(arg).
consteval_cxx20 void consteval_assert(bool v)
constexpr Bool operator||(const Bool lhs, const Bool rhs) noexcept
std::string demangle_name(const char *mangled_name) noexcept
Returns the demangled given mangled_name if successful, otherwise the mangled_name.
Definition debug.cpp:59
#define __attrdef_no_optimize__
constexpr std::string_view name(const Bool v) noexcept
constexpr Bool operator!(const Bool rhs) noexcept
#define consteval_cxx20
consteval qualifier replacement for C++20 consteval.
consteval_cxx20 bool is_cxx26() noexcept
Returns true if compiled with >= C++26.
Bool
Boolean type without implicit conversion, safe for function parameter.
bool runtime_eval(bool v)
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition backtrace.hpp:32
bool operator==(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
STL namespace.
Simple pre-defined value tuple [int64_t, size_t, bool] for structured bindings to multi-values.
size_t s
a size_t value, e.g.
bool b
a boolean value, e.g.
int64_t v
a int64_t value, e.g.
Simple pre-defined value pair [size_t, bool] for structured bindings to multi-values.
size_t s
a size_t value, e.g.
bool b
a boolean value, e.g.
Simple pre-defined value tuple [uint64_t, size_t, bool] for structured bindings to multi-values.
bool b
a boolean value, e.g.
uint64_t v
a uint64_t value, e.g.
size_t s
a size_t value, e.g.
Convenience type trait for __has_builtin(__builtin_bit_cast).
static std::string f(uint32_t v)