Skip to content

Commit ce493dd

Browse files
committed
Add MSVC support by using a DEFER macro and increasing the evaluation depth.
1 parent 033a3e7 commit ce493dd

File tree

2 files changed

+33
-21
lines changed

2 files changed

+33
-21
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ MAP_LIST_UD(f,x,a,b,c) | f(a,x), f(b,x), f(c,x)
147147
MAP_UD_I(f,x,a,b,c) | f(a,x,0) f(b,x,1) f(c,x,2)
148148
MAP_LIST_UD_I(f,x,a,b,c) | f(a,x,0), f(b,x,1), f(c,x,2)
149149
150+
The maximum number of variadic arguments for all macros is 365.
151+
150152
## See Also
151153
152154
C++ users may be intersted in the ['visit_struct' library](https://github.com/cbeck88/visit_struct),

map.h

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,50 @@
1313
#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
1414
#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
1515
#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
16-
#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
16+
#define EVAL5(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
17+
18+
#ifdef _MSC_VER
19+
// MSVC needs more evaluations
20+
#define EVAL6(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
21+
#define EVAL(...) EVAL6(EVAL6(__VA_ARGS__))
22+
#else
23+
#define EVAL(...) EVAL5(__VA_ARGS__)
24+
#endif
1725

1826
#define MAP_END(...)
1927
#define MAP_OUT
20-
#define MAP_COMMA ,
28+
29+
#define EMPTY()
30+
#define DEFER(id) id EMPTY()
2131

2232
#define MAP_GET_END2() 0, MAP_END
2333
#define MAP_GET_END1(...) MAP_GET_END2
2434
#define MAP_GET_END(...) MAP_GET_END1
2535
#define MAP_NEXT0(test, next, ...) next MAP_OUT
26-
#define MAP_NEXT1(test, next) MAP_NEXT0(test, next, 0)
36+
#define MAP_NEXT1(test, next) DEFER ( MAP_NEXT0 ) ( test, next, 0)
2737
#define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next)
2838
#define MAP_INC(X) MAP_INC_ ## X
2939

30-
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP1)(f, peek, __VA_ARGS__)
31-
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP0)(f, peek, __VA_ARGS__)
32-
33-
#define MAP0_UD(f, userdata, x, peek, ...) f(x,userdata) MAP_NEXT(peek, MAP1_UD)(f, userdata, peek, __VA_ARGS__)
34-
#define MAP1_UD(f, userdata, x, peek, ...) f(x,userdata) MAP_NEXT(peek, MAP0_UD)(f, userdata, peek, __VA_ARGS__)
40+
#define MAP0(f, x, peek, ...) f(x) DEFER ( MAP_NEXT(peek, MAP1) ) ( f, peek, __VA_ARGS__ )
41+
#define MAP1(f, x, peek, ...) f(x) DEFER ( MAP_NEXT(peek, MAP0) ) ( f, peek, __VA_ARGS__ )
3542

36-
#define MAP0_UD_I(f, userdata, index, x, peek, ...) f(x,userdata,index) MAP_NEXT(peek, MAP1_UD_I)(f, userdata, MAP_INC(index), peek, __VA_ARGS__)
37-
#define MAP1_UD_I(f, userdata, index, x, peek, ...) f(x,userdata,index) MAP_NEXT(peek, MAP0_UD_I)(f, userdata, MAP_INC(index), peek, __VA_ARGS__)
43+
#define MAP0_UD(f, userdata, x, peek, ...) f(x,userdata) DEFER ( MAP_NEXT(peek, MAP1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
44+
#define MAP1_UD(f, userdata, x, peek, ...) f(x,userdata) DEFER ( MAP_NEXT(peek, MAP0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
3845

39-
#define MAP_LIST_NEXT1(test, next) MAP_NEXT0(test, MAP_COMMA next, 0)
40-
#define MAP_LIST_NEXT(test, next) MAP_LIST_NEXT1(MAP_GET_END test, next)
46+
#define MAP0_UD_I(f, userdata, index, x, peek, ...) f(x,userdata,index) DEFER ( MAP_NEXT(peek, MAP1_UD_I) ) ( f, userdata, MAP_INC(index), peek, __VA_ARGS__ )
47+
#define MAP1_UD_I(f, userdata, index, x, peek, ...) f(x,userdata,index) DEFER ( MAP_NEXT(peek, MAP0_UD_I) ) ( f, userdata, MAP_INC(index), peek, __VA_ARGS__ )
4148

42-
#define MAP_LIST0(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST1)(f, peek, __VA_ARGS__)
43-
#define MAP_LIST1(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST0)(f, peek, __VA_ARGS__)
49+
#define MAP_LIST0(f, x, peek, ...) , f(x) DEFER ( MAP_NEXT(peek, MAP_LIST1) ) ( f, peek, __VA_ARGS__ )
50+
#define MAP_LIST1(f, x, peek, ...) , f(x) DEFER ( MAP_NEXT(peek, MAP_LIST0) ) ( f, peek, __VA_ARGS__ )
51+
#define MAP_LIST2(f, x, peek, ...) f(x) DEFER ( MAP_NEXT(peek, MAP_LIST1) ) ( f, peek, __VA_ARGS__ )
4452

45-
#define MAP_LIST0_UD(f, userdata, x, peek, ...) f(x, userdata) MAP_LIST_NEXT(peek, MAP_LIST1_UD)(f, userdata, peek, __VA_ARGS__)
46-
#define MAP_LIST1_UD(f, userdata, x, peek, ...) f(x, userdata) MAP_LIST_NEXT(peek, MAP_LIST0_UD)(f, userdata, peek, __VA_ARGS__)
53+
#define MAP_LIST0_UD(f, userdata, x, peek, ...) , f(x, userdata) DEFER ( MAP_NEXT(peek, MAP_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
54+
#define MAP_LIST1_UD(f, userdata, x, peek, ...) , f(x, userdata) DEFER ( MAP_NEXT(peek, MAP_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
55+
#define MAP_LIST2_UD(f, userdata, x, peek, ...) f(x, userdata) DEFER ( MAP_NEXT(peek, MAP_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
4756

48-
#define MAP_LIST0_UD_I(f, userdata, index, x, peek, ...) f(x, userdata, index) MAP_LIST_NEXT(peek, MAP_LIST1_UD_I)(f, userdata, MAP_INC(index), peek, __VA_ARGS__)
49-
#define MAP_LIST1_UD_I(f, userdata, index, x, peek, ...) f(x, userdata, index) MAP_LIST_NEXT(peek, MAP_LIST0_UD_I)(f, userdata, MAP_INC(index), peek, __VA_ARGS__)
57+
#define MAP_LIST0_UD_I(f, userdata, index, x, peek, ...) , f(x, userdata, index) DEFER ( MAP_NEXT(peek, MAP_LIST1_UD_I) ) ( f, userdata, MAP_INC(index), peek, __VA_ARGS__ )
58+
#define MAP_LIST1_UD_I(f, userdata, index, x, peek, ...) , f(x, userdata, index) DEFER ( MAP_NEXT(peek, MAP_LIST0_UD_I) ) ( f, userdata, MAP_INC(index), peek, __VA_ARGS__ )
59+
#define MAP_LIST2_UD_I(f, userdata, index, x, peek, ...) f(x, userdata, index) DEFER ( MAP_NEXT(peek, MAP_LIST0_UD_I) ) ( f, userdata, MAP_INC(index), peek, __VA_ARGS__ )
5060

5161
/**
5262
* Applies the function macro `f` to each of the remaining parameters.
@@ -57,7 +67,7 @@
5767
* Applies the function macro `f` to each of the remaining parameters and
5868
* inserts commas between the results.
5969
*/
60-
#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
70+
#define MAP_LIST(f, ...) EVAL(MAP_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
6171

6272
/**
6373
* Applies the function macro `f` to each of the remaining parameters and passes userdata as the second parameter to each invocation,
@@ -70,7 +80,7 @@
7080
* and passes userdata as the second parameter to each invocation,
7181
* e.g. MAP_LIST_UD(f, x, a, b, c) evaluates to f(a, x), f(b, x), f(c, x)
7282
*/
73-
#define MAP_LIST_UD(f, userdata, ...) EVAL(MAP_LIST1_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
83+
#define MAP_LIST_UD(f, userdata, ...) EVAL(MAP_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
7484

7585
/**
7686
* Applies the function macro `f` to each of the remaining parameters, passes userdata as the second parameter to each invocation,
@@ -84,7 +94,7 @@
8494
* passes userdata as the second parameter to each invocation, and the index of the invocation as the third parameter,
8595
* e.g. MAP_LIST_UD_I(f, x, a, b, c) evaluates to f(a, x, 0), f(b, x, 1), f(c, x, 2)
8696
*/
87-
#define MAP_LIST_UD_I(f, userdata, ...) EVAL(MAP_LIST1_UD_I(f, userdata, 0, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
97+
#define MAP_LIST_UD_I(f, userdata, ...) EVAL(MAP_LIST2_UD_I(f, userdata, 0, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
8898

8999
/*
90100
* Because the preprocessor can't do arithmetic that produces integer literals for the *_I macros, we have to do it manually.

0 commit comments

Comments
 (0)