如何可以在一個限定一個C宏IFARGS(YES, NO, ...)
使得調用IFARGS
,沒有額外的參數產生NO
,並與一個或多個參數產生YES
調用IFARGS
?檢測在存在或不存在的參數爲C宏
我有一個使用GCC的答案(見下文),但如果可能的話(或證明它是不可能的),我更願意使用C99。
如何可以在一個限定一個C宏IFARGS(YES, NO, ...)
使得調用IFARGS
,沒有額外的參數產生NO
,並與一個或多個參數產生YES
調用IFARGS
?檢測在存在或不存在的參數爲C宏
我有一個使用GCC的答案(見下文),但如果可能的話(或證明它是不可能的),我更願意使用C99。
#define GET(_0, _1) _0 // Return the first of two arguments
#define GET_(_0, _1) _1 // Return the second of two arguments
#define JOIN(_0, _1) _0 ## _1 // Concatenate two arguments
#define EJOIN(_0, _1) JOIN(_0, _1) // Expand macros and concatenate
#define FIRST(_, ...) _ // Truncate everything after first comma
#define EFIRST(_) FIRST(_) // Expand argument and pass to FIRST
#define REST(_0, ...) __VA_ARGS__ // Remove everything before first comma
#define GET_GET(...) \
EJOIN(GET, EFIRST(REST(,,##__VA_ARGS__ _))) // Branch between GET and GET_
#define IFARGS(YES, NO, ...) GET_GET(__VA_ARGS__)(YES, NO)
需要注意的是,如果這在C99是可能的,那麼這將是可以模擬##__VA_ARGS__
,就像這樣:
#define PREPEND_COMMA(...) , __VA_ARGS__
#define NO_COMMA()
#define PREPEND_COMMA_IF_NONEMPTY(...) IFARGS(PREPEND_COMMA, NO_COMMA, __VA_ARGS__)(__VA_ARGS__)
隨後的, ##__VA_ARGS__
任何情況下,可以通過PREPEND_COMMA_IF_NONEMPTY(__VA_ARGS__)
取代。
在C99中,可以檢測宏參數是否爲空,但是對於可能出現在該參數中的所有可能性(自身擴展的參數,包含()
以及類似的東西)很難實現。我的宏包P99實現了這樣的事情,所以你不必擔心太多。由於您的宏可以實現爲
#define IFARGS(YES, NO, ...) P99_IF_EMPTY(__VA_ARGS__)(YES(__VA__ARGS__))(NO())
正如其名稱所示,P99僅建立在C99功能上。
這不是一個真正的答案,而僅僅是對自己問題的補充。 –
@JensGustedt第一個代碼框是一個部分解決方案 - 它具有所需的行爲,但需要'## __ VA_ARGS__',這是C99宏語法的GCC擴展。 – augurar
我注意到了。關於SO的一些研究可能已經向你揭示了一個答案。請參閱上面的鏈接。 –