在MSVC 2010中映射宏

时间:2015-04-05 12:33:21

标签: c++ macros

我的代码来自https://github.com/swansontec/map-macro/blob/master/map.h

#define EVAL0(...) __VA_ARGS__
#define EVAL1(...) EVAL0 (EVAL0 (EVAL0 (__VA_ARGS__)))
#define EVAL2(...) EVAL1 (EVAL1 (EVAL1 (__VA_ARGS__)))
#define EVAL3(...) EVAL2 (EVAL2 (EVAL2 (__VA_ARGS__)))
#define EVAL4(...) EVAL3 (EVAL3 (EVAL3 (__VA_ARGS__)))
#define EVAL(...) EVAL4 (EVAL4 (EVAL4 (__VA_ARGS__)))
#define MAP_END(...)
#define MAP_OUT
#define MAP_GET_END() 0, MAP_END
#define MAP_NEXT0(test, next, ...) next MAP_OUT
#define MAP_NEXT1(test, next) MAP_NEXT0 (test, next, 0)
#define MAP_NEXT(test, next) MAP_NEXT1 (MAP_GET_END test, next)
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__)
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)
#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))

似乎这段代码工作得很好(在互联网上我找不到有关他的问题的信息),但在Microsoft Visual Studio 2010中,他没有编译,我不能参加MSVC 2013.代码:

MAP(printf, "a", "b"); // just for example

必须扩展为:

printf("a") printf("b") 

但它扩展为:

printf("a") printf("b") printf(()) printf(0)  hundreds of printf() 

有没有办法让这个宏工作正确?

P上。秒。抱歉英文不好

1 个答案:

答案 0 :(得分:1)

我做到了!有了疯狂的黑客,通过结合不同的技术,但它在Visual Studio 2010中工作。所以,主要代码:

// combine names
#define PLUS_TEXT_(x,y) x ## y
#define PLUS_TEXT(x, y) PLUS_TEXT_(x, y)

// receive args from VA_ARGS
#define ARG_1(_1, ...) _1
#define ARG_2(_1, _2, ...) _2
#define ARG_3(_1, _2, _3, ...) _3

#define ARG_40( _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, \
                ...) _39

// slice VA_ARGS
#define OTHER_1(_1, ...) __VA_ARGS__
#define OTHER_3(_1, _2, _3, ...) __VA_ARGS__

// hack for recursion in macro
#define EVAL0(...) __VA_ARGS__
#define EVAL1(...) EVAL0 (EVAL0 (EVAL0 (__VA_ARGS__)))
#define EVAL2(...) EVAL1 (EVAL1 (EVAL1 (__VA_ARGS__)))
#define EVAL3(...) EVAL2 (EVAL2 (EVAL2 (__VA_ARGS__)))
#define EVAL4(...) EVAL3 (EVAL3 (EVAL3 (__VA_ARGS__)))
#define EVAL(...) EVAL4 (EVAL4 (EVAL4 (__VA_ARGS__)))
// expand expressions
#define EXPAND(x) x

// "return" 2 if there are args, otherwise return 0
// for MAP it's ok that ignore first arg and no case with only one arg
// IMPORTANT! must call as MAP_SWITCH(0, __VA_ARGS__) for detection 0/1 arg case
#define MAP_SWITCH(...)\
    EXPAND(ARG_40(__VA_ARGS__, 2, 2, 2, 2, 2, 2, 2, 2, 2,\
            2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\
            2, 2, 2, 2, 2, 2, 2, 2, 2,\
            2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0))

// macro for recursion
#define MAP_A(...) \
    PLUS_TEXT(MAP_NEXT_, MAP_SWITCH(0, __VA_ARGS__)) (MAP_B, __VA_ARGS__)

#define MAP_B(...) \
    PLUS_TEXT(MAP_NEXT_, MAP_SWITCH(0, __VA_ARGS__)) (MAP_A, __VA_ARGS__)

#define MAP_CALL(fn, Value) EXPAND(fn(Value))

#define MAP_OUT /* empty! nasty hack for recursion */

// call destination func/macro
#define MAP_NEXT_2(...)\
    MAP_CALL(EXPAND(ARG_2(__VA_ARGS__)), EXPAND(ARG_3(__VA_ARGS__))) \
    EXPAND(ARG_1(__VA_ARGS__)) \
    MAP_OUT \
    (EXPAND(ARG_2(__VA_ARGS__)), EXPAND(OTHER_3(__VA_ARGS__)))

#define MAP_NEXT_0(...) /* end mapping */

// run foreach mapping... 1st arg must be function/macro with one input argument
#define MAP(...)    EVAL(MAP_A(__VA_ARGS__))

对它的一些测试:

// macro for test
#define DEMO(X) printf(#X " = %d\n", X);
.................
MAP(DEMO); // NO ARGS
MAP(DEMO, a);
MAP(DEMO, a, b);
MAP(DEMO, a, b, c);
MAP(DEMO, a, b, c, d);

此代码扩展为:

; // NO ARGS
printf("a" " = %d\n", a);;
printf("a" " = %d\n", a); printf("b" " = %d\n", b);;
printf("a" " = %d\n", a); printf("b" " = %d\n", b); printf("c" " = %d\n", c);;
printf("a" " = %d\n", a); printf("b" " = %d\n", b); printf("c" " = %d\n", c); printf("d" " = %d\n", d);;