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;
}
UPDATE 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;
}
Я чувствую, что я мог бы сделать лучшую работу с наименованием и комментариями, но я цейтнот. Я определенно открыт для любых комментариев или критических замечаний.
Это уже реализовано хорошо и короткие. Вы пишете больше кода для простой причины! – ninja