I've a typedef char char_t
which can also be typedef wchar_t char_t
and What I want is a generic cout
.
I have a util
namespace I want an util::cout
that would be std::cout
if char_t
is char
and std::wcout
if char_t
is wchar_t
-
What about having a "template
" traits class containing a typedef for the output stream? By default it would typedef to cout and then you could add a specialization for wchar_t where the typedef would be wcout. – Alexander Chertov Aug 15 '12 at 09:44 -
But the problem is both `cout` and `wcout` is objects not type. What can hardly be done is different template overload will have different objects. – Neel Basu Aug 15 '12 at 09:50
-
Oh, I didn't realize that. Then you could have an inline function returning a reference to cout or wcout depending on the specialization. Or go with static pointers as suggested by ecatmur. – Alexander Chertov Aug 15 '12 at 09:57
3 Answers
Yes, no problem; you can do this with a template specialisation holding a static
reference to the appropriate object.
template<typename T> struct select_cout;
template<> struct select_cout<char> { static std::ostream &cout; };
std::ostream &select_cout<char>::cout = std::cout;
template<> struct select_cout<wchar_t> { static std::wostream &cout; };
std::wostream &select_cout<wchar_t>::cout = std::wcout;
std::basic_ostream<char_t> &cout = select_cout<char_t>::cout;

- 152,476
- 27
- 293
- 366
-
Yes I was thinking about something similar but without const and * . why are you using `pointer` here ? – Neel Basu Aug 15 '12 at 09:56
-
@NeelBasu good point, a reference works just as well and is clearer. Fixed. – ecatmur Aug 15 '12 at 10:01
-
@NeelBasu well, if you're putting this in a header you'll have to separate the declarations and definitions, obviously. – ecatmur Aug 15 '12 at 12:31
You're reinventing a terrible (at least in the here and now, perhaps it was a good decision at one point) design by MS.
Note that every other platform most likely uses UTF-8 for output, so a UTF-8 string through std::cout
outputs just fine. On windows, Unicode output on the console is impossible to get right anyway (due to fonts and broken console codepages).
In short, there is no reason to want such a thing, and you're better off using one or the other, not both.

- 74,642
- 33
- 187
- 332
-
The problem is I need to parse unicode files as well. So In Linux I can use `std::string` for that, in Windows Iam using `std::wstring` and I cannot use wstring on cout. there will be compilation problem. – Neel Basu Aug 15 '12 at 09:53
-
@NeelBasu You should be able to imbue your input stream so that it returns UTF-8. Or you could just use UTF-16/UTF-32 everywhere (and imbue the correct encoding). – James Kanze Aug 15 '12 at 10:04
-
1The "terrible design" that you speak of is using UTF-16? Yeah, hindsight is 20/20, but it seems like there are certainly far worse decisions that get made every day. What is your actual real-world solution to this problem? How do you write code that works on Windows? – Cody Gray - on strike Aug 15 '12 at 10:44
-
@Cody: no, the terrible design being the whole `TCHAR` mess and API function defines dependent on `UNICODE` (or was that `_UNICODE`, or both?). There's nothing wrong with UTF-16 over UTF-8. UTF-32 has some pros and contra's over UTF-8/16 though. The way I write code is use `std::string` internally as UTF-8 (though I don't give unicode much thought) and convert at the application/Windows API boundary using `MultiByteToWideChar` API and call the `*W` functions exclusively. This includes using Windows API calls for command line arguments. All in all, a very thin compatibility layer IMHO. – rubenvb Aug 15 '12 at 11:00
If you are reading files in wide format and using a multibyte program which i picked up from the comments, a solution could be . . .
You can read the file content as a std::wstring
in to your programs memory and the use wcstombs_s()
to convert the string read from the file in to a multi-byte character string.
Essentially it doesn't matter which format the string is you can always change it when and where needed.