基于宏函数参数的C ++宏函数扩展

时间:2013-11-19 05:57:44

标签: c++ macros c-preprocessor

我使用的某些系统没有我正在使用的日志库,这对于生产运行中经过良好测试的代码是可以的 - 日志库主要用于调试和测试。在我的主要开发机器上,以及我经常运行实验的几台服务器上,存在日志库。但偶尔我需要将实验扩展到具有更多节点和核心的另一台服务器,但的情况下会有日志库。

库(Google glog)提供了以下宏功能:

LOG(INFO) << "Insert my message here.";
LOG(FATAL) << "Insert another message here.";

所以,我所做的是定义如下:

#ifdef NOLOGGING
    #define MYLOG(i,m) std::cerr << #i << ": " << m << "\n";
#else
    #define MYLOG(i,m) LOG(i) << m ;
#endif

使用这些定义,我现在可以编写如下语句:

MYLOG(INFO, "My info message");
MYLOG(FATAL,"My fatal message");

如果使用标记-DNOLOGGING进行编译,则最后两个语句将扩展为:

std::cerr << "INFO" << ": " << "My info message" << "\n";
std::cerr << "FATAL" << ": " << "My fatal message" << "\n";

此外,如果编译中使用的-DNOLOGGING标志,它们将扩展为:

LOG(INFO) << "My info message";
LOG(FATAL) << "My fatal message";

我上面描述的解决方案令人满意,但并不理想。

理想情况下,当我无法访问日志记录库时,MYLOG(FATAL,"foo")之类的语句会扩展为打印到std::cerr的语句; 然而,像MYLOG(INFO,"bar")这样的语句会扩展为空。换句话说,当我无法使用日志库时,我希望忽略MYLOG(INFO,"bar")之类的语句。我的想法是,当我使用没有日志库的服务器时,我不太关心INFO严重性的日志消息,但我仍然希望看到FATAL严重性的消息

如果可能的话,我是否可以仅使用预处理程序指令执行此操作?

1 个答案:

答案 0 :(得分:2)

我认为你不能单独使用预处理指令,因为预处理器并没有真正为你提供必要的机制来根据宏的参数来指导宏扩展。

那就是说,你可以犯下一些有效的丑陋黑客。请考虑以下代码:

#include <iostream>

#define MYLOG_ERR  1
#define MYLOG_INFO 0

#define P(a,b) a##b

#define MYLOG(x,y) do { if (P(MYLOG_,x)) { std::cerr << y << std::endl; } } while (0)


int main(void)
{
    MYLOG(ERR, "err");
    MYLOG(INFO, "info");
}

这种方法依赖于编译器的优化器来识别一些常见的习语,例如do { ... } while (0)if (0) / if (1),以优化编译时已知的条件。但是,我认为它会给你你想要的东西。