我正在使用C++预处理器宏有选择地忽略一些代码块以进行测试,例如
#ifdef __SAFE
#define note
#define ensure(X) if(X) {} else
#else
#define note while(false)
#define ensure(X) while(false)
#endif
直观地,
note
执行一些代码(通常设置一些保护变量),如果违反条件,ensure
执行下一个代码块。有了这些宏,我可以编写:note { var = true }
ensure(var == true) { throw new std::exception; }
并且无论是否定义了
__SAFE
,代码都会进行编译(并且编译器很可能会删除已淘汰的代码)。很好,因为它的行为本质上是C++语言的扩展。我也想在未定义
__SAFE
时跳过类中的某些数据成员声明。上面的技巧不再起作用,因为在类声明中不允许进行流控制。我想为该类声明一些宏guard
:class A {
guard int x;
}
仅当定义了
int x
时,才包含成员__SAFE
。可能的解决方案:
guard
替换为//
,从而获得所需的结果。但它们仅在某些编译器中有效(特别是在g++
中不可用)。另外,似乎删除注释是在预处理之前进行的,所以它可能仍然无法正常工作。 #ifdef ... #endif
块包围声明。它可以工作,但是有点冗长。 guard(X)
,则将X
定义为__SAFE
,否则定义为空格。这也可行,但是最好不要使用括号,而只需将参数视为“直到下一个分号的所有内容”。 我知道C++前处理器不是很强大。我只想知道是否有一种美学上令人满意的解决方案;否则,我将仅使用后一种选项。
最佳答案
从C++ 11开始,您可以使用模板别名,例如:
struct A {
guarded<int> x;
};
其中
guarded
定义为:#ifdef YOUR_SAFE_MACRO
template<typename T>
using guarded_impl = T;
#define guarded guarded_impl
#else
template<typename T>
struct guarded_impl {};
#define guarded static guarded_impl
#endif
如果在
YOUR_SAFE_MACRO
关闭时使用ODR变量,则还具有给出链接器错误的好处(如果打开,则伪静态变量仍然存在,但是如果未使用,则应在链接时进行优化)。您也可以在
就是说,我想请注意,请确保确保和保护是太普通的名称,不能用作宏,并且仍然希望不会发生名称冲突,因此,我强烈建议您不要使用这种方法(已警告您:))
而且,人们在阅读您的代码时会因为将
static
隐藏在看起来像模板的宏中而感到困惑……在我看来,好的#ifdef
将是更好的解决方案。关于c++ - C++:忽略声明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48009145/