是否可以通过与EasyLogging 相同的方式来创建一个C 类,以模仿STD :: COUT语法

Is it possible to create a C++ class that mimics the std::cout syntax by chaining overloaded insertion operators the same way that easylogging++ does?

本文关键字:一个 语法 COUT STD EasyLogging 可以通过 方式 创建 是否      更新时间:2023-10-16

easylogging 代码定义了一个宏,它非常易于使用:

LOG(logLevel) << "This mimics std::cout syntax.  " << 1 << " + " << 1 << " = " << 2;

我想做一个包装类,以供EasyLogging 。我可以轻松地创建一个具有两个参数的函数来包装上面的行。但是,是否可以在包装类类中模仿该语法?例如:

Logger logger;
logger(logLevel) << "Line " << 1 << " of log text.";

我知道我可以轻松地超载插入操作员,但这仍然使我每次都必须编写另一个功能来设置日志级别。

更新:

感谢Starl1GHT的答案,我能够使此工作正常工作。我认为如果其他人有类似的需求,我会分享。

我创建了两个过载。一个用于(),另一个用于&lt;。

Logger &operator()(logLevelT logLevel) {
  mLogLevel = logLevel;
  return *this;
}

template <typename T>
Logger &operator<<(T const &value) {
  LOG(mLogLevel) << value;
  return *this;
}

更新2:

我想再次更新此帖子以提供我的推理并显示我的最终解决方案。

我的理由是我的项目是抽象的演示。我正在尝试证明可以从软件的核心功能中抽象出记录库(以及许多其他内容)。这也使软件组件模块化。这样,我可以在不丢失语法的情况下交换EasyLogging 库,因为它是在模块接口中实现的。

我的最后一个更新没有提及如何克服插入链的障碍,因此我想发布一个示例来展示我是如何做到的。以下代码是如何实现std :: cout之类的班级语法的简化示例。

#include <iostream>         // For cout
#include <string>           // For strings
#include <sstream>          // For ostringstream

enum logLevelT {
    INFO_LEVEL,
    WARNING_LEVEL,
    ERROR_LEVEL,
    FATAL_LEVEL
};

class Logger {
private:
    std::string logName;
public:
    Logger(std::string nameOfLog, std::string pathToLogFile) {
        logName = nameOfLog;
        //TODO Configure your logging library and instantiate
        //     an instance if applicable.
    }

    ~Logger(){}

    // LogInputStream is instantiated as a temporary object.  It is used
    //  to build the log entry stream.  It writes the completed stream
    //  in the destructor as the object goes out of scope automatically.
    struct LogInputStream {
        LogInputStream(logLevelT logLevel, std::string nameOfLog) {
            currentLogLevel = logLevel;
            currentLogName = nameOfLog;
        }

        // Copy Constructor
        LogInputStream(LogInputStream &lis) {
            currentLogLevel = lis.currentLogLevel;
            currentLogName = lis.currentLogName;
            logEntryStream.str(lis.logEntryStream.str());
        }

        // Destructor that writes the log entry stream to the log as the
        //  LogInputStream object goes out of scope.
        ~LogInputStream() {
            std::cout << "Logger: " << currentLogName
                      << "   Level: " << currentLogLevel
                      << "   logEntryStream = " << logEntryStream.str()
                      << std::endl;
            //TODO Make a log call to your logging library.  You have your log level
            //     and a completed log entry stream.
        }

        // Overloaded insertion operator that adds the given parameter
        //  to the log entry stream.
        template <typename T>
        LogInputStream &operator<<(T const &value) {
            logEntryStream << value;
            return *this;
        }

        std::string currentLogName;
        logLevelT currentLogLevel;
        std::ostringstream logEntryStream;
    };

    // Overloaded function call operator for providing the log level
    Logger::LogInputStream operator()(logLevelT logLevel) {
        LogInputStream logInputStream(logLevel, logName);
        return logInputStream;
    }

    // Overloaded insertion operator that is used if the overloaded
    //  function call operator is not used.
    template <typename T>
    Logger::LogInputStream operator<<(T const &value) {
        LogInputStream logInputStream(INFO_LEVEL, logName);
        logInputStream << value;
        return logInputStream;
    }
};

int main(int argc, char *argv[]) {
    Logger logger1 = Logger("Logger1", "/path/to/log.log");
    Logger logger2 = Logger("Logger2", "/path/to/log.log");
    logger1(INFO_LEVEL) << "This is the " << 1 << "st test";
    logger2(ERROR_LEVEL) << "This is the " << 2 << "nd test";
    logger2 << "This is the " << 3 << "rd test";
    return 0;
}

我觉得我可以在命名和评论方面做得更好,但我被压迫了。我绝对接受任何评论或批评。

您必须超载 operator()因此,它将设置内部日志级别并将*this返回为类型Logger&,因此,Overloaded operator<<将在返回的参考上使用必要的日志级设置。

类似的东西:

Logger& Logger::operator()(LogLevel level) {
    // set internal log level
    return *this;
}