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
而不是重新实现那个宏的主体,那么我认为没有宏是不可能的。
我正在尝试将 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
而不是重新实现那个宏的主体,那么我认为没有宏是不可能的。