Existe-t-il une implémentation de null std::ostream dans C++ ou les bibliothèques?

je cherche un std::ostream implémentation qui agit comme /dev/null . Il serait tout simplement ignorer tout ce qui est diffusé. Existe-t-il une telle chose dans les bibliothèques standard ou Boost? Ou dois-je roule mes propres?

39
demandé sur svick 2011-11-23 18:22:30

4 réponses

si vous avez boost, alors il y a une implémentation nulle ostream & istream disponible dans boost/iostream/device/null.hpp . L'essentiel:

#include "boost/iostreams/stream.hpp"
#include "boost/iostreams/device/null.hpp"
...
boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
...
18
répondu Ylisar 2011-11-23 15:00:14

la solution la plus simple est simplement d'utiliser un std::ofstream non ouvert . Ce entraînera dans un état d'erreur dans le flux, mais la plupart des outputters ne vérifiez ceci; l'idiome habituel est de laisser le chèque à la fin, après le (ce qui le mettrait dans le code que vous avez écrit, où vous savez que le flux doit être valide).

sinon, c'est assez simple à mettre en œuvre: il suffit de créer un streambuf qui contient un petit tampon, et le met en place dans overflow (toujours de retour succès). Notez que ce sera plus lent que l' le fichier non ouvert, cependant; les divers opérateurs >> seront encore à tous les la conversion (ce qu'ils ne font pas si le flux a un État d'erreur).

EDIT:

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

il est habituel de fournir une classe de commodité dérivée de istream ou ostream ainsi, qui contiendra une instance de ce tampon qu'il utilise. Quelque chose du genre:

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

Ou vous pouvez simplement utiliser un std::ostream , en passant l'adresse de le streambuf.

21
répondu James Kanze 2013-07-18 09:59:30

si vous définissez badbit sur un flux, il ne produira rien:

#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";
}

sorties:

a
c
15
répondu Maxim Egorushkin 2011-11-23 14:31:07

je sais que c'est un fil très ancien, mais je voudrais ajouter ceci à quiconque est à la recherche de la même solution sans boost et et le plus rapide.

j'ai combiné trois propositions différentes ci-dessus et une en écrivant directement à /dev/null (donc cela implique le noyau.)

étonnamment, le NullStream qui a obtenu le plus de votes a réalisé le pire.

Voici les résultats pour 100,000,000 écrit:

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)

voici le code d'essai

#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;
}

MODIFIER

la solution la plus rapide - où nous utilisons badbit - présente un inconvénient. Si le programme vérifie si la sortie est correctement écrit - et je n'ai aucune idée pourquoi le programme ne devrait pas le faire - il échouera à cause de cette badbit. Par conséquent, le second - boost - est le gagnant.

5
répondu Grzegorz 2018-09-19 17:00:36