Je recherche un std::ostream
implémentation qui agit comme /dev/null
. Il ignorerait simplement tout ce qui y est diffusé. Une telle chose existe-t-elle dans les bibliothèques standard ou Boost? Ou dois-je rouler le mien?
Si vous avez boost, alors il y a une implémentation nulle ostream & istream disponible dans boost/iostreams/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() ) );
...
La solution la plus simple consiste simplement à utiliser un std::ofstream
Non ouvert. Cela se traduira par un état d'erreur dans le flux, mais la plupart des éditeurs ne vérifieront pas cela; l'idiome habituel est de laisser la vérification à la fin, après la fermeture (ce qui le mettrait dans le code que vous avez écrit, où vous savez que le flux devrait être invalide).
Sinon, il est assez simple à implémenter: créez simplement un streambuf
qui contient un petit tampon, et configurez-le dans overflow
(toujours avec succès). Notez que ce sera plus lent que le fichier non ouvert, cependant; les différents opérateurs >>
effectueront toujours la totalité de la conversion (ce qu'ils ne font pas si le flux a un état d'erreur).
ÉDITER:
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;
}
};
Il est habituel de fournir également une classe de commodité dérivée de istream
ou ostream
, qui contiendra une instance de ce tampon qu'il utilise. Quelque chose dans le sens de:
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 lui passant l'adresse du streambuf.
Si vous définissez badbit
sur un flux, cela 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";
}
Les sorties:
a
c
Je sais que c'est un fil très ancien, mais je voudrais l'ajouter à tous ceux qui recherchent la même solution sans boost et la plus rapide.
J'ai combiné trois propositions différentes ci-dessus et une en écrivant directement dans/dev/null (cela implique donc le noyau.)
Étonnamment, le NullStream qui a obtenu le plus de votes a donné le pire.
Voici les résultats de 100 000 000 d'écritures:
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 de test
#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 le badbit - a un inconvénient. Si le programme vérifie si la sortie a été écrite avec succès - et je ne sais pas pourquoi le programme ne devrait pas faire cela - alors il échouera à cause de cette erreur. Par conséquent, le runner up - boost - est le gagnant.
Pour moi, le moyen le plus simple serait:
#include <fstream>
std::ostream* out = &std::cout;
std::ostream* nullstream() {
static std::ofstream os;
if (!os.is_open())
os.open("/dev/null", std::ofstream::out | std::ofstream::app);
return &os;
}
int main() {
*out << "Normal output\n";
out = nullstream();
*out << "Will not visible\n";
out = &std::cout;
*out << "Back again\n";
return 0;
}
Ou utilisez l'indicateur 'badbit' au lieu de '/ dev/null' dans la fonction 'nullstream' comme décrit ci-dessus.
std::ostream* nullstream() {
static std::ofstream os;
static bool flag_set = false;
if (!flag_set) {
os.setstate(std::ios_base::badbit);
flag_set = true;
}
return &os;
}
Puisse cette solution surmonter le problème de performances sans utiliser boost:
#include <ostream>
class dev0_buffer : public std::streambuf
{
//called usually for n-characters
std::streamsize xsputn (const char* s, std::streamsize n) override { return n; }
//may not required due it's not called anymore
int overflow (int c) override { return c; }
} nirwana;
class dev0_stream : public std::ostream
{
public:
dev0_stream(): std::ostream(&nirwana){}
};