【问题标题】:C++ macro function expansion based on the macro function arguments基于宏函数参数的 C++ 宏函数扩展
【发布时间】:2013-11-19 05:57:43
【问题描述】:

我使用的一些系统没有我正在使用的日志库,这对于在生产运行中经过良好测试的代码来说是可以的 --- 日志库主要用于调试和测试。在我的主要开发机器上,以及我经常在其上运行实验的几台服务器上,存在日志库。但有时我需要将实验外包给具有更多节点和内核的另一台服务器,但 没有 有日志库。

库 (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 严重性的消息。

如果可能的话,我怎样才能只使用预处理器指令来做到这一点?

【问题讨论】:

  • 为什么不简单地使用一个使用预处理器指令的函数呢?像 void log(string target, string message){ #ifdef NOLOGGING if(target.compare("INFO") == 0) { ... } ... },像 log("INFO", "my info message ");

标签: c++ macros c-preprocessor


【解决方案1】:

我认为您不能仅使用预处理指令来做到这一点,因为预处理器并没有真正为您提供必要的机制来根据宏的参数来指导宏扩展。

也就是说,您可以进行一些可行的稍微丑陋的黑客攻击。考虑以下代码:

#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) 来优化编译时已知条件。但是,我认为它会给你你想要的。

【讨论】:

  • 我会改用#define MYLOG(x,y) (P(MYLOG_,x) ? void(std::cerr &lt;&lt; y &lt;&lt; std::endl) : void())
  • @Simple:也有效。我实际上是先用?: 开始写这篇文章的,但我认为void 表达式有点晦涩难懂。两种方法都有效。
  • 谢谢,这个解决方案非常很有趣。我想,鉴于预处理器宏语言的限制,我可能最好定义像 MYLOG_FATAL(m)MYLOG_INFO(m) 这样的宏。
猜你喜欢
  • 2010-12-25
  • 2023-03-26
  • 1970-01-01
  • 2015-08-05
  • 2019-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多