在 C++17 和 C++20 之间可移植地使用 UTF-8 字符串文字前缀

Using UTF-8 string-literal prefixes portably between C++17 and C++20

我有一个用 C++17 编写的代码库,它大量使用 UTF-8,u8 string literal introduced in c++11 表示 UTF 编码。然而,c++20 改变了 C++ 中 u8 文字 的含义,从生成 charconst char*char8_tconst char8_t*;后者是不可隐式指针转换const char*

我希望这个项目能够支持在 C++17 和 C++20 模式下无中断运行;可以做些什么来支持这一点?


目前,该项目使用 char8 别名,该别名使用 u8 文字的类型结果:

// Produces 'char8_t' in C++20, 'char' in anything earlier
using char8 = decltype(u8' ');

但是这种方法存在一些问题:

  1. char 不保证是无符号的,这使得从数值生成代码点不可移植 (e.g. char8{129} breaks with char, but not with char8_t).

  2. char8 与 C++17 中的 charwhich can break existing code, and may cause errors.

    没有区别
  3. 从第 2 点继续,在 C++17 中无法用 char8 重载 char 来处理不同的编码,因为它们不是唯一类型。

如何支持在 C++17 和 C++20 模式下运行,同时避免类型差异问题?

我建议简单地在 pre-C++20 版本中声明你自己的 char8_tu8string 类型,作为别名 unsigned charbasic_string<unsigned char>。然后在任何你 运行 遇到转换问题的地方,你都可以编写包装函数来在每个版本中适当地处理它们。