为什么C ++ 11提供std::u16string
和std::u32string
而非std::u8string
?我们需要实现utf-8编码或使用其他库吗?
答案 0 :(得分:7)
C++20 adds char8_t
and std::u8string
。根据建议,理由是:
UTF-8是C ++标准唯一要求支持的文本编码,没有特殊的代码单元类型。缺少UTF-8编码的字符和字符串文字的独特类型,可以防止在设计用于与编码文本互操作的接口中使用重载和模板专业化。无法推断出窄字符和字符串的编码会限制设计的可能性,并会阻碍在通用代码中似乎无法正常工作的优雅界面的产生。库作者必须选择限制编码支持,设计要求用户明确指定编码的接口,或者至少为实现定义的执行和UTF-8编码提供不同的接口。
无论char是带符号类型还是无符号类型,都是由实现定义的,并且使用8位带符号字符的实现在处理UTF-8编码的文本方面处于不利地位,因为必须依赖于对无符号类型的转换类型,以便正确处理多字节编码代码点的前导和连续代码单元。
缺少独特的类型,并且使用的代码单元类型的范围不能移植地包括UTF-8代码单元的完整无符号范围,这给使用UTF-8编码文本提供了挑战。使用UTF-16或UTF-32编码的文本。随函附上一项有关新的char8_t基本类型和相关库增强功能的提案,旨在消除使用UTF-8编码的文本的障碍,并使通用接口能够以一致的方式与所有五种标准授权文本编码一起使用。
答案 1 :(得分:1)
因为 C/C++ 标准委员会并不关心有效的 UTF-8 序列和比较。对他们来说,strcmp((char*)utf8, (char*)other)
就足够了,即使它们在标准化后是相同的,或者即使一个无效的 UTF-8。
无论是正确的标识符,还是应该可识别的 UTF-8 序列,如路径名。对他们来说,“Café”与“Café”不同,因为它们有不同的字节。 “e\x301”与“\xe9”。对于 u8ident 来说这是错误的,对于 u8string 来说是有争议的。至少需要检查有效性,规范化可以缓存。这是一种罕见的情况。
即使是 coreutils 也不能正确地做到这一点,大多数文件系统将名称视为二进制,这是一个安全风险。
参见例如https://crashcourse.housegordon.org/coreutils-multibyte-support.html 或 http://perl11.github.io/blog/foldcase.html
答案 2 :(得分:0)
C++20 添加了 std::u8string
。但是,我建议改用 std::string
,因为标准中对 char8_t
的支持很差,并且根本不受任何系统 API 支持(并且可能永远不会因为兼容性原因而受到支持)。在大多数平台上,正常的 char
字符串已经是 UTF-8,而在带有 MSVC 的 Windows 上,您可以使用 /utf-8
进行编译,这将为您在主要操作系统上提供可移植的 Unicode 支持。
除了标准的支持不佳外,在 Windows 上使用 MSVC u8 字符串可能会被悄悄损坏。例如:
std::cout << u8"Привет, мир!\n";
几乎肯定会给您一个无效的结果,例如 ╨а╤Я╨б╨В╨а╤С╨а╨Ж╨а┬╡╨бтАЪ, ╨а╤Ш╨а╤С╨б╨В!
。