I use STLport with MinGW - which does have wide iostreams.
http://www.stlport.org/
It's been explained already that wide streams do not support Unicode. Trying to do so in a cross-platform manner is even further complicated in that wchar_t and literal wide-string encodings are implementation defined.
Having said all that - you can prevent the implicit wchar_t to char conversion in wide streams by using your own codecvt facet. This works ok for wide fstreams under most implementations, but still doesn't handle screen output for any windows compiler I have access to. However, starting with the VC++ 2008 CRT, you can use a new MS extension to enable Unicode (UTF16LE) output with wcout. Here's some code to play with:
Code:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <locale>
#include <string>
//------------------------------------------------------------------------------
// null_wcodecvt is a codecvt facet that prevents the implicit conversion of
// whcar_t to char in wide streams
typedef std::codecvt<wchar_t , char , mbstate_t> null_wcodecvt_base;
class null_wcodecvt : public null_wcodecvt_base
{
public:
explicit null_wcodecvt(size_t refs = 0) : null_wcodecvt_base(refs) {}
protected:
virtual result do_out(mbstate_t&,
const wchar_t* from,
const wchar_t* from_end,
const wchar_t*& from_next,
char* to,
char* to_end,
char*& to_next) const
{
size_t len = (from_end - from) * sizeof(wchar_t);
memcpy(to, from, len);
from_next = from_end;
to_next = to + len;
return ok;
}//do_out
virtual result do_in(mbstate_t&,
const char* from,
const char* from_end,
const char*& from_next,
wchar_t* to,
wchar_t* to_end,
wchar_t*& to_next) const
{
size_t len = (from_end - from);
memcpy(to, from, len);
from_next = from_end;
to_next = to + (len / sizeof(wchar_t));
return ok;
}//do_in
virtual result do_unshift(mbstate_t&, char* to, char*,
char*& to_next) const
{
to_next = to;
return noconv;
}//do_unshift
virtual int do_length(mbstate_t&, const char* from,
const char* end, size_t max) const
{
return (int)((max < (size_t)(end - from)) ? max : (end - from));
}//do_length
virtual bool do_always_noconv() const throw()
{
return true;
}//do_always_noconv
virtual int do_encoding() const throw()
{
return sizeof(wchar_t);
}//do_encoding
virtual int do_max_length() const throw()
{
return sizeof(wchar_t);
}//do_max_length
};//null_wcodecvt
//------------------------------------------------------------------------------
std::wostream& wendl(std::wostream& out)
{
// this is needed for files opened in binary mode under Windows in order
// to retain Windows-style newline
#if defined(_WIN32)
out.put(L'\r');
#endif
out.put(L'\n');
out.flush();
return out;
}//wendl
//------------------------------------------------------------------------------
const wchar_t UTF_BOM = 0xfeff;
const wchar_t CHECK_SYM = L'\u221a';
//------------------------------------------------------------------------------
void file_test()
{
// create UTF16LE text file for windows, UTF32[BE|LE] for *nix
std::wfstream file;
null_wcodecvt wcodec(1);
std::locale wloc(std::locale::classic(), &wcodec);
file.imbue(wloc);
file.open("data.txt", std::ios::out | std::ios::binary);
if (!file)
{
std::cerr << "Failed to open data.txt for writting" << std::endl;
return;
}//if
file << UTF_BOM << L"data = " << 42 << CHECK_SYM << wendl;
file.close();
}//file_test
//------------------------------------------------------------------------------
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
# define HAVE_O_U16TEXT
# include <fcntl.h>
# include <io.h>
#endif
void wcout_test()
{
#if defined(HAVE_O_U16TEXT)
// newest MS CRT supports UTF16 output using special mode
int mode = _setmode(_fileno(stdout), _O_U16TEXT);
#else
// for everything else, use our codecvt facet - I haven't seen this work
// for any windows compiler...may work for *nix but untested
null_wcodecvt wcodec(1);
std::locale wloc(std::locale::classic(), &wcodec);
std::wcout.imbue(wloc);
#endif
std::wcout << L"U+221a - [" << wchar_t(0x221a) << L"]" << std::endl;
#if defined(HAVE_O_U16TEXT)
// revert to original mode
_setmode(_fileno(stdout), mode);
#endif
std::cout << "Testing 1, 2, 3" << std::endl;
}//wcout_test
//------------------------------------------------------------------------------
int main()
{
file_test();
wcout_test();
return 0;
}//main
I would interested in knowing if this works for anyone running *nix and a Unicode-enabled terminal.
There's still the underlying problem that the wchar_t encoding is implementation defined - which means that using wchar_t as a cross-platform Unicode character is useless.
"Forcing" wchar_t to do something useful with Unicode is really a platform and implementation dependent exercise.
gg