Mescolando cout e wcout nello stesso programma

Stavo leggendo il “C ++ Cookbook” che aveva il seguente frammento:

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

Se sei interessato a vedere l’esempio, ecco un link alla pagina su Google books .

Inoltre, ho trovato questa domanda SO che sembra affermare che mescolare wcout e cout è ok. Qualcuno potrebbe spiegarmi di cosa sta parlando questo commento?

MODIFICARE

Da C ++ Standard [27.4.1]:

Le operazioni di missaggio su stream corrispondenti di caratteri ampi e stretti seguono la stessa semantica della combinazione di tali operazioni su FILE, come specificato nell’emendamento 1 dello standard ISO C.

Da C Standard [7.19.2]:

Ogni stream ha un orientamento. Dopo che un stream è associato a un file esterno, ma prima che vengano eseguite le operazioni su di esso, lo stream non ha orientamento. Una volta che una funzione di input / output di caratteri estesi è stata applicata a un stream senza orientamento, il stream diventa un stream orientato all’ampia gamma. Allo stesso modo, una volta che una funzione di input / output di byte è stata applicata a un stream senza orientamento, il stream diventa un stream orientato ai byte. Solo una chiamata alla funzione freopen o alla funzione fwide può altrimenti modificare l’orientamento di un stream. (Una chiamata riuscita a freopen rimuove qualsiasi orientamento.)

Le funzioni di input / output dei byte non devono essere applicate a un stream wide-oriented e le funzioni di input / output di caratteri estesi non devono essere applicate a un stream orientato ai byte.

Quindi, lo standard sembra dire che non dovresti mescolarli. Tuttavia, ho trovato questa citazione da questo articolo :

Per Visual C ++ 10.0 la funzione fwide è documentata come non implementata. E da un punto di vista pratico, almeno a livello di emissione di intere linee, a quanto pare funziona bene a mescolare l’uso di cout e wcout. Quindi, per fortuna, Visual C ++ sembra ignorare semplicemente i requisiti dello standard e non mantiene un orientamento del stream C FILE esplicito.

E anche, riguardo a gcc ho trovato questa citazione da qui :

Questa è una (nuova) funzionalità, non un bug, vedi libstdc ++ / 11705 e in generale la ricerca sull’orientamento del stream nello standard C (C99, 7.19.2). In breve, non è ansible combinare I / O orientato ai byte e orientato alla larghezza. Per ora, a causa del bug evidenziato in libstdc ++ / 11705, puoi ottenere qualcosa di più vicino alle tue aspettative chiamando std :: ios :: sync_with_stdio (false); all’inizio del tuo programma.

Quando viene chiamata per la prima volta cout o wcout , l’orientamento per lo stdout viene impostato. Nel caso di cout , lo stdout diventa uno stream orientato ai byte e, nel caso di wcout , lo stdout diventa uno stream wide-oriented. Secondo lo standard C ++ [27.4.1] e C standard [7.19.2], una volta impostato l’orientamento di un stream, non si dovrebbe chiamare una funzione che non è compatibile con l’orientamento di quel stream.

Non ne ho idea.

Esclusione di thread, non è ansible eseguire due istruzioni “allo stesso tempo”. Puoi certamente usare cout e wcout in diversi punti del tuo programma, però. Entrambi si STDOUT a STDOUT e questo è quello … anche se in alcuni casi potresti cadere in cattive condizioni di buffer diversi e ottenere ordini leggermente inaspettati.

Apparentemente, ciascuno impregna un orientamento sul stream “destinazione” STDOUT , e non è consentito mischiare operazioni su un stream che è stato imbevuto di un orientamento [C++11: 27.4.1] e [C99: 7.19.2] .

Tecnicamente, puoi usare contemporaneamente sia i flussi stretti che quelli ampi. Tuttavia, è probabile che il risultato sia incasinato a meno che non si preveda che entrambi possano codificare i caratteri allo stesso modo. Questo, sfortunatamente, viene fornito con l’avvertenza che non è ansible controllare le codifiche utilizzate dagli oggetti stream standard, almeno non in modo portabile. Anche se la codifica è la stessa, è necessario accertarsi che i caratteri parziali siano scritti completamente, vale a dire, per lo meno, è necessario svuotare il buffer quando si passa all’altra larghezza.

Violare “non deve” dallo standard di solito ti atterra nel regno del comportamento indefinito. Un comportamento indefinito potrebbe funzionare correttamente su alcune implementazioni.

Come ipotesi: cout e wcout sono due flussi diversi e le virgolette fornite non dicono nulla su come l’orientamento del stream sia correlato all’orientamento del file sottostante. Può essere che i flussi riorientino silenziosamente lo stdout sotto il cofano?