2011-06-05 9 views
21

Duplicar posible:
Implementing a no-op std::ostreamIndependiente de la plataforma/dev/null en C++

¿Hay alguna corriente equivalente a NULL en C++? Quiero escribir una función que toma en una corriente si el usuario quiere tener emite el interior de algún lugar, pero si no es así, la salida va a algún lugar falso

void data(std::stream & stream = fake_stream){ 
    stream << "DATA" ; 
} 

Quiero ser capaz de elegir que hacer data() o data(std::cout)

+2

usted está buscando una especie de "agujero negro" corriente que también puedes escribir pero que no hace nada con los datos? Podría derivar uno, supongo, pero la mayoría de las personas simplemente verificaría que el puntero de flujo no sea NULL antes de intentar escribir en él. –

+1

¿Qué significa '" pero destruido si no "' significa? ¿Por qué no escribes pseudocódigo para aclarar tu pregunta? – Nawaz

+0

como en: no me importa a dónde va, siempre que aparezca en cualquier lugar donde un usuario verifique, como un archivo, o la terminal – calccrypto

Respuesta

33

Editar: Tomado de @Johannes Schaub - electrónico de litb here con ligeras modificaciones:

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); 

utilizar esos:

void data(std::ostream& stream = cnull){ 
    // whatever... 
} 

Ahora bien, esto se ve bien y todo, pero el siguiente es camino más corto y las obras, ya que si se proporciona un puntero nulo al constructor de ostream, que ajusta automáticamente la badbit y silenciosamente ignora cualquier escritura :

// in .h 
extern std::ostream cnull; 
extern std::wostream wcnull; 

// in .cpp 
std::ostream cnull(0); 
std::wostream wcnull(0); 

las garantías estándar esto funciona, a partir de 27.6.2.2 [lib.ostream.cons] p1 que describe el constructor de ostream que toma un puntero a una streambuf:

Efectos: Construye un objeto de la clase basic_ostream, asignando valores iniciales a la clase base llamando al basic_ios<charT,traits>::init(sb).

La función relevante de basic_ios, 27.4.4.1 [lib.basic.ios.cons] p3:

void init(basic_streambuf<charT,traits>* sb);
Postcondiciones: Las condiciones posteriores de esta función se indican en la Tabla 89:

La fila importante de la Tabla 89:

rdstate() - goodbit si sb no es un puntero nulo, de lo contrario es badbit.

¿Qué pasa si el badbit se establece que se describe en 27.6.2.6 [lib.ostream.unformatted]:

Cada función de salida sin formato se inicia la ejecución mediante la construcción de un objeto de clase sentry. Si este objeto devuelve verdadero, mientras se convierte a un valor de tipo bool, la función intenta generar la salida solicitada.

Esto implica que, en caso de que sentry sea falso, no es así.Aquí es cómo la sentry convierte a bool, tomada de 27.6.2.3 [lib.ostream::sentry] p3 & p5:

3) Si, después de que se complete cualquier preparación, os.good() es true, ok_ == true lo contrario, ok_ == false.

5) operator bool();
Efectos: Devuelve ok_.

(ok_ es miembro de ostream::sentry de tipo bool.)


Tenga en cuenta que estas citas están todavía presentes en C++ 11, sólo que en diferentes lugares. En orden de aparición en esta respuesta:

  • 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]
  • Tabla 89 => Tabla 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
+0

Gracias por la buena respuesta. ¿Hay una diferencia en 'os.good()' para los dos esquemas? Con 'std :: ostream os (nullptr)', 'assert (os)' fallará mientras que con 'std :: ostream os (& nullobj)', 'assert (os)' no? Solo estoy adivinando. – Hugues

1

Linux file/dev/null es un agujero negro como el que está buscando. En Windows hay un dispositivo llamado NUL :. Nunca intenté abrir ese archivo, pero lo he usado desde la línea de comandos

+0

... podría hacer lo mismo sin abrir estos archivos especiales. Técnicamente, todo lo que tienes que hacer es aceptar argumentos en tu sobrecarga << << 'y simplemente no hacer nada con ellos. –

+0

eso es cierto. pero el usuario todavía tendría que crear la secuencia en primer lugar – calccrypto

+0

y cómo la usaría?'std :: ostream stream = NUL' y' std :: ostream stream = std :: ostream (NUL) 'no funcionan como parámetros – calccrypto

-1

puedes probar ostream (NULL, false), la primera entrada es el resultado final y no sé cuál es la segunda entrada significa exactamente, pero después del código de rastreo parece que solo porque ostream no tiene ningún lugar donde escribir, la llamada a operator << es simplemente ignorada por ostream. Es decir, en los primeros cambios de estado de llamada al mal y después de que siempre está ignorando los datos de entrada a causa de estado corriente, por lo que puede utilizar el siguiente código:

void data(std::ostream & stream = ostream(NULL,false)){ 
    stream << "DATA" ; 
} 
+3

-1, esto no funcionará. Un temporal solo puede vincularse a una referencia 'const T &', pero no se puede escribir un flujo constante. Creo que MSVC permite esto como una extensión, pero ... – Xeo

+0

funciona y se compila con vC++ pero parece tener algunos problemas con gcc. – Ali1S232

Cuestiones relacionadas