簡體   English   中英

如何使#if #endif成為宏的一部分

[英]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-PPBoost.Preprocessor這樣的元編程庫來獲取它們,但是如果你在語法中稍微滑了一下,那么就應該為晦澀的錯誤消息做好准備。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM