儘管我完全同意,如果可能的話,應該使用可變參數函數或函數模板,這個問題也顯示出一些關於宏可以和不可以做什麼的誤解,所以在這個答案中,我將假裝函數不是一種選擇。
改變定義FOO(a, ...);
和__VA_ARGS__
變量(其代表...)分成b
和,如果存在的話,進入休息。
是的。
所以函數調用看起來像:FOO(5, "4gamma");
和FOO(5, "4");
號繼續調用爲FOO(5, 4, "gamma");
和FOO(5, 4);
。在第一種情況下,__VA_ARGS__
是4, "gamma"
。在第二種情況下,__VA_ARGS__
是4
。
如果您需要從前者提取, "gamma"
,那麼可以由預處理器完成。它需要參數數量的上限,但您可以將其增加到幾乎任何您喜歡的數字。雖然這很醜陋。
如果__VA_ARGS__
不包含逗號,提取很簡單:
#define COMMA_TRAILING_ARGS_0(a)
如果你知道__VA_ARGS__
至少包含一個逗號,你可以使用
#define COMMA_TRAILING_ARGS_1(a, ...) , __VA_ARGS__
而且你可以檢測到這些來使用,達到一定的宏參數上限:
#define ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define HAS_COMMA(...) ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,)
合併:
#define COMMA_TRAILING_ARGS_0(a)
#define COMMA_TRAILING_ARGS_1(a, ...) , __VA_ARGS__
#define ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define HAS_COMMA(...) ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,)
#define CONCAT(a, b) a ## b
#define CONCAT_(a, b) CONCAT(a, b)
#define FOO(a, ...) BAR(a CONCAT_(COMMA_TRAILING_ARGS_, HAS_COMMA(__VA_ARGS__)) (__VA_ARGS__))
FOO(5, 4, x, q); // expands to BAR(5, x, q);
FOO(5, 4, "gamma"); // expands to BAR(5, "gamma");
FOO(5, 4); // expands to BAR(5);
爲什麼使用宏?你試圖解決的實際問題是什麼? –
可變參數函數模板是您的解決方案。 – DeiDei
@DeiDei請你詳細說明功能模板? – FigsHigs