C ++ 11为我们带来了UTF-8字面量的u8前缀,我认为几年前这很酷,并在代码中添加了以下内容:
std::string myString = u8"●";
这一切都很好,但是在C ++ 20中出现了问题,因为u8创建了char8_t *,而且与仅使用char的std :: string不兼容,因此似乎不再编译了。
我应该创建一个新的utf8string吗?在C ++ 20世界中,如果我们有更显式的类型与标准std :: string完全不匹配,那么一致的正确方法是什么?
答案 0 :(得分:13)
我应该创建一个新的utf8string吗?
不,它已经在那里。 P0482不仅提议char8_t
,而且还为std::basic_string
名为char8_t
的字符类型提供了std::u8string
的新专业化。因此,这已经在主干中使用clang
和libc++
进行了编译:
const std::u8string str = u8"●";
不幸的是,std::string
字面意思是u8
的构造。从提案中:
除了保留不推荐使用的接口外,该建议书未指定任何向后兼容性功能。缺少此类功能并不是因为人们认为不需要向后兼容功能。作者认为此类功能是必要的,但由于时间限制,无法充分研究必须解决的问题,必须解决的程度以及如何指定这些功能。 [...]
但是我想上面的大多数此类初始化应该可以grep
进行,或者需要进行一些clang
自动工具修复。
答案 1 :(得分:12)
除了@lubgr的答案,论文char8_t backward compatibility remediation (P1423)讨论了几种使用std::string
字符数组制作char8_t
的方法。
基本上,您的想法是可以将u8
char数组转换为“普通” char数组,以获得与C ++ 17相同的行为,在此之前,您必须更加明确一些。本文讨论了实现此目标的各种方法。
适合用例的最简单的方法(但开销不为零,除非添加更多的重载)可能是最后一种方法,即引入显式转换函数:
std::string from_u8string(const std::string &s) {
return s;
}
std::string from_u8string(std::string &&s) {
return std::move(s);
}
#if defined(__cpp_lib_char8_t)
std::string from_u8string(const std::u8string &s) {
return std::string(s.begin(), s.end());
}
#endif
答案 2 :(得分:9)
我应该创建一个新的 utf8string 吗?
不,C++20 添加了 std::u8string
。但是,我建议改用 std::string
,因为标准中对 char8_t
的支持很差,并且根本不受任何系统 API 支持(并且可能永远不会因为兼容性原因而受到支持)。在大多数平台上,正常的 char
字符串已经是 UTF-8,而在带有 MSVC 的 Windows 上,您可以使用 /utf-8
进行编译,这将为您在主要操作系统上提供可移植的 Unicode 支持。
例如,您甚至无法在 C++20 (https://godbolt.org/z/E6rvj5) 中使用 u8 字符串编写 Hello World 程序:
std::cout << u8"Hello, world!\n"; // won't compile in C++20
在使用 MSVC 和 C++20 之前的 Windows 上情况更糟,因为 u8 字符串可能会被悄悄损坏。例如:
std::cout << "Привет, мир!\n";
将产生有效的 UTF-8,根据其当前的代码页可能会或可能不会在控制台中显示
std::cout << u8"Привет, мир!\n";
几乎肯定会给您一个无效的结果,例如 ╨а╤Я╨б╨В╨а╤С╨а╨Ж╨а┬╡╨бтАЪ, ╨а╤Ш╨а╤С╨б╨В!
。
答案 3 :(得分:0)
可能不方便,但是你用这个:
(const char*)u8"こんにちは"
或者使用参数“const char*”和“const char8_t*”创建2个函数
答案 4 :(得分:0)
目前看起来 utf8 到处都是倡导者,而 C++20 提供了又一个有缺陷的不完整选项,供在决定如何处理可移植代码的字符编码时考虑。 char8_t 进一步搅乱了一些已经很脏的水。作为 msvc optionPreview - 来自最新 C++ 工作草案 (/std:c++latest) 的功能的止损,我能想到的最好的就是这个...
#if defined(__cpp_char8_t)
template<typename T>
const char* u8Cpp20(T&& t) noexcept
{
#pragma warning (disable: 26490)
return reinterpret_cast<const char*>(t);
#pragma warning (default: 26490)
}
#define U8(x) u8Cpp20(u8##x)
#else
#define U8(x) u8##x
#endif
它丑陋、低效且烦人。但它允许在遗留的“utf8 无处不在”代码中用 U8"" 替换所有 u8""。我计划避开 char8_t,直到产品更加连贯和完整(或永远)。我们应该拭目以待,看看 C++20 最终会选择什么。目前 char8_t 令人非常失望。
如果有人感兴趣,我已经在 github 上发布了我自己的 utf8 无处不在响应的开源示例(用于 Visual Studio 社区)。 https://github.com/JackHeeley/App3Dev