简体   繁体   English

MSVC 2010中的地图巨集

[英]Map macro in MSVC 2010

I have code, that taken from https://github.com/swansontec/map-macro/blob/master/map.h : 我有从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))

It's seems that this code work fine (in Internet i not found information about problems with him), but in Microsoft Visual Studio 2010 he is not compiled and i cant take MSVC 2013. Code: 似乎该代码可以正常工作(在Internet中我找不到与他有关的问题的信息),但是在Microsoft Visual Studio 2010中,他没有被编译,因此我无法使用MSVC2013。代码:

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

must expand to: 必须扩展为:

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

but it expand to: 但它扩展为:

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

is there is a way to make this macros work correct? 有没有办法使此宏正常工作?

P. s. P.s. sorry for bad English 对不起,英语不好

I'm did it! 我做到了! With crazy hack, by combining different techniques, but it work in Visual Studio 2010. So, main code: 通过疯狂的黑客,通过组合不同的技术,但它可以在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__))

And some tests for it: 并为此进行一些测试:

// 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);

This code expand to: 此代码扩展为:

; // 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);;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM