qxLib
apply.h
Go to the documentation of this file.
1 /**
2 
3  @file apply.h
4  @details Initially taken from https://github.com/swansontec/map-macro
5  @author Khrapov
6  @date 24.09.2023
7  @copyright © Nick Khrapov, 2023. All right reserved.
8 
9 **/
10 #pragma once
11 
12 #define _QX_APPLY_EVAL0(...) __VA_ARGS__
13 #define _QX_APPLY_EVAL1(...) _QX_APPLY_EVAL0(_QX_APPLY_EVAL0(_QX_APPLY_EVAL0(__VA_ARGS__)))
14 #define _QX_APPLY_EVAL2(...) _QX_APPLY_EVAL1(_QX_APPLY_EVAL1(_QX_APPLY_EVAL1(__VA_ARGS__)))
15 #define _QX_APPLY_EVAL3(...) _QX_APPLY_EVAL2(_QX_APPLY_EVAL2(_QX_APPLY_EVAL2(__VA_ARGS__)))
16 #define _QX_APPLY_EVAL4(...) _QX_APPLY_EVAL3(_QX_APPLY_EVAL3(_QX_APPLY_EVAL3(__VA_ARGS__)))
17 #define _QX_APPLY_EVAL5(...) _QX_APPLY_EVAL4(_QX_APPLY_EVAL4(_QX_APPLY_EVAL4(__VA_ARGS__)))
18 
19 #ifdef _MSC_VER
20  // MSVC needs more evaluations
21  #define _QX_APPLY_EVAL6(...) _QX_APPLY_EVAL5(_QX_APPLY_EVAL5(_QX_APPLY_EVAL5(__VA_ARGS__)))
22  #define _QX_APPLY_EVAL(...) _QX_APPLY_EVAL6(_QX_APPLY_EVAL6(__VA_ARGS__))
23 #else
24  #define _QX_APPLY_EVAL(...) _QX_APPLY_EVAL5(__VA_ARGS__)
25 #endif
26 
27 #define _QX_APPLY_MAP_END(...)
28 #define _QX_APPLY_MAP_OUT
29 
30 #define _QX_APPLY_EMPTY()
31 #define _QX_APPLY_DEFER(id) id _QX_APPLY_EMPTY()
32 
33 #define _QX_APPLY_MAP_GET_END2() 0, _QX_APPLY_MAP_END
34 #define _QX_APPLY_MAP_GET_END1(...) _QX_APPLY_MAP_GET_END2
35 #define _QX_APPLY_MAP_GET_END(...) _QX_APPLY_MAP_GET_END1
36 #define _QX_APPLY_MAP_NEXT0(test, next, ...) next _QX_APPLY_MAP_OUT
37 #define _QX_APPLY_MAP_NEXT1(test, next) _QX_APPLY_DEFER(_QX_APPLY_MAP_NEXT0)(test, next, 0)
38 #define _QX_APPLY_MAP_NEXT(test, next) _QX_APPLY_MAP_NEXT1(_QX_APPLY_MAP_GET_END test, next)
39 
40 #define _QX_APPLY_MAP_COMMA0(f, x, peek, ...) \
41  , f(x) _QX_APPLY_DEFER(_QX_APPLY_MAP_NEXT(peek, _QX_APPLY_MAP_COMMA1))(f, peek, __VA_ARGS__)
42 #define _QX_APPLY_MAP_COMMA1(f, x, peek, ...) \
43  , f(x) _QX_APPLY_DEFER(_QX_APPLY_MAP_NEXT(peek, _QX_APPLY_MAP_COMMA0))(f, peek, __VA_ARGS__)
44 #define _QX_APPLY_MAP_COMMA2(f, x, peek, ...) \
45  f(x) _QX_APPLY_DEFER(_QX_APPLY_MAP_NEXT(peek, _QX_APPLY_MAP_COMMA1))(f, peek, __VA_ARGS__)
46 
47 #define _QX_APPLY_MAP_SEMICOLON0(f, x, peek, ...) \
48  ; \
49  f(x) _QX_APPLY_DEFER(_QX_APPLY_MAP_NEXT(peek, _QX_APPLY_MAP_SEMICOLON1))(f, peek, __VA_ARGS__)
50 #define _QX_APPLY_MAP_SEMICOLON1(f, x, peek, ...) \
51  ; \
52  f(x) _QX_APPLY_DEFER(_QX_APPLY_MAP_NEXT(peek, _QX_APPLY_MAP_SEMICOLON0))(f, peek, __VA_ARGS__)
53 #define _QX_APPLY_MAP_SEMICOLON2(f, x, peek, ...) \
54  f(x) _QX_APPLY_DEFER(_QX_APPLY_MAP_NEXT(peek, _QX_APPLY_MAP_SEMICOLON1))(f, peek, __VA_ARGS__)
55 
56 /**
57  @def QX_APPLY_COMMA
58  @brief Applies the function macro `f` to each of the remaining parameters and inserts commas between the results:
59  QX_APPLY_SPACE(foo, 1, 2, 3) -> foo(1), foo(2), foo(3)
60  @param f - function macro
61  @param ... - parameters to apply
62 **/
63 #define QX_APPLY_COMMA(f, ...) _QX_APPLY_EVAL(_QX_APPLY_MAP_COMMA2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
64 
65 /**
66  @def QX_APPLY_SEMICOLON
67  @brief Applies the function macro `f` to each of the remaining parameters and inserts semicolons between the results:
68  QX_APPLY_SPACE(foo, 1, 2, 3) -> foo(1); foo(2); foo(3)
69  @param f - function macro
70  @param ... - parameters to apply
71 **/
72 #define QX_APPLY_SEMICOLON(f, ...) _QX_APPLY_EVAL(_QX_APPLY_MAP_SEMICOLON2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))