std :: u8string与std :: string有何不同?

use*_*241 8 c++ string unicode c++20

如果我有一个字符串:

std::string s = u8"??";
Run Code Online (Sandbox Code Playgroud)

在C ++ 20中

std::u8string s = u8"??";
Run Code Online (Sandbox Code Playgroud)

有何std::u8string不同std::string

Nic*_*las 8

由于之间的差别u8string,并string是一个模板上char8_t,另一个在char中,真正的问题是,什么是两者的区别char8_t为基础的弦与char基于字符串。

真正归结为:基于类型的编码。

任何char基于字符串(char*char[]string等)可以以UTF-8编码。但是话又说回来,可能不会。您可以在假设所有char*等效项都将以UTF-8编码的前提下开发代码。您可以u8在每个字符串文字前写一个和/或以其他方式确保对它们进行正确编码。但:

  1. 其他人的代码可能不同意。因此,您不能使用任何可能返回char*s且未使用UTF-8编码的库。

  2. 您可能不小心违反了自己的戒律。毕竟,char not_utf8[] = "??";有条件地支持C ++。char[]不管是什么其编码将是编译器的窄编码。在某些编译器上可能是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,这是一个单独的函数,该函数返回一个path由UTF-8编码的字符串构造的。

更糟糕的是,如果您尝试将基于UTF-8编码char的字符串传递给path的构造函数...它会很好地编译。尽管充其量是不可移植的,但它似乎还是可以工作的。

char8_t和所有类似的附件的u8string存在,是为了允许UTF-8用户获得与其他UTF编码相同的功能。在C ++ 20中,filesystem::pathchar8_t基于基的字符串重载,并且u8path将变得过时。

而且,作为一项额外的好处,char8_t它周围没有特殊的别名语言。因此,采用char8_t基于字符串的API 肯定是采用字符数组而不是任意字节数组的API。

  • @ChefGladiator:我不“卖”任何东西。我正在解释该类型的用途和用途。类型可以以其不该使用的方式使用这一事实并不意味着它不能以其实际应有的方式使用。`char8_t` 是一个 UTF-8 代码单元,就像 `char16_t` 是一个 UTF-16 代码单元一样。还能是什么?如果您不喜欢该类型,那是您的特权,但这不会改变该类型的用途及其使用方式。 (4认同)
  • @ChefGladiator:相对于什么?`char8_t` 旨在成为 UTF-8 代码*单元*,而不是 Unicode 代码点。UTF-8 代码单元的大小为 8 个字节,并且“unsigned char”要求至少有那么大。还有很多代码点也会因“char16_t”而失败。 (3认同)
  • @ChefGladiator:好的,如果没有“出售 WG21 决策”,我该如何准确地解释 `char8_t` 及其伴随的 typedef 是什么?我试图提供事实,而不是意见,比如强制每个人都使用 char UTF-8 是否是一个更好的主意(尽管我不明白这将如何允许 char utf8 = '你'`比“char8_t”版本更合法,因此批评似乎相当没有根据)。我的观点是我正在推动*事实*;你正试图推动一个议程。 (3认同)
  • @ChrisJefferson:它“可能不是”UTF-8,就像“char16_t *”“可能不是”UTF-16 一样。您*可以*创建这样的字符串,但它需要*实际的努力*。相比之下,创建一个不需要是 UTF-8 的 char* 就非常容易了。通过故意使用“char8_t”类型,您就对要放入其中的数据的含义做出了承诺。你可以撒谎,但这比“char”需要更多的努力。 (2认同)