What does it take to specialize basic_i/ostream?

Pages: 12
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
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.
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
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?
Bump
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...
OK, I'll try that out, but how are cin and cout made? They have to be constructed somehow!
Last edited on
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...
Oh, and although I made u16cout work, u16cin reports std::bad_cast! Does anyone know why?
Last edited on
Anyone? Please?
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.
But a conversion from char16_t to char looses information, doesn't it?
Alo, which of the codecvt facets should I use?
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)
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??
There's no telling what havoc that reinterpet_cast could wreck. Someone could dig through your library implementation, but would it be helpful?
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!
Bump, please help!
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

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