C++预处理器按参数宏选择
我试图定义一个预处理器宏,该宏根据参数的值依次选择正确的宏C++预处理器按参数宏选择,c++,preprocessor,C++,Preprocessor,我试图定义一个预处理器宏,该宏根据参数的值依次选择正确的宏 #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; } BITn应扩展到: 如果为n,则为第8n位≤8. 如果n>8,则为位Nn 有什么方法可以做到这一点吗?除
#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;
}
BITn应扩展到:
如果为n,则为第8n位≤8.
如果n>8,则为位Nn
有什么方法可以做到这一点吗?除非您想要非常笨拙的代码,否则您无法做到这一点。预处理器不知道传入的参数的值。它只是替换字符串而已 也就是说,他们是为[0到63]中的所有x实现位_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,你可以使用COSTEXPR获得相似的结果,如果可能的话,编译器将在编译时计算,从而得到与宏有效的代码。
在上面的示例中,您只需将签名替换为constexpr const char*bit\msgunsigned int b,编译器甚至可能跳过该函数并编写printf%d%s的等效值,9大于8。除非您需要非常笨拙的代码,否则无法执行此操作。预处理器不知道传入的参数的值。它只是替换字符串而已 也就是说,他们是为[0到63]中的所有x实现位_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,你可以使用COSTEXPR获得相似的结果,如果可能的话,编译器将在编译时计算,从而得到与宏有效的代码。 在上面的示例中,您只需将签名替换为constexpr const char*bit\msgunsigned int b,编译器甚至可能跳过该函数并编写printf%d%s的等效值,9大于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) 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。挑战在于预处理器不懂数学。你可以通过实现你需要的数学来解决这个问题,但它会变得难看。例如,下面是您要执行的操作的预处理器代码:
#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。确实不希望使用if constexpr吗?预处理器宏执行相当简单的文本替换。作为一种编程语言,预处理器是一个糟糕的选择。你确定不想使用if constexpr吗?预处理器宏执行相当简单的文本替换。作为一种编程语言,预处理器是一个糟糕的选择。我想补充一点,指出说明符可以用来将宏重写为可以在编译时计算的函数。理想情况下,现代C++代码不应该使用更多的预处理器。注意,如果使用令牌粘贴调用BIT9,那么对于所有X的实现BITYX都可以工作,它将失败为BIT8+。1@MartinBonner你完全正确。预处理器只是复制和粘贴,它不是一种语言。我想补充一点,指出可以使用说明符将宏重写为可在编译时计算的函数。理想情况下,现代C++代码不应该使用更多的预处理器。注意,如果使用令牌粘贴调用BIT9,那么对于所有X的实现BITYX都可以工作,它将失败为BIT8+。1@MartinBonner你完全正确。预处理器只是复制和粘贴,它不是一种语言。