RAC中有一個宏定義metamacro_argcount(...) 其作用是計算出可變參中的數量,比如:int num = metamacro_argcount(a, b, c); 則相當于int num = 3; 因為采用的是宏展開,所以編譯時就知道這個num的值了,無須等到運行時。作者說他的靈感 來于P99:Inspired by P99: http://p99.gforge.inria.fr
我們來剖析一下:
#define metamacro_argcount(...)
metamacro_at(20, VA_ARGS, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
宏metamacro_argcount的意義是計算出可變參的長度,通過這個宏可以在預處理之后就拿到可變參數的個數,而不是使用傳統的va_start va_arg va_end這些運行時才可以確定可變參數信息的函數。
int count = metamacro_argcount(a, b, c);
NSLog(@"%d", count); // 3
#define metamacro_argcount(...) \
metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
展開為:int count = metamacro_at(20, a, b, c, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define metamacro_at(N, ...) \
metamacro_concat(metamacro_at, N)(__VA_ARGS__)
展開為:int count = metamacro_concat(metamacro_at, 20)(a, b, c, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define metamacro_concat(A, B) \
metamacro_concat_(A, B)
展開為:int count = metamacro_concat_(metamacro_at, 20)(a, b, c, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define metamacro_concat_(A, B) A ## B
展開為:int count = metamacro_at20(a, b, c, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) metamacro_head(__VA_ARGS__)
展開為:int count = metamacro_head(3, 2, 1)
#define metamacro_head(...) \
metamacro_head_(__VA_ARGS__, 0)
展開為:int count = metamacro_head_(3, 2, 1, 0)
#define metamacro_head_(FIRST, ...) FIRST
展開為:int count = 3
屌爆了!