What does it take to specialize basic_i/ostream?

Pages: 12
Aug 15, 2012 at 5:20pm
I tried to specialize basic_ostream and basic_iostream for the new character types like this in the <iostream> header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  typedef basic_ostream<char16_t> u16ostream;
  typedef basic_ostream<char32_t> u32ostream;
  
  typedef basic_istream<char16_t> u16istream;
  typedef basic_istream<char32_t> u32istream;

  extern u16istream u16cin;		/// Linked to standard input
  extern u16ostream u16cout;		/// Linked to standard output
  extern u16ostream u16cerr;		/// Linked to standard error (unbuffered)
  extern u16ostream u16clog;		/// Linked to standard error (buffered)
  
  extern u32istream u32cin;		/// Linked to standard input
  extern u32ostream u32cout;		/// Linked to standard output
  extern u32ostream u32cerr;		/// Linked to standard error (unbuffered)
  extern u32ostream u32clog;		/// Linked to standard error (buffered) 

But it reports linker errors. Is there something I'm missing, or is it simply impossible for now?
Last edited on Aug 15, 2012 at 5:20pm
Aug 15, 2012 at 5:26pm
Aug 15, 2012 at 5:46pm
This is the error:
The linker wrote:
[Linker error] c:/program files/novi_mingw/mingw/bin/../lib/gcc/i686-pc-mingw32/4.7.1/../../../../include/c++/4.7.1/bits/basic_string.h:2755: undefined reference to `std::u16cout'
¿Did you instantiate them?
How are cin and cout insantiated? I didn't find anything else so I did just what I saw the library do for cin and cout.
Aug 15, 2012 at 5:54pm
When you use extern you say that that variable is global and shared by all the sources of your project.
However there must be one that instantiate it. You need to put u16istream u16cin; //any constructor that you like in one cpp
Aug 15, 2012 at 6:56pm
But what constructor? I can't use the default or the copy constructor because they are private, so I can only use the one that takes a streambuf*. But then how to make that streambuf? It has NO public constructors! Absolutely none! So how am I supposed to do that?
Aug 16, 2012 at 6:05am
Bump
Aug 16, 2012 at 7:23am
So how am I supposed to do that?

Look at this:

http://www.cplusplus.com/reference/iostream/streambuf/

You cannot use streambuf directly. Use filebuf or stringbuf

This is an abstract base class, therefore no objects can be directly instantiated from it. The standard hierarchy defines two classes derived from this one that can be used to directly instantiate objects: filebuf and stringbuf.


but to achieve that it behaves like the original cin/cout you have to make your own streambuf. It's not impossible...
Aug 16, 2012 at 9:53am
OK, I'll try that out, but how are cin and cout made? They have to be constructed somehow!
Last edited on Aug 16, 2012 at 10:04am
Aug 16, 2012 at 11:09am
Wow I did it without making my own streambuf!
1
2
u16ostream std::u16cout(reinterpret_cast<basic_streambuf<char16_t>*>
						(wcout.rdbuf()));

And it works and prints UTF-16 characters perfectly! But it's only because wchar_t has the same size as char16_t... I don't know how I'm gonna do it for char32_t...
Aug 16, 2012 at 12:21pm
Oh, and although I made u16cout work, u16cin reports std::bad_cast! Does anyone know why?
Last edited on Aug 16, 2012 at 12:22pm
Aug 16, 2012 at 1:02pm
Anyone? Please?
Aug 16, 2012 at 1:04pm
But it's only because wchar_t has the same size as char16_t

Which is actually a Windows defect: wchar_t is intended to be able to represent every code point, but it doesn't on Windows. wchar_t is 32-bit on other systems.

As for wrapping cin/cout, that's what std::wbuffer_convert is for.
Aug 16, 2012 at 1:58pm
But a conversion from char16_t to char looses information, doesn't it?
Alo, which of the codecvt facets should I use?
Aug 16, 2012 at 2:05pm
Actually, I don't even have std::wbuffer_convert or codecvt! And, can anyone answer why the output works, but the input doesn't(std::bad_cast)
Aug 16, 2012 at 2:55pm
Why does it throw bad_cast in an input operation? I highly doubt there is a dynamic_cast somewhere in the extraction operator definition, so why does it happen??
Aug 16, 2012 at 2:58pm
There's no telling what havoc that reinterpet_cast could wreck. Someone could dig through your library implementation, but would it be helpful?
Aug 16, 2012 at 5:11pm
I don't know! u16cout, u16cerr and u16clog all work with no problem! And the problem is in *some* dynamic_cast my u16cin is supposed to run, but I don't know where, when or how!
Aug 18, 2012 at 5:01am
Bump, please help!
Aug 18, 2012 at 6:52am
Use std::wbuffer_convert<> http://en.cppreference.com/w/cpp/locale/wbuffer_convert
in conjunction with std::codecvt_utf8<> (utf-8 to UCS2, utf-8 to UCS4) http://en.cppreference.com/w/cpp/locale/codecvt_utf8
or std::codecvt_utf8_utf16<> (utf-8 to utf-16) http://en.cppreference.com/w/cpp/locale/codecvt_utf8_utf16

Aug 18, 2012 at 10:53am
I wrote:
Actually, I don't even have std::wbuffer_convert or codecvt!

If I do this:
1
2
3
4
5
6
7
8
#include <locale>

using namespace std;

int main()
{
    wbuffer_convert<codecvt_utf8_utf16<char16_t>, char16_t> a;
}

I get this:
The compiler wrote:
C:\Users\Vilim\Desktop\Nova mapa\Neimenovano1.cpp In function 'int main()':
5 C:\Users\Vilim\Desktop\Nova mapa\Neimenovano1.cpp:9 'wbuffer_convert' was not declared in this scope
21 C:\Users\Vilim\Desktop\Nova mapa\Neimenovano1.cpp:9 'codecvt_utf8_utf16' was not declared in this scope
40 C:\Users\Vilim\Desktop\Nova mapa\Neimenovano1.cpp:9 expected primary-expression before 'char16_t'
40 C:\Users\Vilim\Desktop\Nova mapa\Neimenovano1.cpp:9 expected ';' before 'char16_t'
Pages: 12