如何在C ++ 20中安全地将const char *转换为const char8_t *?

时间:2019-08-22 06:15:05

标签: c++ unicode utf-8 c++20

this answer中我了解到,在C ++ 17中,我们可以通过std::fstream使用UTF-8路径打开std::filesystem::u8path。但是在C ++ 20中,不建议使用此函数,而应该将const char8_t*传递给std::filesystem::path构造函数。

问题来了:尽管我们可以合法地(通过reinterpret_cast转换任何指向const char*的指针,但是我们不能倒退:从const char*到例如。 const char8_t*(这将违反严格的别名规则)。因此,如果我们有一些外部API返回文件名的基于char的UTF-8表示形式(例如,用C编写的库),我们将无法安全地将指针转换为基于char8_t的指针

那么,我们应该如何将这种基于char的UTF-8字符串视图转换为基于char8_t的它们的视图?

2 个答案:

答案 0 :(得分:1)

免责声明:我是P0482提案的作者,该提案介绍了char8_t,而弃用了u8path

您的观察是正确的;不允许使用reinterpret_cast生成指向char8_t对象序列的char指针。 https://stackoverflow.com/a/57453713/11634221对此进行了进一步讨论。

尽管std::filesystem::u8path在C ++ 20中已被弃用,但尚无计划立即删除它。您可以继续使用它。此外,P1423纠正了P0482中更改的意外结果,并允许在C ++ 20中使用charchar8_t的范围来调用它。据我所知,没有实现者将std::filesystem::u8path注释为已弃用(我不知道是否有这样做的计划)。

没有(格式良好)的方法来生成char8_t序列的基于char指针的视图。可以编写一个范围/迭代器适配器,该适配器在内部将迭代器解引用中的各个char值转换为char8_t。这样的适配器可以满足非可变迭代器的C ++ 17和C ++ 20随机访问迭代器的要求(它不能满足可变迭代器的要求,因为解引用操作无法提供一个左值,也不能满足连续迭代器的要求)。这样的适配器足以调用接受范围的std::filesystem::path构造函数。嗯,这可能是一个足够有用的适配器,可以添加到https://github.com/tahonermann/char8_t-remediation

当然可以复制基础char数据的视图,但是我可以理解为什么这样做可能被认为是不希望的(在使用时,我们已经倾向于进行大量复制了) std::filesystem::path

答案 1 :(得分:0)

来自this character types referencechar8_t

  

它的大小,符号和对齐方式与unsigned char(因此,其大小和对齐方式与charsigned char)相同,但是是不同的类型。 / p>

因为它是独特的类型,所以您在不破坏严格的别名的情况下无法从const char*转换为const char8_t*。但是出于所有实际目的,由于char8_t基本上是unsigned char,因此您可以使用reinterpret_cast来转换指针。这是错误的,但可以使用。

为了获得正确的正确性,请使用char8_t开头,或者将原始字符复制到char8_t缓冲区(或std::u8string)中。