1

I've written my own specialisation of each virtual member function of std::ctype<char16_t>, so that this now works:

#include <string>
#include <locale>
#include "char16_facets.h"  // Header containing my ctype specialisation
#include <sstream>
#include <iostream>

// Implemented elsewhere using iconv
std::string Convert(std::basic_string<char16_t>);

int main() {
    std::basic_string<char16_t> s("Hello, world.");
    std::basic_stringstream<char16_t> ss(s);
    ss.imbue(std::locale(ss.getloc(), new std::ctype<char16_t>()));
    std::basic_string<char16_t> t;
    ss >> t;
    std::cout << Convert(t) << " ";
    ss >> t;
    std::cout << Convert(t) << std::endl;
}

Is there a way to make streams use the new ctype specialisation by default, so I don't have to imbue each stream with a new locale?

I haven't written a new class, just provided

template<>
inline bool std::ctype<char16_t>::do_is (std::ctype_base::mask m, char16_t c) const {

etc. I'd sort of hoped it would be picked up automatically, so long as it was declared before I #include <sstream> but it isn't.

Most of the work for the above was done using G++ and libstdc++ 4.8, but I get the same result with them built from SVN trunk.

Edit - Update This question originally asked about how to get number extraction working. However, given a stream imbued with correct ctype and numpunct implementations, then no specialisation of num_get is necessary; simply

ss.imbue(std::locale(ss.getloc(), new std::num_get<char16_t>()));

and it will work, with either gcc version.

Again, is there some way to get the streams to pick this up automatically, rather than having to imbue every stream with it?

Tom
  • 7,269
  • 1
  • 42
  • 69
  • `std::locale::global(std::locale(), new std::ctype());` – David G Feb 06 '15 at 14:08
  • Just so - thanks. A further question - does this replace the existing ctype facet of the global locale? Or does it mean that the global locale will have both ctype facets and will use the one appropriate to the type of the stream? I'm guessing the latter, because it works, but I can't find it documented anywhere. – Tom Feb 12 '15 at 00:00
  • It replaces the `std::ctype` facet in the global locale. I can't explain why it works as you just described though. – David G Feb 12 '15 at 02:12
  • Does it? According to http://en.cppreference.com/w/cpp/locale/locale, the 'classic' locale always contains at least ctype and ctype; why couldn't you add another ctype on top of that? – Tom Feb 13 '15 at 01:54
  • Sorry, I was mistaken. Your `std::ctype` specialization introduces a new _facet family_ and thus does not replace the `std::ctype` or `std::ctype` facets because they all have different _facet identifications_. So your code will work because the character type of the stream is `char16_t`, and so it will use the `std::ctype` facet you specialized and imbued into the global locale. – David G Feb 13 '15 at 20:02
  • Great. If you'd like to write that up into an answer, I'll accept it; otherwise, I'll write it up myself. – Tom Feb 15 '15 at 02:13

1 Answers1

4

Use std::locale::global():

std::locale::global(std::locale(std::locale(), new std::ctype<char16_t>()));
David G
  • 94,763
  • 41
  • 167
  • 253