Created
September 14, 2019 02:15
-
-
Save christophercrouzet/403548e3f703425c5bcc235d23bdbb7b to your computer and use it in GitHub Desktop.
Counting Variadic Macro Arguments in C99 and C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Credits: Jens Gustedt | |
https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments | |
*/ | |
#include <stdio.h> | |
#define EXPAND(x) x | |
#define CONCAT_(a, b) a##b | |
#define CONCAT(a, b) CONCAT_(a, b) | |
#define IF_0(t, f) f | |
#define IF_1(t, f) t | |
#define IF(x, t, f) CONCAT(IF_, x)(t, f) | |
#define ARG( \ | |
_0, _1, _2, _3, _4, _5, _6, _7, \ | |
_8, _9, _10, _11, _12, _13, _14, _15, \ | |
_16, _17, _18, _19, _20, _21, _22, _23, \ | |
_24, _25, _26, _27, _28, _29, _30, _31, \ | |
_32, _33, _34, _35, _36, _37, _38, _39, \ | |
_40, _41, _42, _43, _44, _45, _46, _47, \ | |
_48, _49, _50, _51, _52, _53, _54, _55, \ | |
_56, _57, _58, _59, _60, _61, _62, _63, \ | |
_64, ...) _64 | |
#define IS_EMPTY_TRIGGER(...) , | |
#define IS_EMPTY_HAS_COMMA(...) \ | |
EXPAND(ARG( \ | |
__VA_ARGS__, \ | |
1, 1, 1, 1, 1, 1, 1, 1, \ | |
1, 1, 1, 1, 1, 1, 1, 1, \ | |
1, 1, 1, 1, 1, 1, 1, 1, \ | |
1, 1, 1, 1, 1, 1, 1, 1, \ | |
1, 1, 1, 1, 1, 1, 1, 1, \ | |
1, 1, 1, 1, 1, 1, 1, 1, \ | |
1, 1, 1, 1, 1, 1, 1, 1, \ | |
1, 1, 1, 1, 1, 1, 1, 0)) | |
#define IS_EMPTY_PASTE(_0, _1, _2, _3, _4) _0##_1##_2##_3##_4 | |
#define IS_EMPTY_0000 0 | |
#define IS_EMPTY_0001 1 | |
#define IS_EMPTY_0010 0 | |
#define IS_EMPTY_0011 0 | |
#define IS_EMPTY_0100 0 | |
#define IS_EMPTY_0101 0 | |
#define IS_EMPTY_0110 0 | |
#define IS_EMPTY_0111 0 | |
#define IS_EMPTY_1000 0 | |
#define IS_EMPTY_1001 0 | |
#define IS_EMPTY_1010 0 | |
#define IS_EMPTY_1011 0 | |
#define IS_EMPTY_1100 0 | |
#define IS_EMPTY_1101 0 | |
#define IS_EMPTY_1110 0 | |
#define IS_EMPTY_1111 0 | |
#define IS_EMPTY_(_0, _1, _2, _3) \ | |
IS_EMPTY_PASTE(IS_EMPTY_, _0, _1, _2, _3) | |
#define IS_EMPTY(...) \ | |
IS_EMPTY_( \ | |
IS_EMPTY_HAS_COMMA(__VA_ARGS__), \ | |
IS_EMPTY_HAS_COMMA(IS_EMPTY_TRIGGER __VA_ARGS__), \ | |
IS_EMPTY_HAS_COMMA(__VA_ARGS__ ()), \ | |
IS_EMPTY_HAS_COMMA(IS_EMPTY_TRIGGER __VA_ARGS__ ())) | |
#define COUNT_ARGS_(...) \ | |
EXPAND(ARG( \ | |
__VA_ARGS__, \ | |
64, 63, 62, 61, 60, 59, 58, 57, \ | |
56, 55, 54, 53, 52, 51, 50, 49, \ | |
48, 47, 46, 45, 44, 43, 42, 41, \ | |
40, 39, 38, 37, 36, 35, 34, 33, \ | |
32, 31, 30, 29, 28, 27, 26, 25, \ | |
24, 23, 22, 21, 20, 19, 18, 17, \ | |
16, 15, 14, 13, 12, 11, 10, 9, \ | |
8, 7, 6, 5, 4, 3, 2, 1, \ | |
0)) | |
#define COUNT_ARGS(...) \ | |
IF(IS_EMPTY(__VA_ARGS__), 0, COUNT_ARGS_(__VA_ARGS__)) | |
static const int count_0 = COUNT_ARGS(); | |
static const int count_1 = COUNT_ARGS(a); | |
static const int count_8 = COUNT_ARGS(a, b, c, d, e, f, g, h); | |
int | |
main(void) | |
{ | |
printf("count_0: %d\n", count_0); | |
printf("count_1: %d\n", count_1); | |
printf("count_8: %d\n", count_8); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment