是否有可能创建一个C++类来模仿std :: cout语法:通过链接重载插入操作符来执行与easylogging ++相同的方式?
的easylogging ++代码定义一个宏,使得它非常简单易用:是否有可能创建一个C++类来模仿std :: cout语法:通过链接重载插入操作符来执行与easylogging ++相同的方式?
LOG(logLevel) << "This mimics std::cout syntax. " << 1 << " + " << 1 << " = " << 2;
我想打一个包装类easylogging ++。我可以使用两个参数轻松创建一个函数来包装上面的行。但是,是否有可能在包装类中模仿这种语法?例如:
Logger logger;
logger(logLevel) << "Line " << 1 << " of log text.";
我知道我可以很容易地重载插入运算符,但仍然给我留下了无需编写另一个函数以每次设置日志级别。
UPDATE:
由于Starl1ght的回答,我能够得到这个工作。我想我会分享以防其他人有类似的需求。
我创建了两个重载。一个用于(),另一个用于< <。
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&
的类型,所以,超载operator<<
与必要的日志级别集中返回的引用将正常工作。
事情是这样的:
Logger& Logger::operator()(LogLevel level) {
// set internal log level
return *this;
}
非常感谢!这正是实现它所需要的。 – Blackwood
它已经实现好和短。出于简单的原因你正在编写更多的代码! – ninja