¿Hay una implementación null de std:: ostream en C++ o bibliotecas?


Estoy buscando una implementación std::ostream que actúe como /dev/null. Simplemente ignoraría cualquier cosa que se le transmita. ¿Existe tal cosa en las bibliotecas estándar o Boost? ¿O tengo que hacer el mío?

Author: svick, 2011-11-23

4 answers

Si tiene boost, entonces hay una implementación de ostream e istream null disponible en boost/iostreams/device/null.hpp . La esencia de esto:

#include "boost/iostreams/stream.hpp"
#include "boost/iostreams/device/null.hpp"
...
boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
...
 18
Author: Ylisar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-23 15:00:14

La solución más simple es usar un std::ofstream sin abrir. Este dará lugar a un estado de error en la secuencia, pero la mayoría de los outputters no marque esto; el modismo habitual es dejar la comprobación hasta el final, después de la cerrar (lo que lo pondría en el código que escribió, donde usted sabe que el stream debe ser inválido).

De lo contrario, es bastante sencillo de implementar: simplemente cree un streambuf que contiene un pequeño búfer, y lo configura en overflow (siempre devolviendo el éxito). Tenga en cuenta que esto ser más lento que el sin embargo, los distintos operadores >> seguirán la conversión (que no hacen si la secuencia tiene un estado de error).

EDITAR:

class NulStreambuf : public std::streambuf
{
    char                dummyBuffer[ 64 ];
protected:
    virtual int         overflow( int c ) 
    {
        setp( dummyBuffer, dummyBuffer + sizeof( dummyBuffer ) );
        return (c == traits_type::eof()) ? '\0' : c;
    }
};

Es habitual proporcionar una clase de conveniencia derivada de istream o ostream también, que contendrá una instancia de este buffer que utiliza. Algo parecido a:

class NulOStream : private NulStreambuf, public std::ostream
{
public:
    NulOStream() : std::ostream( this ) {}
    NulStreambuf* rdbuf() const { return this; }
};

O simplemente puede usar un std::ostream, pasando la dirección de el streambuf a ella.

 21
Author: James Kanze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-18 09:59:30

Si establece badbit en una secuencia, no generará nada:

#include <iostream>

int main() {
    std::cout << "a\n";

    std::cout.setstate(std::ios_base::badbit);
    std::cout << "b\n";

    std::cout.clear();
    std::cout << "c\n";
}

Salidas:

a
c
 15
Author: Maxim Egorushkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-23 14:31:07

Sé que este es un hilo muy antiguo, pero me gustaría agregar esto a cualquiera que esté buscando la misma solución sin boost y la más rápida.

Combiné tres propuestas diferentes arriba y una escribiendo directamente a /dev/null (por lo que involucra al kernel.)

Sorprendentemente, el NullStream que obtuvo la mayor cantidad de votos fue el peor.

Aquí están los resultados de 100,000,000 de escrituras:

a) /dev/null : 30 seconds
b) NullStream: 50 seconds
c) badbit    : 16 seconds (the winner in speed, but cannot test for errors!)
d) boost     : 25 seconds (the ultimate winner)

Aquí está el código de prueba

#include <iostream>
#include <fstream>
#include <time.h>
#include <boost/iostreams/stream.hpp>

class NullStream : public std::ostream {
    class NullBuffer : public std::streambuf {
    public:
        int overflow( int c ) { return c; }
    } m_nb;
public:
    NullStream() : std::ostream( &m_nb ) {}
};

int test( std::ostream& ofs, const char* who ) {
    const time_t t = time(NULL);
    for ( int i = 0 ; i < 1000000000 ; i++ )
        ofs << "Say the same" ;
    std::cout << who << ": " << time(NULL) - t << std::endl;
}

void devnull() {
    std::ofstream ofs;
    ofs.open( "/dev/null", std::ofstream::out | std::ofstream::app );
    test(ofs, __FUNCTION__);
    ofs.close();
}

void nullstream() {
    NullStream ofs;
    test(ofs, __FUNCTION__);
}

void badbit() {
    std::ofstream ofs;
    ofs.setstate(std::ios_base::badbit);
    test(ofs, __FUNCTION__);
}

void boostnull() {
    boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
    test(nullOstream, __FUNCTION__);
}

int main() {
    devnull();
    nullstream();
    badbit();
    boostnull();
    return 0;
}

EDITAR

El la solución más rápida, donde usamos badbit, tiene un inconveniente. Si el programa comprueba si la salida se escribe correctamente - y no tengo idea de por qué el programa no debería hacer eso - entonces fallará debido a este badbit. Por lo tanto, el subcampeón - boost - es el ganador.

 5
Author: Grzegorz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-19 17:00:36