Перенаправление C ++ fstream - PullRequest
0 голосов
/ 09 июля 2009

Итак, у меня есть программа на C ++, которая обычно при выполнении записывает данные в файл журнала. Это делается с помощью fstream. Однако теперь я хочу включить функциональность, чтобы отключить ведение журнала. По сути, мой код выглядит так:

bool isLogging;
fstream* logFilePtr;

во всем моем коде есть несколько операторов вроде:

(*logFilePtr) << "    Kernel call time in seconds: " << kTime << endl;
...

Теперь, если "isLogging" истинно, я не хочу, чтобы они печатались. Я мог бы просто окружить их кучей утверждений if, но я бы предпочел что-то более чистое, чем это. Я подумал, что есть какой-то способ взять поток C ++ и перенаправить его так, чтобы он указывал на «ничто», чтобы при использовании оператора << ничего не печаталось. </p>

Кто-нибудь знает, как перенаправить поток, или есть какие-то идеи о том, как с этим справиться элегантно?

Спасибо, Colin

Ответы [ 7 ]

6 голосов
/ 09 июля 2009

Вы могли бы обернуть это в классе.

class Log {
  Log (fstream &s) : stream(s), enabled(false) { }
  void Enable () { enabled = true; }
  void Disable () { enabled = false; }

  template<class T>
  Log &operator<< (T const& rhs) {
    if (enabled) stream << rhs;
    return *this;
  }

private:
  fstream &stream;
  bool enabled;
};

это не проверено ... но основная идея должна быть там.

4 голосов
/ 09 июля 2009

Взгляните на rdbuf член функции . Вы можете создать буфер потока отбрасывания и связать его с вашим потоком.

struct nullbuf: std::streambuf
{
    int overflow(int c) { return traits_type::not_eof(c); }
};
1 голос
/ 09 июля 2009

std :: iostream не разрешает перенаправление на уровне ОС, однако вы можете совместно использовать std :: streambufs между std :: iostreams:

int main() {
    // redirect stdout to stderr:
    std::streambuf * const oldstdout = std::cout.rdbuf();
    std::cout.rdbuf( std::cerr.rdbuf() );

    // test
    std::cout << "Hello ";
    std::cerr << "World" << std::endl;

    // re-set, so streambufs are properly deleted:
    std::cout.rdbuf( oldstdout );

    // test
    std::cout << "Hello ";
    std::cerr << "World" << std::endl;

    return 0;
}

Таким образом, вы можете перенаправить ведение журнала куда-либо еще (например, "/ dev / null" :) или, если вы следуете ответу avakar, использовать nullbuf.

0 голосов
/ 09 июля 2009

В разделе «Другие идеи о том, как справиться с этим»:

  1. Используйте шаблон состояний, чтобы исключить необходимость проверок if для всего кода.
  2. Использовать шаблон политики (шаблон стратегии времени компиляции) с объектом политики ведения журнала.
0 голосов
/ 09 июля 2009
std::ostream& Debug(int level) {
  std::clog.clear(levell <= shown_level ? std::ios_base::goodbit: std::ios_base::badbit);
  return std::clog;
}

С comp.lang.c ++ .

0 голосов
/ 09 июля 2009

Я использую функцию ведения журнала библиотеки POCO. Он поддерживает настройку каналов - консоль, файл, оба. Настройка формата выходных данных и уровней ведения журнала (трассировка, отладка, ошибка и т. Д.). Затем я окружаю функции регистрации такими функциями, как

inline void logError(const std::string & str)
{
#ifdef COMPILE_ERROR_LOGGING
   g_pMyPocoLogger->error(str);
#endif
}

Вы можете не использовать библиотеку, но я все же рекомендую окружить ваш журнал оболочкой.

0 голосов
/ 09 июля 2009

платформа? если вы работаете в Unix, вы можете записать файл в / dev / null

...