C++20 引入了预定义功能测试宏的概念,允许检查语言和库功能的可用性(请参阅 https://en.cppreference.com/w/cpp/feature_test 中的表格)。
我正在编写一个简单的应用程序,它将打印其中一些宏的值。为了减少代码重复,我将打印提取到类似函数的宏中:
#include <iostream>
#define print(feature) std::cout << #feature " : " << feature << '\n'
int main()
{
print(__cpp_aggregate_bases);
print(__cpp_aggregate_nsdmi);
print(__cpp_aggregate_paren_init);
}
然而事实证明,一些宏没有在我的编译器(g++ 11.4.0)中定义,例如
__cpp_auto_cast
或__cpp_char
,编译失败。
是否有一种优雅的方法来检测未定义的宏(最好在
print
宏内部),而不必求助于这样的怪物:
#if defined(__cpp_auto_cast)
std::cout << "__cpp_auto_cast : " << __cpp_auto_cast << '\n';
#else
std::cout << "__cpp_auto_cast : undefined\n;
#endif
对每个功能测试宏都重复?
值得解释一下 cppreference 在这里使用的技巧。
考虑:
#define ONCE(x) #x
#define TWICE2(x) #x
#define TWICE(x) TWICE2(x)
并采用一些为最新 gcc 定义的 C++20 宏,
__cpp_using_enum
,以及另一个甚至不存在的宏,__cpp_no_dangling
:
|
|
|
---|---|---|
|
|
|
|
|
|
所以
ONCE
是没用的,但是 TWICE
让我们处于一种可以区分存在和不存在的境地,并做一些有趣的事情。如果 TWICE(x)
给出一个以 _
开头的字符串,则为其指定值 0
。否则,手动计算该值 - 在这里我们可以相信它总是 YYYYMM
。
这就是 cppreference 宏的作用在示例中:
// Expect a string that starts with 6-decimal-digits or with '_' (if unsupported)
#define COMPILER_VALUE_INT(n) #n [0] == '_' ? 0 : \
(#n[5] - '0') + (#n[4] - '0') * 10 + (#n[3] - '0') * 100 + \
(#n[2] - '0') * 1000 + (#n[1] - '0') * 10000 + (#n[0] - '0') * 100000
#define COMPILER_FEATURE_ENTRY(expect, name) { #name, COMPILER_VALUE_INT(name), expect },