web-dev-qa-db-ja.com

C ++ 11のUnicode

私はUnicode、特にUTF-8のC++ 11での(非)サポートについて少し読んでいますが、StackOverflowの教祖が私の理解が正しいことを私に安心させてくれることを望んでいました。 、またはその場合は、どこで誤解したか、何かを見逃したかを指摘します。

簡単な要約

まず、良い点です。ソースコードでUTF-8、UTF-16、UCS-4リテラルを定義できます。また、<locale>ヘッダーには、UTF-8、UTF-16、UCS-4とプラットフォームマルチバイトエンコーディングの間で変換できるいくつかのstd::codecvt実装が含まれています(ただし、APIは、控えめに言っても、単純ではありません)。これらのcodecvt実装をストリームにimbue()することで、ファイル(または他のストリーム)の読み取りまたは書き込み時に変換を実行できます。

[EDIT:Cubbiはコメントの中で、ロケールに依存しない<codecvt>実装を提供するstd::codecvtヘッダーについて言及しなかったことを指摘しています。また、std::wstring_convert関数とwbuffer_convert関数は、これらのcodecvtsを使用して、ストリームに依存せずに文字列とバッファーを直接変換できます。]

C++ 11には、プラットフォームのマルチバイトエンコーディング(UTF-8の場合とそうでない場合があります)からUCS-2およびUCS-4との間で個々の文字を変換する関数を含むC99/C11<uchar.h>ヘッダーも含まれています。

しかし、それはその程度です。もちろん、UTF-8テキストをstd::stringに格納することはできますが、それを使って本当に役立つことを行うために私が見ることができる方法はありません。たとえば、コードでリテラルを定義する以外に、有効なUTF-8を含むものとしてバイトの配列を検証することはできません。また、長さ(つまり、「文字」の定義についてはUnicode文字の数)を見つけることもできません。 )UTF-8を含むstd::stringであり、バイトごと以外の方法でstd::stringを繰り返すことはできません。

同様に、std::u16stringのC++ 11追加でさえUTF-16を実際にはサポートしていませんが、古いUCS-2のみをサポートしています。サロゲートペアはサポートされていないため、BMPだけが残ります。

観察

UTF-8が、ほとんどすべてのUnix派生システム(を含む)でUnicodeを処理する標準的な方法であることを考えると Mac OSXおよび* Linux)であり、主にWebのデファクトスタンダードになっていますが、最新のC++でのサポートの欠如は、かなり深刻な省略のようです。 Windowsでも、新しいstd::u16stringがUTF-16を実際にサポートしていないという事実は、いくぶん残念なようです。

*コメントで指摘され、明確にされているように ここ 、Mac OSのBSD派生部分はUTF-8を使用し、CocoaはUTF-16を使用します。

質問

あなたがそれをすべて読むことができたなら、ありがとう!結局のところ、これはStack Overflowであるため、簡単な質問が2つだけあります...

  • 上記の分析は正しいですか、それとも私が見逃している他のUnicodeサポート機能はありますか?

  • 標準化委員会は、過去2年間で、C++を急速に前進させる素晴らしい仕事をしてきました。彼らは皆賢い人で、上記の欠点をよく知っていると思います。 UnicodeサポートがC++で非常に貧弱なままであるという特定のよく知られた理由はありますか?

  • 今後、状況を是正するための提案を知っている人はいますか? isocpp.orgをすばやく検索しても、何も表示されなかったようです。

編集:ご回答ありがとうございます。私は彼らが少しがっかりしていると思うことを告白しなければなりません-現状が近い将来変わる可能性は低いようです。 cognoscentiの間でコンセンサスがある場合、完全なUnicodeサポートは非​​常に困難であり、どのソリューションでもICUのほとんどを再実装する必要があるようです。有用であると考えられます。

私は個人的にこれに同意しません。貴重な中間点が見つかると思います。たとえば、UTF-8およびUTF-16の検証および正規化アルゴリズムは、Unicodeコンソーシアムによって適切に指定されており、標準ライブラリによって、たとえばstd::unicode名前空間の無料関数として提供できます。これらだけでも、Unicode入力を期待するライブラリとインターフェイスする必要があるC++プログラムにとって非常に役立ちます。しかし、以下の答えに基づいて(苦味のある、言わなければならない)、この種の制限された機能だけに関するパピーの提案は、十分に受け入れられなかったようです。

57
Tristan Brindle

上記の分析は正しいですか

どれどれ。

有効なUTF-8を含むものとしてバイトの配列を検証することはできません

不正解です。 std::codecvt_utf8<char32_t>::length(start, end, max_lenght)は、配列内の有効なバイト数を返します。

あなたは長さを見つけることができません

部分的に正しい。 char32_tに変換して、結果の長さを調べることができます。実際の変換を行わずに長さを見つける簡単な方法はありません(ただし、以下を参照)。文字を数える必要性は(何らかの意味で)かなりまれにしか発生しないと言わなければなりません。

バイトごと以外の方法でstd :: stringを反復処理することはできません。

不正解です。 std::codecvt_utf8<char32_t>::length(start, end, 1)を使用すると、UTF-8の「文字」(Unicodeコード単位)を反復処理でき、もちろんその数を判別できます(これは、文字数を数える「簡単な」方法ではありませんが、仕方)。

uTF-16を実際にはサポートしていません

不正解です。たとえば、UTF-16との間で変換できます。 std::codecvt_utf8_utf16<char16_t>。 UTF-16への変換の結果は、まあ、UTF-16です。 BMPに限定されません。

これらのポイントを説明するデモ

他の「できない」を見逃した場合は、指摘してください。対処します。

重要な補遺。これらの機能は、C++ 17では非推奨になっています。これはおそらく、C++の将来のバージョンで廃止されることを意味します。ご自身の責任で使用してください。元の質問に列挙されたこれらすべてのことは、標準ライブラリのみを使用して、(安全に)再度実行することはできません。

10
n.m.