使用C ++宏检查变量存在

时间:2010-07-06 21:12:15

标签: c++ macros metaprogramming

我正在为我的库创建一个日志工具,并制作了一些不错的宏,例如:

#define DEBUG  myDebuggingClass(__FILE__, __FUNCTION__, __LINE__)
#define WARING myWarningClass(__FILE__, __FUNCTION__, __LINE__)

其中myDebuggingClass和myWarningClass都有重载<<运算符,并使用日志消息做一些有用的事情。

现在,我有一些用户将重载的基类叫做“Widget”,我想将这些定义更改为更像:

#define DEBUG  myDebuggingClass(__FILE__, __FUNCTION__, __LINE__, this)
#define WARNING myWarningClass(__FILE__, __FUNCTION__, __LINE__, this)

以便当用户调用'DEBUG<< “有些消息”; '我可以查看“this”参数是否为一个Widget进行dynamic_casts,如果是这样,我可以用这些信息做一些有用的事情,如果没有,那么我可以忽略它。唯一的问题是我希望用户能够从非成员函数(例如main())发出DEBUG和WARNING消息。但是,给定这个简单的宏,用户只会得到一个编译错误,因为“this”不会在类成员函数之外定义。

最简单的解决方案是只定义单独的WIDGET_DEBUG,WIDGET_WARNING,PLAIN_DEBUG和PLAIN_WARNING宏,并记录与用户的差异,但如果有办法解决这个问题,那将是非常酷的。有没有人看到过做这种事的任何伎俩?

6 个答案:

答案 0 :(得分:4)

在Widget类中声明全局Widget* const widget_this = NULL;和受保护的成员变量widget_this,初始化为this,然后执行

#define DEBUG myDebuggingClass(__FILE__, __FUNCTION__, __LINE__, widget_this)

答案 1 :(得分:2)

宏基本上是由预处理器完成的直接文本替换。宏没有办法知道它被调用的上下文来进行你感兴趣的那种检测。

最好的解决方案可能是您怀疑的单独宏。

答案 2 :(得分:1)

我认为你不能用宏来做这件事。您可以可能设法使用SFINAE,但使用SFINAE(至少直接)的代码是 1 难以编写,更难调试,几乎不可能对任何人专家阅读或理解。如果你真的想这样做,我会试着看看你是否可以得到Boost enable_if(或其亲戚)来处理至少部分肮脏的工作。

1 ...至少在我见过的每一个案例中,我都很难想象它也不是。

答案 3 :(得分:1)

受到solipist的启发,但在实现中稍微简单一些:

class Widget { 
  protected: 
  ::myDebuggingClass myDebuggingClass(char const* file, char const* function, int line) {
    return ::myDebuggingClass(file, function, line, this);
  }
  // ...

这消除了对阴影变量的需要;它依赖于简单的类名查找规则。

答案 4 :(得分:0)

我能想到的唯一方法就是定义一个全局变量:

Widget * this = NULL;

如果它甚至编译(我怀疑,但没有编译器来测试它),成员函数将使用最近的范围变量(真正的his指针),其他一切将得到一个空值。每个人都很开心(可以这么说......)

答案 5 :(得分:0)

你可以使用弱引用来检测变量或函数是否存在。 例如: 检测int存在:

int 属性((弱)); 如果一个)     存在 其他     不存在