[英]How to make #if #endif part of a macro
#define M(N)\
#if N == 5\
/*several lines of code that
Can't be replaced with a
tertnary operator*/
#else\
N;\
#endif
當我像這樣使用這個宏
M(5);
我期待輸出
// everything within the #if #else block
但它沒有編譯。
我並不感到意外,因為它不能編譯:我知道#if不能用在延續線上,即“\\”。
我也試過了
#define POUND_IF #if
然后使用POUND_IF但不起作用。
這可能嗎?
是否有一些可以使用的漂亮的Boost預處理器東西?
簡而言之,你做不到。 不過,您可以依賴優化器:
#define M(N)\
do { if (N == 5) { \
/*several lines of code that
Can't be replaced with a
ternary operator*/ \
} else { N; } } while (0)
如果編譯器在運行代碼時可以確定N
的值將為5(例如,您編寫M(5)
),那么只有if
主體中的代碼將包含在生成的代碼中。 如果編譯器在運行代碼時可以確定N
的值不為5,則它將僅生成else
子句主體中的代碼。 如果它無法確定值是什么,預處理器也不能這樣做,但編譯器將包含所有代碼。
宏定義不能包含預處理程序指令(以#
開頭的任何內容)。
要有條件地擴展到某些值,需要相當復雜的宏觀,並且可能並不總是按照您想要的方式進行。 上面的例子可以這樣編寫:
#define ONE_OR_TWO(...) ONE_OR_TWO_(__VA_ARGS__, 2, 1,)
#define ONE_OR_TWO_(_1, _2, X, ...) X
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A ## B
#define M(N) CAT(IF_, ONE_OR_TWO(CAT(IS_, N)))({\
code; \
code; \
}, N)
#define IS_5 ,
#define IF_1(A, B) B
#define IF_2(A, B) A
M(5); //-> { code; code; }
M(8); //-> 8
但這非常脆弱。 例如,您只能使用某些類型的表達式作為M
的參數 - 它們必須具有允許連接的語法結構,並且沒有未包裝的逗號 - 並且它僅適用於預定值(例如,與比較復雜的事物進行比較)此方法無法使用簡單的數字,因為您無法使用更復雜的表達式構建宏名稱。
但原則上可以做到。 您只需要成千上萬行宏定義來覆蓋一組有用的案例,而不是像這樣的普通案例。 你可以通過使用像Order-PP或Boost.Preprocessor這樣的元編程庫來獲取它們,但是如果你在語法中稍微滑了一下,那么就應該為晦澀的錯誤消息做好准備。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.