我目前正在使用cpp记录器,该记录器旨在在每个打印的消息之前显示__FILE__
和__LINE__
。就我而言,我们主要使用两种打印方法:printf样式和std::cout样式。目前,每种样式都有一个宏:
#define HATFormatFatal(...) HATLogger::logFormat(HATLogger::LogLevel::FATAL, __FILE__, __LINE__, __VA_ARGS__)
#define HATFormatError(...) HATLogger::logFormat(HATLogger::LogLevel::ERROR, __FILE__, __LINE__, __VA_ARGS__)
等...以及:#define HATStreamFatal HATLogger::logStream(HATLogger::LogLevel::FATAL, __FILE__, __LINE__)
#define HATStreamError HATLogger::logStream(HATLogger::LogLevel::ERROR, __FILE__, __LINE__)
这些宏可以在下面调用:HATFormatError("This is an %s message", "ERROR");
HATStreamError << "This is an " << "ERROR" << " message" << std::endl;
我想用相同的名字来称呼他们:HATLogError
。正确的宏将在寻找括号时在编译时确定。 到目前为止,我已经看到一些示例,这些示例显示了如何通过参数的数量来区分宏,但是没有什么可以处理“非括号”情况。有谁知道如何实现这一目标?
最佳答案
最简单的方法是根本不重载宏,而是让宏返回一个同时重载了operator<<
和operator()
的对象。像这样:
class error_logger {
public:
error_logger(
HATLogger::LogLevel level,
char const * file,
char const * line
) : level{level}, file{file}, line{line} { }
template <typename... T>
void operator()(T && ... args) {
HATLogger::logFormat(level, file, line, std::forward<T>(args)...);
}
template <typename T>
HATLogger::logStream operator<<(T && arg) {
HATLogger::logStream stream{level, file, line};
stream << std::forward<T>(arg);
return stream;
}
private:
HATLogger::LogLevel level;
char const * file;
char const * line;
};
(此示例假定HATLogger::logStream
可以移动。可能需要根据您的代码的详细信息对该示例实现进行调整,但是我在此处演示的是基本方法。)现在您可以执行以下操作:
#define HATFormatFatal (error_logger{HATLogger::LogLevel::FATAL, __FILE__, __LINE__})
然后可以同时使用HATFormatFatal << ...
和HATFormatFatal(...)
。
关于c++ - 重载C预处理程序宏-基于调用语法的区分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63330463/