2012-01-20 11 views
18

estaba leyendo el "C++ Cookbook", que tenía el siguiente fragmento:Mezcla cout y wcout mismo programa en

// cout << s << std::endl; // You shouldn't be able to 
wcout << ws << std::endl;  // run these at the same time 

Si está interesado en ver el ejemplo real, aquí es a link to the page on Google books.

Además, encontré este SO question que parece indicar que mezclar wcout y cout está bien. ¿Podría alguien explicarme de qué está hablando este comentario?

EDITAR

De C++ estándar [27.4.1]:

operaciones de mezcla en correspondiente ancha y estrecha-streams de caracteres sigue la misma semántica que la mezcla de tales operaciones en los ficheros, como se especifica en la Enmienda 1 del estándar ISO C.

De C Standard [7.19.2]:

Cada flujo tiene una orientación. Después de asociar un flujo con un archivo externo, pero antes de que se realicen operaciones en él, el flujo es sin orientación. Una vez que se ha aplicado una función de entrada/salida amplia de caracteres a una secuencia sin orientación, la transmisión se convierte en una secuencia orientada en gran medida. De forma similar, una vez que se ha aplicado una función de entrada/salida de un byte a en una secuencia sin orientación, la transmisión se convierte en una secuencia orientada por bytes. Solo una llamada a la función freopen o la función fwide puede alterar la orientación de una transmisión. (Una llamada exitosa a freopen elimina cualquier orientación.)

Las funciones de entrada/salida de bytes no se aplicarán a un flujo orientado a gran angular y las funciones de entrada/salida de caracteres no se aplicarán a un flujo orientado a bytes.

Por lo tanto, el estándar parece decir que no debe mezclarlos. Sin embargo, encontré esta cita from this article:

Para Visual C++ 10.0 la función fwide está documentada como no implementada. Y desde un punto de vista práctico, al menos a nivel de salida de líneas enteras, aparentemente funciona bien para mezclar el uso de cout y wcout. Por lo tanto, felizmente, aparentemente Visual C++ simplemente ignora los requisitos de la norma y no mantiene una orientación de flujo C FILE impracticable.

Y también, en relación con gcc encontré esta cita de here:

Esta es una (nueva) característica, no un error, consulte libstdC++/11705 y en la búsqueda general sobre la orientación corriente en el Estándar C (C99, 7.19.2). En resumen, no puede mezclar E/S orientadas a bytes y de gran amplitud. Por ahora, debido al error señalado en libstdC++/11705, puede obtener algo cercano a sus expectativas llamando a std :: ios :: sync_with_stdio (false); al comienzo de su programa.

Respuesta

16

Cuando se llama por primera vez a cout o wcout, se establece la orientación para stdout. En el caso de cout, stdout se convierte en un flujo orientado a bytes, y en el caso de wcout, stdout se convierte en un flujo orientado en gran medida. Según el estándar C++ [27.4.1] y el estándar C [7.19.2], una vez que se establece la orientación de una secuencia, no debe llamar a una función que no sea compatible con la orientación de esa secuencia.

2

No tengo ni idea.

Prohibición de subprocesos, no puede ejecutar cualquiera dos declaraciones "al mismo tiempo". Sin embargo, puedes usar cout y wcout en diferentes puntos de tu programa. Ambos se asignan al STDOUT y eso es todo ... aunque puede que falle en los buffers y obtenga pedidos inesperados, en algunos casos.

Al parecer, cada imbuye una orientación en el "destino" corriente STDOUT, y no se permite mezclar las operaciones en una corriente que ha sido impregnada con una orientación [C++11: 27.4.1] y [C99: 7.19.2].

+0

En realidad revisé la página de erratas del libro porque pensé que podría ser un error, pero no pude encontrar nada. –

+0

@Jesse: es hora de contactar al autor, quizás. –

+0

¿Puede explicar a qué se refiere y qué sucede en realidad: "Ambos se asignan a STDOUT"? , Gracias –

1

Técnicamente, definitivamente puede usar las secuencias angosta y ancha simultáneamente. Sin embargo, es probable que el resultado sea un error, a menos que haga arreglos para que ambos codifiquen los caracteres de la misma manera. Desafortunadamente, esto viene con la advertencia de que no puede controlar las codificaciones utilizadas por los objetos de transmisión estándar, al menos de forma no portátil. Incluso si la codificación es la misma, debe asegurarse de que los caracteres parciales estén completamente escritos, es decir, cuando menos necesite vaciar el búfer al cambiar al otro ancho.

+0

¿'imbue' no está definido para las transmisiones en el estándar o cómo debería interpretar esto? – Voo

+1

@Voo 'imbue()' en realidad ** está ** definido para todos los objetos de transmisión. Sin embargo, el único buffer de flujo requerido para hacer uso de 'std :: codecvt <...>' es 'std :: basic_filebuf <...>'. Sin embargo, los objetos de flujo estándar no son necesarios para usar este tipo de almacenamiento intermedio de flujo. Pueden usar 'std :: basic_filebuf <...>' pero no contaría con esto, en parte porque no puedo imaginar que lo implemente de esa manera.En realidad, debería verificar el estándar de C++ 2011 para esto: definitivamente fue cierto en C++ 2003, pero no creo que haya cambiado. –

+0

Eso es interesante: solo he usado 'imbue' para archivos en los que funcionó bien, pero implícitamente esperaba que esto funcionara también para los objetos de transmisión estándar. Es bueno saberlo, pero hay una razón por la que nunca lo necesité para las transmisiones estándar en primer lugar, así que probablemente no sea un gran problema en la práctica. – Voo

1

Violar "no debe" s de la norma generalmente te lleva al dominio de un comportamiento indefinido. El comportamiento indefinido podría funcionar correctamente en algunas implementaciones.

0

Como una conjetura: cout y wcout son dos flujos diferentes, y las citas que proporciona no dicen nada sobre cómo la orientación de la secuencia se correlaciona con la orientación del archivo subyacente. ¿Puede ser que las corrientes reorienten silenciosamente stdout debajo del capó?