首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以通过链接重载的插入操作符来创建一个模仿std::cout语法的C++类,就像easylogging++那样?

是否可以通过链接重载的插入操作符来创建一个模仿std::cout语法的C++类,就像easylogging++那样?
EN

Stack Overflow用户
提问于 2016-11-30 17:59:32
回答 1查看 366关注 0票数 3

easylogging++代码定义了一个宏,使其使用起来非常简单:

代码语言:javascript
复制
LOG(logLevel) << "This mimics std::cout syntax.  " << 1 << " + " << 1 << " = " << 2;

我想为easylogging++做一个包装类。我可以很容易地创建一个包含两个参数的函数来包装上面的行。但是,在包装类中可以模仿这种语法吗?例如:

代码语言:javascript
复制
Logger logger;
logger(logLevel) << "Line " << 1 << " of log text.";

我知道我可以轻松地重载插入操作符,但这仍然让我不得不编写另一个函数来设置日志级别。

更新:

多亏了Starl1ght的回答,我才能做到这一点。我想如果其他人有类似的需求,我也会分享的。

我创造了两个过载。一个用于(),另一个用于<<。

代码语言:javascript
复制
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的简化示例,类似于类的语法。

代码语言:javascript
复制
#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;
}

我觉得我本来可以做一个更好的命名和评论,但我是紧迫的时间。我绝对愿意接受任何评论或批评。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-30 18:02:02

您必须重载operator()所以,它将设置内部日志级别并将*this返回为Logger&类型,因此,重载的operator<<将使用必要的日志级别集处理返回的引用。

就像这样:

代码语言:javascript
复制
Logger& Logger::operator()(LogLevel level) {
    // set internal log level
    return *this;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40895150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档