32

I was reading the "C++ Cookbook" which had the following snippet:

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

If you're interested in seeing the actual example, here is a link to the page on Google books.

Also, I found this SO question which seems to state that mixing wcout and cout is okay. Could someone explain to me what this comment is talking about?

EDIT

From C++ Standard [27.4.1]:

Mixing operations on corresponding wide- and narrow-character streams follows the same semantics as mixing such operations on FILEs, as specified in Amendment 1 of the ISO C standard.

From C Standard [7.19.2]:

Each stream has an orientation. After a stream is associated with an external file, but before any operations are performed on it, the stream is without orientation. Once a wide character input/output function has been applied to a stream without orientation, the stream becomes a wide-oriented stream. Similarly, once a byte input/output function has been applied to a stream without orientation, the stream becomes a byte-oriented stream. Only a call to the freopen function or the fwide function can otherwise alter the orientation of a stream. (A successful call to freopen removes any orientation.)

Byte input/output functions shall not be applied to a wide-oriented stream and wide character input/output functions shall not be applied to a byte-oriented stream.

So, the standard seems to say that you should not mix them. However, I found this quote from this article:

For Visual C++ 10.0 the fwide function is documented as being unimplemented. And from a practical point of view, at least at the level of outputting whole lines it apparently works fine to intermingle use of cout and wcout. So, happily, Visual C++ apparently just disregards the standard’s requirements and does not maintain an impractical explicit C FILE stream orientation.

And also, concerning gcc I found this quote from here:

This is a (new) feature, not a bug, see libstdc++/11705 and in general search about stream orientation in the C standard (C99, 7.19.2). In a nutshell you cannot mix byte oriented and wide oriented I/O. For now, due to the bug pointed out in libstdc++/11705, you can obtain something close to your expectations by calling std::ios::sync_with_stdio(false); at the beginning of your program.

Community
  • 1
  • 1
Jesse Good
  • 50,901
  • 14
  • 124
  • 166

6 Answers6

32

When cout or wcout is called for the first time, the orientation for stdout becomes set. In the case of cout, stdout becomes a byte-oriented stream, and in the case of wcout, stdout becomes a wide-oriented stream. Per the C++ standard [27.4.1] and C standard [7.19.2], once the orientation of a stream is set, you should not call a function which is not compatible with the orientation of that stream.

Marc.2377
  • 7,807
  • 7
  • 51
  • 95
Jesse Good
  • 50,901
  • 14
  • 124
  • 166
4

Violating "shall not"s from the standard usually lands you in the realm of undefined behavior. Undefined behavior might very well work properly on some implementations.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
3

Technically, you can definitely use both the narrow and the wide streams simultaneously. The result is, however, likely to be messed up unless you arrange for both of them to encode characters the same. This, unfortunately, comes with the caveat that you can't control the encodings used by the standard stream objects, at least not portably. Even if the encoding is the same, you need to make sure that partial characters are completely written, i.e. at the very least you need to flush the buffer when switching to the other width.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • Is `imbue` not defined for streams in the standard or how should I interpret this? – Voo Jan 20 '12 at 21:38
  • 2
    @Voo `imbue()` actually **is** defined for all of the stream objects. However, the only stream buffer required to make use of `std::codecvt<...>` is `std::basic_filebuf<...>`. However, the standard stream objects are not required to use this kind of stream buffer. They may use `std::basic_filebuf<...>` but I wouldn't count on it, partially because I can't imagine that I would implement it that way. Actually, I should check the C++2011 standard for this: it was definitely true in C++2003 but I don't think it has changed. – Dietmar Kühl Jan 20 '12 at 21:45
  • That's interesting - I only ever used `imbue` for files where it did work fine, but I implicitly expected this to work for the standard stream objects as well. Good to know - but then there's a reason I never needed it for the standard streams in the first place so it's probably no big deal in practice.. – Voo Jan 20 '12 at 22:03
  • @Voo I seem to recall that even for file streams there are restriction on the effect of calling `imbue()`. In particular, if there were characters already read or a seek executed, I think the encoding isn't required to change. – Dietmar Kühl Jan 20 '12 at 22:11
  • 1
    According to what I found, you shouldn't mix them, however, some implementations allow it (see my edits). – Jesse Good Jan 20 '12 at 22:29
  • @Jesse: Yes, you are right. It is while I looked at it and I remembered the state diagram wrongly (see e.g. [Dinkumware's documentation]{http://www.dinkumware.com/manuals/default.aspx?manual=compleat&page=lib_file.html} for a nice picture of what is supported): I thought a seek takes you back to "unbound" but apparently it does not... – Dietmar Kühl Jan 20 '12 at 22:52
2

I have no idea.

Barring threads, you can't run any two statements "at the same time". You can certainly use cout and wcout at different points in your program, though. They both map to STDOUT and that's that... though you may fall foul of differing buffers and get slightly unexpected ordering, in some cases.

Apparently, each imbues an orientation on the "destination" stream STDOUT, and it is not allowed to mix operations on a stream that has been imbued with an orientation [C++11: 27.4.1] and [C99: 7.19.2].

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0
  • if sync with stdio is enabled
    • if cout is first called, the standard output stream is byte oriented;
    • if wcout is first called, the standard output stream is wide byte oriented;
  • if sync with stdio is disabled - std::ios::sync_with_stdio(false);
    • the standard output stream is always undecided.

try this code

#include <iostream>                                                             
#include <fstream>                                                              
                                                                                
void checkStdoutOrientation()                                                   
{                                                                               
    std::fstream fs("result.txt", std::ios::app);                               
    int ret = fwide(stdout, 0);                                                 
    if (ret > 0) {                                                              
        fs << "wide byte oriented\n";                                           
    } else if (ret < 0) {                                                       
        fs << "byte oriented\n";                                                
    } else {                                                                    
        fs << "undecided oriented\n";                                           
    }                                                                           
    fs.close();                                                                 
}

int main()
{
    std::ios::sync_with_stdio(false);                                           
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    std::cout << "123" << std::endl;                                            
                                                                                
    checkStdoutOrientation();                                                   
                                                                                
    std::wcout << "456" << std::endl;                                           
                                                                                
    checkStdoutOrientation();                                                   
                                                                                                       
    return 0;
}        

I execute it in Debian10+GCC8.3.0, the result:

Output:
enter image description here

result.txt:
enter image description here

name-1001
  • 120
  • 2
  • 4
0

As a guess: cout and wcout are two different streams, and the quotes you provide say nothing about how stream orientation correlates with underlying file's orientation. May it be that the streams silently reorient stdout under the hood?

vines
  • 5,160
  • 1
  • 27
  • 49