c++ - 重载C预处理程序宏-基于调用语法的区分

标签 c++ logging macros c-preprocessor

我目前正在使用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/

相关文章:

c++ - 如何在 C++ 中的单个构造函数中调用多个构造函数

c++ - 如果内存不足抛出 Bad_alloc 异常

c++ - 获取所有数组的结构列表并自动检测每个数组的名称并打印它

python - pytest - 从运行测试的 CLI 命令指定日志级别

C++ 在 if 条件下使用 g++ 定义一个静态变量

macros - 卫生宏 : function parameter names?

c++ - 成员初始值设定项中使用的 sizeof 的行为是什么?

azure - 如何在 azure 应用服务中查看控制台或跟踪输出? Console.WriteLine 或 Trace.TraceError

logging - Axis2 使用 logback 记录 SOAP 请求和响应截断为 4000 个字符(字节)

c++ - 设置和取消设置 64 位整数中的特定位