是否可以验证预处理器宏以确保它是一个数字?
Can I validate a preprocessor macro to make sure it's a number?
我正在使用宏在我的代码中定义简单的变量(如下所示):
#define foobar 1
//...
barfoo(foobar);
为了防止错误,我想通过验证输入来确保foobar
是一个数字。 foobar
应该始终是一个数字,所以它可以非常简单。
显然,预处理器不处理数学,因此失去了用算术生成某种类型错误的希望。
我想由于这个原因,常量确实更好,但我正在尝试使用所有宏,因此它在我拥有的配置文件中是一致的(有些确实需要宏)。正则表达式可能是一个很好的解决方法,但 GCC 似乎不支持 [使用宏] 这一点(加上 http://xkcd.com/1171/)。
在 C++11 中,有一些类型特征和静态断言应该可以满足您的目的:
#include <type_traits>
#define foo 1
// #define foo "bar" // will lead to a compiler error containing the message "foo is not int"
static_assert(std::is_integral<decltype(foo)>::value, "foo is not int");
由于对问题的注释说表达式也应该被禁止,因此涉及编译时检查表达式是否具有整型的答案不会起作用:这将检测1
、(1)
和(0+1)
之间没有区别,因为这三个都是具有完全相同值的 int
类型的 pr值。
因此,答案必须涉及查看宏定义本身,这可以通过将其字符串化,并将验证放在接受字符串的constexpr
函数中,并在静态断言中使用它来实现。正十进制无后缀整数文本的示例:
#define A 1
#define B 2
#define C 3
#define D (4)
#define STR_(x) #x
#define STR(x) STR_(x)
constexpr bool is_number(const char *str) {
return (*str >= '0' && *str <= '9') && (str[1] == ' ' || is_number(str+1));
}
#define VERIFY(x) static_assert(is_number(STR(x)), STR(x) " is not a number!")
VERIFY(A); // passes
VERIFY(B); // passes
VERIFY(C); // passes
VERIFY(D); // fails: (4) is not a number!
如果您还需要处理带后缀的文字 ( 123L
) 或非十进制文字 ( 0x123
),则需要扩展它。如果作为特殊例外,您希望允许将一元-
应用于整数文本,则也需要扩展。
这几乎肯定不值得保护。如果有人认为代码更具可读性和/或可维护性,如果D
被定义为(4)
,或(3+1)
,或(C+1)
,而不是4
,如果除了这个断言之外,这些定义将很好地工作,断言很快就会从代码中剥离出来。
我建议您仅在必要时使用宏,否则使用常量。 一致性并不总是最重要的优先事项。
为此,有充分的理由使用常量而不是定义。
斯科特·迈耶斯(Scott Meyers)在他的《有效C++》一书中有一章专门讨论这一点:
http://books.google.com/books?id=U7lTySXdFk0C&pg=PT41&lpg=PT41#v=onepage&q&f=false
第 2 项:"首选常量、枚举和内联而不是 #defines"。
使用常量可以使调试变得容易得多,因为编译器可以访问名称(而不仅仅是预处理器替换)。
定义也没有相同类型的安全功能(这可能是您在这里尝试解决的问题)。它们没有相同的范围限定功能。
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 如何获取一个数字的前3位
- 以C++输出一个数字三角形
- 反转一个数字程序不起作用,为什么?
- 如何让用户在 c++ 中选择一个数字
- 输出一个数字,该数字可能是三种类型之一
- C++在不使用pow或循环的情况下计算一个数字的幂
- 我必须更改我的数字最后一个数字和第一个数字,但不要使用仅带有整数或循环的函数.例如从 12345 到 52341
- 找到所有与自己求和的数字X的快速方法,去掉一个数字得到N
- C++[递归]将一个数字写成2的升序之和
- 试图找到一个数字的平方根,但代码不起作用。C++
- 我没有得到一个数字作为输出,而是一个表情符号
- 我的代码应该接受一个数字,并返回字母等级或"Grade is not valid"但 else 语句不起作用
- 将一个数字拆分为多个数字,每个数字只有一个有效位
- 你怎么编码,如果x不等于一个数字,程序就会退出
- 如何将整数数组相乘得到一个数字?
- 为无符号字符* 分配一个数字
- 如何以更有效的方式检查一个数字是否是素数?
- C++显示两个区间之间的数字的程序检查一个数字是否可以表示为两个素数的总和
- 字符串和双精度的麻烦,等值后再得到一个数字