C ++ поток как переменная-член - PullRequest
10 голосов
/ 09 декабря 2011

У меня есть класс C ++, в котором я хотел бы хранить поток, используемый для ведения журнала.

Поток должен быть в состоянии быть установлен (и, возможно, сброшен) после создания объекта.

Должна быть возможность установить поток как std::cout, или как файловый поток для записи в файл, или как строковый поток, который не делает ничего, кроме игнорирования данных (своего рода /dev/null).В любом случае, это должен быть объект типа ostream, который создатель объекта может сбросить в любой момент.Сам класс не обращает внимания на конкретный тип потока.

Я мог бы сделать это с помощью указателя на ostream, но тогда синтаксис становится немного раздражающим, так как приходится использовать оператор deref:

(*m_log) << "message";

, а не

m_log << "message";

Но я не могу использовать ссылки, поскольку объект потока должен быть сброшен после инициализации объекта.

Есть ли элегантный способдобиться этого, т. е. избегать использования указателей, но все же иметь возможность сброса после построения?

Ответы [ 2 ]

10 голосов
/ 09 декабря 2011

Вы можете сбросить потоки: посмотреть вживую на https://ideone.com/Ci4eo

#include <fstream>
#include <iostream>
#include <string>

struct Logger
{
    Logger(std::ostream& os) : m_log(os.rdbuf()) { }

    std::streambuf* reset(std::ostream& os) 
    {
        return m_log.rdbuf(os.rdbuf());
    }

    template <typename T> friend Logger& operator<<(Logger& os, const T& t)
    { os.m_log << t; return os; }

    friend Logger& operator<<(Logger& os, std::ostream& ( *pf )(std::ostream&))
    { os.m_log << pf; return os; }

  private:
    std::ostream m_log;
};

int main(int argc, const char *argv[])
{
    Logger logto(std::cout);

    logto << "Hello world" << std::endl;

    logto.reset(std::cerr);
    logto << "Error world" << std::endl;

    return 0;
}
5 голосов
/ 09 декабря 2011

Зачем беспокоиться?

class foo{
public:
  // ..
private:
  std::ostream& log() const{ return *m_log; }
  mutable std::ostream* m_log;
};

И просто используйте log() << "blah\n";.

...