c++ - C++11 中的 Unicode

标签 c++ c++11 unicode utf-8 utf-16

我一直在阅读有关 Unicode 主题的一些资料——特别是 UTF-8——C++11 中的(非)支持,我希望 Stack Overflow 上的专家可以让我放心,我的理解是正确的,或者指出我误解或遗漏的地方,如果是这样的话。
一个简短的总结
首先,好处是:您可以在源代码中定义 UTF-8、UTF-16 和 UCS-4 文字。另外,<locale> header 包含多个 std::codecvt可以在任何 UTF-8、UTF-16、UCS-4 和平台多字节编码之间转换的实现(尽管 API 似乎,委婉地说,不太简单)。这些 codecvt实现可以是 imbue() 'd 在流上允许您在读取或写入文件(或其他流)时进行转换。
[ 编辑: Cubbi 在评论中指出我忽略提及 <codecvt> header ,提供 std::codecvt不依赖于语言环境的实现。另外,std::wstring_convertwbuffer_convert函数可以使用这些codecvt s 直接转换字符串和缓冲区,而不依赖于流。]
C++11 还包括 C99/C11 <uchar.h>头文件包含将平台多字节编码(可能是也可能不是 UTF-8)中的单个字符转换为 UCS-2 和 UCS-4 的函数。
然而,这就是它的程度。虽然您当然可以将 UTF-8 文本存储在 std::string 中,我看不出有什么方法可以用它做任何真正有用的事情。例如,除了在代码中定义文字外,您无法验证字节数组是否包含有效的 UTF-8,您无法找出长度(即 Unicode 字符的数量,对于某些“字符”的定义) ) 的包含 UTF-8 的 std::string ,并且您不能迭代 std::string以逐字节以外的任何方式。
同样,即使是 C++11 添加的 std::u16string并不真正支持 UTF-16,而只支持较旧的 UCS-2——它不支持代理对,只剩下 BMP。
观察
鉴于 UTF-8 是几乎所有 Unix 派生系统(包括 Mac OS X 和* Linux)上处理 Unicode 的标准方式,并且在很大程度上已成为网络上的事实上的标准,现代 C++ 似乎缺乏支持就像一个非常严重的遗漏。即使在 Windows 上,事实是新的 std::u16string不真正支持UTF-16似乎有些遗憾。
* 正如评论中指出并明确指出的here ,Mac OS 的 BSD 派生部分使用 UTF-8,而 Cocoa 使用 UTF-16。
问题
如果你能读完所有这些,谢谢!只是几个简单的问题,毕竟这是堆栈溢出......

  • 以上分析是否正确,还是我缺少其他支持 Unicode 的工具?
  • 在过去几年中,标准委员会在插入 C++ 快速发展方面做得非常出色。他们都是聪明人,我想他们很清楚上述缺点。在 C++ 中对 Unicode 的支持仍然如此差,是否有一个众所周知的原因?
  • 展望 future ,有没有人知道任何纠正这种情况的建议?在 isocpp.org 上快速搜索似乎没有发现任何信息。

  • 编辑:谢谢大家的回复。我必须承认,我觉得他们有点令人沮丧——看起来现状在不久的将来不太可能改变。如果行家之间达成共识,那么完整的 Unicode 支持似乎太难了,任何解决方案都必须重新实现 ICU 的大部分才能被认为有用。
    我个人不同意这一点。我认为可以找到有值(value)的中间立场。例如,UTF-8 和 UTF-16 的验证和规范化算法由 Unicode 联盟明确指定,并且可以由标准库作为免费函数提供,例如 std::unicode命名空间。对于需要与需要 Unicode 输入的库进行交互的 C++ 程序,仅这些将是一个很大的帮助。但是根据下面的答案(必须说,带有一丝苦涩)似乎 Puppy 提出的这种有限功能的建议并没有得到很好的接受。

    最佳答案

    Is the above analysis correct



    让我们来看看。

    you can't validate an array of bytes as containing valid UTF-8



    不正确。 std::codecvt_utf8<char32_t>::length(start, end, max_lenght)返回数组中的有效字节数。

    you can't find out the length



    部分正确。可以转换为 char32_t 并找出结果的长度。在不进行实际转换的情况下,没有简单的方法可以找出长度(但见下文)。我必须说,需要计算字符(在任何意义上)的情况很少出现。

    you can't iterate over a std::string in any way other than byte-by-byte



    不正确。 std::codecvt_utf8<char32_t>::length(start, end, 1)使您可以遍历 UTF-8“字符”(Unicode 代码单元),当然还可以确定它们的数量(这不是计算字符数的“简单”方法,但它是一种方法)。

    doesn't really support UTF-16



    不正确。可以使用例如在 UTF-16 和 UTF-16 之间进行转换。 std::codecvt_utf8_utf16<char16_t> .转换为 UTF-16 的结果就是 UTF-16。它不限于 BMP。

    Demo that illustrates these points .

    如果我错过了其他一些“你不能”,请指出,我会解决它。

    重要附录 .这些设施是已弃用 在 C++17 中。这可能意味着它们将在 future 的 C++ 版本中消失。使用它们需要您自担风险。原始问题中列举的所有这些事情现在不能​​(安全地)再次完成,仅使用标准库。

    关于c++ - C++11 中的 Unicode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25249498/

    相关文章:

    c++ - 为什么这里调用的是 Copy Constructor 而不是普通的 Constructor 和重载的赋值运算符?

    c++ - 为前后增量重载 C++

    c++ - 多个类中使用的函数

    c++ - 类初始值设定项检查特定输入

    c++ - 为什么 clang 不使用自动返回类型省略此函数中的拷贝?

    mysql - Navicat 查询 - 从 utf8 到 varbinary

    C++:计算游戏中的总帧数

    c++ - high_resolution_clock 最高分辨率为1000ns

    c++ - 什么 utf 格式应该 boost wdirectory_iterator 返回?

    perl - 如何计算文件中的所有字符,包括 Control 和 Unicode?