我正在为我的库创建一个日志工具,并制作了一些不错的宏,例如:
#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宏,并记录与用户的差异,但如果有办法解决这个问题,那将是非常酷的。有没有人看到过做这种事的任何伎俩?
答案 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 属性((弱)); 如果一个) 存在 其他 不存在