C ++:忽略声明

问题描述 投票:1回答:1

我正在使用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(并且编译器很可能会摆脱dummied out代码)。这很好,因为它的行为基本上是C ++语言的扩展。

__SAFE未定义时,我也想在类中跳过一些数据成员声明。上面的技巧不再起作用,因为在类声明中不允许流控制。我想声明一些宏guard为哪个类:

class A {
guard int x;
}

仅在定义int x时包含成员__SAFE

可能的解决方案:

  • 一些预编译器技巧能够用guard替换//,从而获得所需的结果;但它们只适用于某些编译器(尤其不适用于g++)。此外,似乎在预处理之前删除了注释,因此它可能无论如何都不会起作用。
  • #ifdef ... #endif块围绕声明。它有效,但有点冗长。
  • 如果定义了guard(X),则将X定义为__SAFE,否则定义为空格。这也有效,但摆脱括号会很好,只需将参数作为“一切直到下一个分号”。

我知道C ++预处理器不是很强大。我想知道是否有一个美学上令人愉悦的解决方案;否则我会简单地使用后一种选择。

c++ macros c-preprocessor
1个回答
3
投票

从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使用,那么这也会产生链接器错误(如果打开,则虚拟静态变量仍然存在,但如果未使用则应在链接时进行优化)。

您也可以在<C ++ 11中执行此操作,但它会稍微冗长一些。

也就是说,我想注意,确保和守卫是太常见的名称,不能用作宏,仍然希望不会发生名称冲突,所以我强烈建议反对这样的事情(你已被警告:))

此外,阅读你的代码的人会因为将qazxsw poi隐藏在一个看起来像模板的宏中而感到困惑......在我看来,一个好的ol qazxsw poi将是一个更好的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.