Управление потоком журналов в C ++ в cout-подобной нотации - PullRequest
6 голосов
/ 30 декабря 2010

У меня есть класс в C ++ для того, чтобы писать файлы журналов для моего приложения. Я уже построил класс, и он работает, это что-то вроде этого:

class Logger {
   std::string _filename;
public: 
   void print(std::string tobeprinted);
}

Хорошо, интуитивно понятно, что для печати строки в файле журнала для объекта Logger просто необходимо сделать следующее:

Logger mylogger("myfile.log");
mylogger.print(std::string("This is a log line"));

Хорошо. Использование методического подхода не то же самое, что использование гораздо лучшего шаблона, такого как << is. Я хотел бы сделать следующее: </p>

Logger mylogger("myfile.log");
mylogger << "This is a log line";

Вот и все. Я полагаю, я должен перегрузить оператор << ... Но перегрузка с использованием этой подписи (классическая): </p>

ostream& operator<<(ostream& output, const MyObj& o);

Но у меня нет ostream ... Итак, я должен сделать следующее?

Logger& operator<<(Logger& output, const std::string& o);

Это правильный путь? Спасибо

Ответы [ 4 ]

6 голосов
/ 30 декабря 2010
class Log
{
public:

    enum Level { Debug, Error, Info };

    static ostream& GetStream() { return cout; }
    static bool IsLevelActive(Level l) { return true; }
};

#ifndef NO_LOG
#define LOG_ERROR(M)   do { if (Log::IsLevelActive(Log::Error))   (Log::GetStream() << "ERR: " << M << "\n"); } while (false)
#define LOG_INFO(M)    do { if (Log::IsLevelActive(Log::Info))    (Log::GetStream() << "INF: " << M << "\n"); } while (false)
#define LOG_WARNING(M) do { if (Log::IsLevelActive(Log::Warning)) (Log::GetStream() << "WRN: " << M << "\n"); } while (false)
#else
#define LOG_ERROR(M)
#define LOG_INFO(M)
#define LOG_WARNING(M)
#endif

struct MyObject {
    int a, b;
};

ostream& operator<<(ostream& ostr, const MyObject& obj) {
    ostr << "(a=" << obj.a << ", b=" << obj.b << ")";
    return ostr;
}

void test() {
    int v1 = 42;
    int v2 = 43;
    LOG_INFO("value1=" << v1 << ", value2=" << v2);

    MyObject o = {1, 2};
    LOG_INFO("obj=" << o);
}
4 голосов
/ 30 декабря 2010

Почему бы просто не сделать Logger подклассом либо std :: ostream, либо std :: ostringstream?Тогда весь этот функционал уже будет реализован.

1 голос
/ 30 декабря 2010

Да, это правильный путь. Но вам придется добавить << перегруженные операторы для каждого типа данных, которые вам нужно регистрировать. </p>

0 голосов
/ 30 декабря 2010

Вы на самом деле не хотите создавать совершенно новые потоки, так как вам необходимо переопределить все операторы потоков. Вы сделали бы это, только если хотите полностью изменить способ преобразования данных в символьные данные. (Ик).

Что я нашел лучше всего для этого, так это создать класс, который будет отслеживать поток и отправлять его содержимое в место назначения по моему выбору (регистратор) при его разрушении. Это в сочетании с небольшим количеством макросов дает вам то, что вы ищете: потоковый синтаксис для ведения журнала.

У Boost действительно есть классы, которые помогают с этим. Посмотрите на iostreams .

...