preprocessor.hpp (6579B)
1 #ifndef _C4_PREPROCESSOR_HPP_ 2 #define _C4_PREPROCESSOR_HPP_ 3 4 /** @file preprocessor.hpp Contains basic macros and preprocessor utilities. 5 * @ingroup basic_headers */ 6 7 #ifdef __clang__ 8 /* NOTE: using , ## __VA_ARGS__ to deal with zero-args calls to 9 * variadic macros is not portable, but works in clang, gcc, msvc, icc. 10 * clang requires switching off compiler warnings for pedantic mode. 11 * @see http://stackoverflow.com/questions/32047685/variadic-macro-without-arguments */ 12 # pragma clang diagnostic push 13 # pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" // warning: token pasting of ',' and __VA_ARGS__ is a GNU extension 14 #elif defined(__GNUC__) 15 /* GCC also issues a warning for zero-args calls to variadic macros. 16 * This warning is switched on with -pedantic and apparently there is no 17 * easy way to turn it off as with clang. But marking this as a system 18 * header works. 19 * @see https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html 20 * @see http://stackoverflow.com/questions/35587137/ */ 21 # pragma GCC system_header 22 #endif 23 24 #define C4_WIDEN(str) L"" str 25 26 #define C4_COUNTOF(arr) (sizeof(arr)/sizeof((arr)[0])) 27 28 #define C4_EXPAND(arg) arg 29 30 /** useful in some macro calls with template arguments */ 31 #define C4_COMMA , 32 /** useful in some macro calls with template arguments 33 * @see C4_COMMA */ 34 #define C4_COMMA_X C4_COMMA 35 36 /** expand and quote */ 37 #define C4_XQUOTE(arg) _C4_XQUOTE(arg) 38 #define _C4_XQUOTE(arg) C4_QUOTE(arg) 39 #define C4_QUOTE(arg) #arg 40 41 /** expand and concatenate */ 42 #define C4_XCAT(arg1, arg2) _C4_XCAT(arg1, arg2) 43 #define _C4_XCAT(arg1, arg2) C4_CAT(arg1, arg2) 44 #define C4_CAT(arg1, arg2) arg1##arg2 45 46 #define C4_VERSION_CAT(major, minor, patch) ((major)*10000 + (minor)*100 + (patch)) 47 48 /** A preprocessor foreach. Spectacular trick taken from: 49 * http://stackoverflow.com/a/1872506/5875572 50 * The first argument is for a macro receiving a single argument, 51 * which will be called with every subsequent argument. There is 52 * currently a limit of 32 arguments, and at least 1 must be provided. 53 * 54 Example: 55 @code{.cpp} 56 struct Example { 57 int a; 58 int b; 59 int c; 60 }; 61 // define a one-arg macro to be called 62 #define PRN_STRUCT_OFFSETS(field) PRN_STRUCT_OFFSETS_(Example, field) 63 #define PRN_STRUCT_OFFSETS_(structure, field) printf(C4_XQUOTE(structure) ":" C4_XQUOTE(field)" - offset=%zu\n", offsetof(structure, field)); 64 65 // now call the macro for a, b and c 66 C4_FOR_EACH(PRN_STRUCT_OFFSETS, a, b, c); 67 @endcode */ 68 #define C4_FOR_EACH(what, ...) C4_FOR_EACH_SEP(what, ;, __VA_ARGS__) 69 70 /** same as C4_FOR_EACH(), but use a custom separator between statements. 71 * If a comma is needed as the separator, use the C4_COMMA macro. 72 * @see C4_FOR_EACH 73 * @see C4_COMMA 74 */ 75 #define C4_FOR_EACH_SEP(what, sep, ...) _C4_FOR_EACH_(_C4_FOR_EACH_NARG(__VA_ARGS__), what, sep, __VA_ARGS__) 76 77 /// @cond dev 78 79 #define _C4_FOR_EACH_01(what, sep, x) what(x) sep 80 #define _C4_FOR_EACH_02(what, sep, x, ...) what(x) sep _C4_FOR_EACH_01(what, sep, __VA_ARGS__) 81 #define _C4_FOR_EACH_03(what, sep, x, ...) what(x) sep _C4_FOR_EACH_02(what, sep, __VA_ARGS__) 82 #define _C4_FOR_EACH_04(what, sep, x, ...) what(x) sep _C4_FOR_EACH_03(what, sep, __VA_ARGS__) 83 #define _C4_FOR_EACH_05(what, sep, x, ...) what(x) sep _C4_FOR_EACH_04(what, sep, __VA_ARGS__) 84 #define _C4_FOR_EACH_06(what, sep, x, ...) what(x) sep _C4_FOR_EACH_05(what, sep, __VA_ARGS__) 85 #define _C4_FOR_EACH_07(what, sep, x, ...) what(x) sep _C4_FOR_EACH_06(what, sep, __VA_ARGS__) 86 #define _C4_FOR_EACH_08(what, sep, x, ...) what(x) sep _C4_FOR_EACH_07(what, sep, __VA_ARGS__) 87 #define _C4_FOR_EACH_09(what, sep, x, ...) what(x) sep _C4_FOR_EACH_08(what, sep, __VA_ARGS__) 88 #define _C4_FOR_EACH_10(what, sep, x, ...) what(x) sep _C4_FOR_EACH_09(what, sep, __VA_ARGS__) 89 #define _C4_FOR_EACH_11(what, sep, x, ...) what(x) sep _C4_FOR_EACH_10(what, sep, __VA_ARGS__) 90 #define _C4_FOR_EACH_12(what, sep, x, ...) what(x) sep _C4_FOR_EACH_11(what, sep, __VA_ARGS__) 91 #define _C4_FOR_EACH_13(what, sep, x, ...) what(x) sep _C4_FOR_EACH_12(what, sep, __VA_ARGS__) 92 #define _C4_FOR_EACH_14(what, sep, x, ...) what(x) sep _C4_FOR_EACH_13(what, sep, __VA_ARGS__) 93 #define _C4_FOR_EACH_15(what, sep, x, ...) what(x) sep _C4_FOR_EACH_14(what, sep, __VA_ARGS__) 94 #define _C4_FOR_EACH_16(what, sep, x, ...) what(x) sep _C4_FOR_EACH_15(what, sep, __VA_ARGS__) 95 #define _C4_FOR_EACH_17(what, sep, x, ...) what(x) sep _C4_FOR_EACH_16(what, sep, __VA_ARGS__) 96 #define _C4_FOR_EACH_18(what, sep, x, ...) what(x) sep _C4_FOR_EACH_17(what, sep, __VA_ARGS__) 97 #define _C4_FOR_EACH_19(what, sep, x, ...) what(x) sep _C4_FOR_EACH_18(what, sep, __VA_ARGS__) 98 #define _C4_FOR_EACH_20(what, sep, x, ...) what(x) sep _C4_FOR_EACH_19(what, sep, __VA_ARGS__) 99 #define _C4_FOR_EACH_21(what, sep, x, ...) what(x) sep _C4_FOR_EACH_20(what, sep, __VA_ARGS__) 100 #define _C4_FOR_EACH_22(what, sep, x, ...) what(x) sep _C4_FOR_EACH_21(what, sep, __VA_ARGS__) 101 #define _C4_FOR_EACH_23(what, sep, x, ...) what(x) sep _C4_FOR_EACH_22(what, sep, __VA_ARGS__) 102 #define _C4_FOR_EACH_24(what, sep, x, ...) what(x) sep _C4_FOR_EACH_23(what, sep, __VA_ARGS__) 103 #define _C4_FOR_EACH_25(what, sep, x, ...) what(x) sep _C4_FOR_EACH_24(what, sep, __VA_ARGS__) 104 #define _C4_FOR_EACH_26(what, sep, x, ...) what(x) sep _C4_FOR_EACH_25(what, sep, __VA_ARGS__) 105 #define _C4_FOR_EACH_27(what, sep, x, ...) what(x) sep _C4_FOR_EACH_26(what, sep, __VA_ARGS__) 106 #define _C4_FOR_EACH_28(what, sep, x, ...) what(x) sep _C4_FOR_EACH_27(what, sep, __VA_ARGS__) 107 #define _C4_FOR_EACH_29(what, sep, x, ...) what(x) sep _C4_FOR_EACH_28(what, sep, __VA_ARGS__) 108 #define _C4_FOR_EACH_30(what, sep, x, ...) what(x) sep _C4_FOR_EACH_29(what, sep, __VA_ARGS__) 109 #define _C4_FOR_EACH_31(what, sep, x, ...) what(x) sep _C4_FOR_EACH_30(what, sep, __VA_ARGS__) 110 #define _C4_FOR_EACH_32(what, sep, x, ...) what(x) sep _C4_FOR_EACH_31(what, sep, __VA_ARGS__) 111 #define _C4_FOR_EACH_NARG(...) _C4_FOR_EACH_NARG_(__VA_ARGS__, _C4_FOR_EACH_RSEQ_N()) 112 #define _C4_FOR_EACH_NARG_(...) _C4_FOR_EACH_ARG_N(__VA_ARGS__) 113 #define _C4_FOR_EACH_ARG_N(_01, _02, _03, _04, _05, _06, _07, _08, _09, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, N, ...) N 114 #define _C4_FOR_EACH_RSEQ_N() 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 09, 08, 07, 06, 05, 04, 03, 02, 01 115 #define _C4_FOR_EACH_(N, what, sep, ...) C4_XCAT(_C4_FOR_EACH_, N)(what, sep, __VA_ARGS__) 116 117 /// @endcond 118 119 #ifdef __clang__ 120 # pragma clang diagnostic pop 121 #endif 122 123 #endif /* _C4_PREPROCESSOR_HPP_ */