了解最新技术文章
我们最近考虑是否将所有的char
s 更改为 C++20 char8_t
,并决定反对,至少目前是这样。
从表面上看,添加char8_t
似乎是直接且有吸引力的。已经有一个用于 UTF-16 和 UTF-32 字符串的char16_t
andchar32_t
了,那么为什么没有一个char8_t
用于 UTF-8 字符串的 a 呢?
我完全支持强类型,即基本(或其他)类型的别名,它们共享相同的表示形式,但不会隐式转换为其他类型以避免错误。如果我们要计算苹果的数量,我们也可能有一个类型,这样我们就不会意外地将苹果的数量分配给计算橙子的变量。如果我们想要表达,无论出于何种原因,购买与橙子相同数量的苹果,我们仍然可以在苹果和橙子的数量之间进行显式转换。
不幸的是,C++ 对强类型的支持不是很好,并且需要大量的样板文件。到目前为止,没有任何有用的东西进入标准库。Rust 作为一种更现代的语言,在这方面要好得多。
那么为什么不为 Unicode 编码字符的引入而喝彩呢char*_t
?这样我们至少就有了强类型呢?
首先,现在大多数字符串都是 Unicode 编码的。因此,我们努力引入一个新关键字来区分 1% 的非 Unicode 编码字符和 99% 的 Unicode 字符。
我们这样做的时候,真正的问题在别处:字符串不仅在编码方面不同,而且实际上更常见的是在其他不变量方面。文件路径可能不包含某些字符。字符串可能会被转义,例如根据 JSON 或 XML 或 SQL 规则,这些规则都是不同的。UI 可能仅支持打印控制字符的子集。遇见BEL你想敲响警钟吗?
情况变得更糟。对于文件路径,Windows 喜欢任何 16 位值序列,甚至不必是有效的 UTF-16。这实际上是一个很好的理由,不要为整个程序选择单一字符编码(UTF-8 是最有吸引力的):我们在野外遇到的一些字符串可能不是正确的 Unicode,但只要你的程序知道这些特质并且仅在其特定上下文中使用这些字符串,一切都工作得很好。
理想情况下,所有这些具有不同不变量的字符串实际上应该是不同的类型。但请记住,我们讨论的是字符串类型,而不是单个字符类型。许多不变量(包括编码和转义)是字符序列的不变量,而不是单个字符的不变量。拥有单个字符的类型无助于维持不变性。
使字符串不同类型也不是那么容易。我们已经使用了不同的字符串类型,因为我们想以不同的方式存储字符串。字符串常量是 C 数组,动态字符串是,它们可以通过引用作为或std::basic_string
传递。在 think-cell,我们在跨进程共享堆中存储字符串,因为它们与具有自定义(在本例中为可重定位)指针类型的分配器配合使用。std::span
std::basic_string_view
std::vectors
字符串的不变量与其存储正交。我们需要采用任何这些存储类型并限制它们的转换规则和其他操作,例如通过某种标记。think-cell 尚未这样做。相反,我们依赖惯例。我们使用字符类型别名,例如tc::filechar
和 为每个变量添加前缀,例如包含操作系统文件或路径名的变量使用“path”,包含 HTML 的变量使用“html”。
当然,这实在是太弱了。但正如你所看到的,引入对解决char8_t
这些问题没有任何帮助,只会创造更多的转化。这就是我们决定反对的原因。
24小时免费咨询
请输入您的联系电话,座机请加区号