web-dev-qa-db-ja.com

std :: u8stringはstd :: stringとどのように異なりますか?

文字列がある場合:

std::string s = u8"你好";

そしてC++ 20では、

std::u8string s = u8"你好";

std::u8stringstd::stringとどのように異なりますか?

11
user963241

u8stringstringの違いは、1つはchar8_tでテンプレート化され、もう1つはcharでテンプレート化されるということなので、real質問は、char8_tベースの文字列とcharベースの文字列の使用の違いは何ですか。

それは本当にこれに帰着します:タイプベースのエンコーディング。

charベースの文字列(char*char[]stringなど)は、UTF-8でエンコードできます。しかし、再び、それはできませんchar*に相当するものはすべてUTF-8でエンコードされることを想定して、コードを開発できます。また、すべての文字列リテラルの前にu8を記述したり、適切にエンコードされていることを確認したりできます。だが:

  1. 他の人のコードは同意しないかもしれません。そのため、UTF-8エンコーディングを使用しないchar*sを返す可能性のあるライブラリは使用できません。

  2. 誤って自分の教訓に違反する可能性があります。結局のところ、char not_utf8[] = "你好";は条件付きでサポートされるC++です。そのchar[]のエンコーディングは、コンパイラの狭いエンコーディングになります...が何であっても。一部のコンパイラではUTF-8になり、他のコンパイラではUTF-8になる場合があります。

  3. これがあなたがやっていることを他の人のコード(またはチームの他の人)に伝えることはできません。つまり、APIは特定のchar*がUTF-8でエンコードされていることを宣言できません。これは、ユーザーがコードで見るものではなく、ユーザーが想定している、またはドキュメントで別の方法で読んだものでなければなりません。

これらの問題は、UTF-16またはUTF-32のユーザーには存在しないことに注意してください。 char16_tベースの文字列を使用すると、これらの問題はすべてなくなります。他の人のコードがchar16_t文字列を返す場合、彼らは何をしているのかわかります。それらが別のものを返す場合、それらはおそらくUTF-16ではないことがわかります。 UTF-16ベースのコードは、それらと相互運用できます。 char16_tベースの文字列を返すAPIを作成すると、コードを使用しているすべての人が、文字列のタイプからそれがどのエンコーディングであるかを確認できます。そして、これはコンパイルエラーであることが保証されています: `char16_t not_utf16 [] ="你好 ";

今はそうです、これらの事柄の保証はありません。特定のchar16_t文字列には、UTF-16で不正な値であっても、値が含まれている可能性があります。ただし、char16_tは、デフォルトの想定が特定のエンコーディングであるタイプを表します。それを考えると、UTF-16エンコードされていないこのタイプの文字列を提示する場合、これをユーザーによる間違い/改ざんと見なすことは不合理ではなく、それは契約違反であると考えられます。

UTF-8に同様のタイプベースの機能がないことにより、C++がどのように影響を受けたかがわかります。 filesystem::pathを検討してください。 Unicodeエンコーディングの文字列をとることができます。 UTF-16/32の場合、pathのコンストラクターはchar16/32_tベースの文字列を取ります。ただし、UTF-8文字列をpathのコンストラクターに渡すことはできません。 charベースのコンストラクタは、エンコーディングがUTF-8ではなく、実装定義のナローエンコーディングであることを前提としています。したがって、代わりにfilesystem::u8pathを使用する必要があります。これは、UTFから構築されたpath返す独立した関数です-8エンコードされた文字列。

さらに悪いことに、UTF-8でエンコードされたcharベースの文字列をpathのコンストラクターに渡そうとすると、正常にコンパイルされます。せいぜいポータブルではありませんが、機能しているように見えます。

char8_t、およびu8stringなどのすべての付属品は、UTF-8ユーザーが他のUTFエンコーディングと同じ能力を使用できるようにするために存在します。 C++ 20では、filesystem::pathchar8_tベースの文字列のオーバーロードを取得し、 u8pathは廃止されます。

また、追加のボーナスとして、char8_tには特別なエイリアス言語がありません。したがって、char8_tベースの文字列を受け取るAPIは、確かに任意のバイト配列ではなく、文字配列を受け取るAPIです。

8
Nicol Bolas