gpt4 book ai didi

c++ - 是否可以像 easylogging++ 一样通过链接重载的插入运算符来创建模仿 std::cout 语法的 C++ 类?

转载 作者:太空狗 更新时间:2023-10-29 21:14:23 28 4
gpt4 key购买 nike

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

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

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

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

我知道我可以轻松地重载插入运算符,但这仍然让我每次都必须编写另一个函数来设置日志级别。

更新:

多亏了 Starl1ght 的回答,我才得以正常工作。我想我会分享,以防其他人有类似的需求。

我创建了两个重载。一个用于 (),另一个用于 <<。

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


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

更新 2:

我想再次更新这篇文章以给出我的推理并展示我的最终解决方案。

我的理由是我的项目是抽象的演示。我试图证明日志库(以及许多其他东西)可以从软件的核心功能中抽象出来。这也使软件组件模块化。这样我就可以在不丢失语法的情况下换出 easylogging++ 库,因为它是在模块接口(interface)中实现的。

我上次更新没有提到我是如何克服插入链接的障碍的,所以我想发布一个例子来展示我是如何做到的。以下代码是如何为类实现类似 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& ,所以,重载了operator<<将处理返回的引用并设置必要的日志级别。

像这样:

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

关于c++ - 是否可以像 easylogging++ 一样通过链接重载的插入运算符来创建模仿 std::cout 语法的 C++ 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40895150/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com