簡體   English   中英

通過參數選擇C ++預處理程序宏

[英]C++ Preprocessor macro selection by argument

我正在嘗試定義一個預處理器宏,該宏又根據參數的值選擇正確的宏。

#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"
#define BIT(n) ?????

int main() {
    printf("%d %s", BIT(9));
    return 0;
}

BIT(n)應擴展為:

如果BIT_8(n)
如果n> 8,則BIT_N(n)

有什么辦法可以做到這一點?

除非您想要非常笨拙的代碼,否則您將無法做到這一點。 預處理器不知道傳入的參數的值。它只是在進行字符串替換,僅此而已。

話雖這么說,但他們瘋狂地為[0到63]中的所有x實現BIT_x。 這非常丑陋,並且將參數設置為64會失敗。

一個干凈的解決方案是使用一個函數代替:

const char * bit_msg(unsigned int b)
{
    if (b > 8) return "is greater than 8";
    const char * bits[] = {
"is 0 and lower than 8",
"is 1 and lower than 8",
"is 2 and lower than 8",
"is 3 and lower than 8",
"is 4 and lower than 8",
"is 5 and lower than 8",
"is 6 and lower than 8",
"is 7 and lower than 8",
"is 8",
}; 
return bits[b];
}

#define BIT(X) X, bit_msg(X)
[...]
printf("%d %s", BIT(9));

因為您已經用C ++標記了問題並遵循@Romen,所以可以使用constexpr獲得類似的結果,如果可能的話,它將由編譯器在編譯時計算,從而產生與宏一樣高效的代碼。

在上面的示例中,您只需要用constexpr const char * bit_msg(unsigned int b)替換簽名,編譯器甚至可能會跳過該函數並寫入(等效於) printf("%d %s", 9, "is greater than 8")

你可以這樣做

#include <stdio.h>

#define BIT_8(n) printf("%d is lower than or equal to 8 \n" , n)
#define BIT_N(n) printf("%d is greater than 8 \n" , n)
#define BIT(n) ((n <= 8) ? (BIT_8(n)) : (BIT_N(n)))

int main() {
    BIT(7);
    BIT(8);
    BIT(9);
    return 0;
}

挑戰在於預處理器不懂數學。 您可以通過實現所需的數學方法來解決此問題,但是這很麻煩。 例如,以下是您要執行的工作的預處理程序代碼:

#include <stdio.h>

#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"

// Identify values less than 8; make the second argument 8
#define LT_8_0 ~,8
#define LT_8_1 ~,8
#define LT_8_2 ~,8
#define LT_8_3 ~,8
#define LT_8_4 ~,8
#define LT_8_5 ~,8
#define LT_8_6 ~,8
#define LT_8_7 ~,8
#define LT_8_8 ~,8

// Helper macros.  Delays let arguments be processed before the macros is run.
#define MERGE(A, B) A ## B
#define MERGE_DELAY(A, B) MERGE(A,B)
#define ARG2(A,B,...) B
#define ARG2_DELAY(A,B,...) ARG2(A,B,__VA_ARGS__)

// Return 8 or N depending if n <= 8...
#define LT_8(n) ARG2_DELAY( MERGE(LT_8_, n), N,~ )

#define BIT(n) MERGE_DELAY(BIT_, LT_8(n))(n)

int main() {
  printf("%d %s\n", BIT(9));
  return 0;
}

請注意,LT_8宏通過采用一系列參數中的第二個來工作。 我們將第二個參數默認設置為N,但是如果我們識別輸入數字為8或更小,我們將插入一個新的第二個參數8。

暫無
暫無

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

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