?
Werner Salomon schrieb:
Problematisch ist das, wenn char32_t nicht identisch mit wchar_t , sondern z.B. ein typedef unsigned int ist. Dann kann der Compiler nicht mehr unterscheiden, ob Du ein ein Zeichen oder eben einen unsigned int lesen möchtest. Eines von beiden funktioniert dann nicht mehr.
Types char16_t and char32_t denote distinct types with the same size, signedness, and alignment as uint_least16_t and uint_least32_t, respectively, in <stdint.h>, called the underlying types. (3.9.1/5)
Weiter setzt es voraus, dass die verwendete Facetten auch alle für diesen Datentyp implementiert sind.
Almost every(!) facet has design flaws.
Der Artikel http://www.utf8everywhere.org/ und insbesondere der Vorschlag http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3572.html unterscheiden nur wenig oder gar nicht.
Was das Proposal ignoriert ist die Tatsache, dass der C++-Standard schon sehr genau zwischen externen Bytes (oder Words) und internen Zeichen unterscheidet. C++ tut dies in der Facette std::codecvt und in C++11 sind konkrete Derivate definiert, die die ganze UTF-Familie abdecken (z.B.: http://www.cplusplus.com/reference/codecvt/codecvt_utf8).
Irritierender Weise erwähnt das Proposal das mit keinem Wort.
In particular, we believe that adding wchar_t to C++ was a mistake, and so are the Unicode additions to C++11.
// Fehler, da keine 8Bit
Toll, 100 Zeile Code nur um "€" durch ein 8-Bit-Zeichen zu ersetzen. Das ist kein Unicode, das ist ein ASCII-Hack.
Um Strings zu parsen nimmt man const char* , das ist 1. schneller (strstr ftw), 2. mächtiger (manchmal will man mehr als nur 1 Zeichen im Voraus wissen), 3. weniger Code und vor allem 4. Unicode-aware.
Nun ist es aber so, dass UTf-8/16 so designend ist, dass eine Folge von char, bei denen jedes <=0x7f ist, gleichzeitig Unicode und gültiges UTF-8 sei kann. Das gleiche gilt für eine String aus wchar_t mit sizeof(wchar_t)==2 mit Zeichen deren Code <=0x7fff; [...] ein paar Umlaute, die falsch dargestellt werden, stören nicht wirklich.
Das erscheint mir äussert kurzsichtig. Es gibt kein "bisschen Unicode". Es gibt nur vollständigen Unicode-Support oder keinen Unicode-Support.
Vollständigen Unicode-Support kann man erreichen, in dem man entweder wie von utf8everywhere.org empfohlen UTF-8 verwendet und sich nur an Zeichen <=127 orientiert (splittet, ersetzt, parst) und den Rest unbesehen weiterleitet oder indem Unicode vollständig verstanden wird. Zweiteres ist äusserst schwierig, da es Fälle wie " ¨y " gibt, bei denen zwei Codepoints ein Zeichen " ÿ " darstellen. Splitten darf man also nicht einfach so, weder mit wstring noch mit u32string.
Im Gegebenen Fall von Eisflamme heisst das also std::string mit UTF-8 zu verwenden.
const char *ptr; // das, was geparst wird
const std::string euro = u8"€";
if (std::equal(euro.begin(), euro.end(), ptr)
// es handelt sich um ein Euro-Zeichen