LOG4CXX_INFO 不是#define 的干净包装器

LOG4CXX_INFO clean wrapper that is not a #define

我正在尝试将 C++ 中的 #define 宏包装到内联函数或模板函数中。在 LOG4CXX 中,它有一个定义,例如:

#define LOG4CXX_INFO(logger, message) { \
        if (logger->isInfoEnabled()) {\
           ::log4cxx::helpers::MessageBuffer oss_; \
           logger->forcedLog(::log4cxx::Level::getInfo(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}

我需要将其他上下文添加到日志中,并将 LOG4CXX_INFO 包装在另一个定义中并让此实现正常工作。我想不再使用 #define 来包装它,而是以更 C++ 的方式进行。我 运行 关注的这个问题是消息参数可以是使用 + 或 << 运算符连接在一起的各种类型的对象,目前在 MessageBuffer class 中使用运算符覆盖进行处理。

如果我尝试将其模板化为:

   template<typename T> 
   void info(LoggerPtr logger, const T& message) {
        ...do stuff ...
        LOG4CXX_INFO(logger, message);
   }

编译器会抱怨没有为各种类型的对象找到<<运算符。

要完成这项工作需要做什么?

在 ubuntu

上编译了以下内容
gcc main.cpp -lstdc++ -llog4cxx
#include <log4cxx/logger.h>

using namespace std;

#define info(logger, message) LOG4CXX_INFO(logger, message)

template<typename T> void tinfo(log4cxx::LoggerPtr logger, const T& message) {
     LOG4CXX_INFO(logger, message);
}

int main()
{
        log4cxx::LoggerPtr logger;
        LOG4CXX_INFO(logger, "test" << "test2");

        info(logger,"another test");
        info(logger,"another test" << "another test2");

        tinfo(logger,"test template");

        //tinfo(logger,"test template" << "test template 2"); -> this line does not compile
        return 0;
}

编译器错误:

main.cpp: In function ‘int main()’:
main.cpp:21:31: error: invalid operands of types ‘const char [14]’ and ‘const char [16]’ to binary ‘operator<<’
  tinfo(logger,"test template" << "test template 2");

MessageBuffer 代码可以在这里找到:https://github.com/apache/logging-log4cxx/blob/master/src/main/include/log4cxx/helpers/messagebuffer.h and here https://github.com/apache/logging-log4cxx/blob/master/src/main/cpp/messagebuffer.cpp

tinfo(logger,"test template" << "test template 2");

错了。它 首先 计算 "test template" << "test template 2" 然后将结果传递给函数。但这没有意义,因为 << 的左侧应该是一个流对象。

这对宏有效,因为宏是纯文本替换,所以替换

LOG4CXX_INFO(logger, "test" << "test2");

产量

oss_ << "test" << "test2"

从左到右求值。 如果在宏参数周​​围添加括号

LOG4CXX_INFO(logger, ("test" << "test2"));

你忠实地重现了函数行为,你会得到同样的错误,因为你会评估

oss_ << ("test" << "test2")

如果你想在一个函数调用中输出多个东西,我建议使用折叠表达式(自 C++17 起可用):

template<typename... Ts>
void tinfo(log4cxx::LoggerPtr logger, const Ts&... messages) {
    if (logger->isInfoEnabled()) {
        ::log4cxx::helpers::MessageBuffer oss_; 
        logger->forcedLog(::log4cxx::Level::getInfo(), oss_.str((oss_ << ... << messages)), LOG4CXX_LOCATION);
    }
}

tinfo(logger, "test template", "test template 2");

如果你想保持原来的语法and/or参考LOG4CXX_INFO而不是重新实现那个宏的主体,那么我认为没有宏是不可能的。