[英]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.