Независимая от платформы /dev/null в C++
Возможный дубликат:
Реализация no-op std::ostream
Есть ли потоковый эквивалент NULL в C++? Я хочу написать функцию, которая принимает поток, если пользователь хочет, чтобы внутренний вывод был куда-то, но если нет, вывод идет в какое-то поддельное место
void data(std::stream & stream = fake_stream){
stream << "DATA" ;
}
я хочу быть в состоянии сделать выбор data()
или же data(std::cout)
3 ответа
Редактировать: взято из @Johannes Schaub - письмо Литба здесь с небольшими изменениями:
template<typename Ch, typename Traits = std::char_traits<Ch> >
struct basic_nullbuf : std::basic_streambuf<Ch, Traits> {
typedef std::basic_streambuf<Ch, Traits> base_type;
typedef typename base_type::int_type int_type;
typedef typename base_type::traits_type traits_type;
virtual int_type overflow(int_type c) {
return traits_type::not_eof(c);
}
};
// convenient typedefs
typedef basic_nullbuf<char> nullbuf;
typedef basic_nullbuf<wchar_t> wnullbuf;
// buffers and streams
// in some .h
extern std::ostream cnull;
extern std::wostream wcnull;
// in a concrete .cpp
nullbuf null_obj;
wnullbuf wnull_obj;
std::ostream cnull(&null_obj);
std::wostream wcnull(&wnull_obj);
Используйте те:
void data(std::ostream& stream = cnull){
// whatever...
}
Теперь, это выглядит круто и все, но следующее намного короче и работает, потому что, если нулевой указатель предоставляется конструктору ostream
, он автоматически устанавливает badbit и молча игнорирует любые записи:
// in .h
extern std::ostream cnull;
extern std::wostream wcnull;
// in .cpp
std::ostream cnull(0);
std::wostream wcnull(0);
Стандарт гарантирует, что это работает, начиная с 27.6.2.2 [lib.ostream.cons] p1
который описывает конструктор ostream
это берет указатель на streambuf
:
Эффекты: Создает объект класса
basic_ostream
, присваивая начальные значения базовому классу, вызываяbasic_ios<charT,traits>::init(sb)
,
Соответствующая функция из basic_ios
, 27.4.4.1 [lib.basic.ios.cons] p3
:
void init(basic_streambuf<charT,traits>* sb);
Постусловия: постусловия этой функции указаны в таблице 89:
Важная строка из таблицы 89:
rdstate () - goodbit, если sb не является нулевым указателем, иначе badbit.
Что произойдет, если badbit
установлен описан под 27.6.2.6 [lib.ostream.unformatted]
:
Каждая неотформатированная выходная функция начинает выполнение с создания объекта класса
sentry
, Если этот объект возвращает true при преобразовании в значение типа bool, функция пытается сгенерировать запрошенный вывод.
Это означает, что в случае sentry
ложно, это не так. Вот как sentry
превращается в bool
, взято из 27.6.2.3 [lib.ostream::sentry] p3 & p5
:
3) Если после какой-либо подготовки
os.good()
являетсяtrue
,ok_ == true
иначе,ok_ == false
,5)
operator bool();
Эффекты: возвращает ok_.
(ok_
является членом ostream::sentry
типа bool
.)
Обратите внимание, что эти кавычки все еще присутствуют в C++11, просто в разных местах. По порядку появления в этом ответе:
27.6.2.2 [lib.ostream.cons] p1
=>27.7.3.2 [ostream.cons] p1
27.4.4.1 [lib.basic.ios.cons] p3
=>27.5.5.2 [basic.ios.cons]
- Таблица 89 => Таблица 128
27.6.2.6 [lib.ostream.unformatted]
=>27.7.3.7 [ostream.unformatted] p1
27.6.2.3 [lib.ostream::sentry] p3 & p5
=>27.7.3.4 [ostream::sentry] p4 & p5
Файл Linux /dev/null - это черная дыра, которую вы ищете. В Windows есть устройство под названием NUL:. Я никогда не пытался открыть этот файл, но я использовал его из командной строки
Вы можете попробовать ostream(NULL,false), первый вход - целевой выход, и я не знаю, что означает второй ввод exaclty, но после отслеживания кода кажется, что ostream просто некуда писать, вызывая operator <<
просто игнорируется ostream. Я имею в виду, что при первом вызове состояние меняется на плохое, и после этого оно всегда игнорирует входные данные из-за состояния потока, поэтому вы можете использовать следующий код:
void data(std::ostream & stream = ostream(NULL,false)){
stream << "DATA" ;
}