C++20 with u8, char8_t and std::string
C++20 with u8, char8_t and std::string
c 11为我们带来了UTF-8文字的U8前缀,我认为几年前很酷,并用类似的东西给我的代码撒了下来:
std::string myString = u8"●";
这一切都很好,但是问题出现在C 20中,它似乎不再编译了,因为U8创建了一个char8_t*,这与仅使用char的STD :: String不兼容。p>我应该创建一个新的UTF8String吗?在C 20世界中,一致和正确的方法是什么,我们有更多的显式类型与标准STD :: String不匹配?
除了 @lubgr的答案外,纸char8_t向后兼容性补救(P1423(讨论了如何使用char8_t
字符数组制作std::string
的几种方法。
基本上的想法是,您可以将u8
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
我应该创建一个新的utf8string吗?
no,C 20添加std::u8string
。但是,我建议使用std::string
,因为char8_t
在标准中受支持的支持很差,并且根本不受任何系统API的支持(并且可能永远不会因为兼容原因(。在大多数平台上,普通char
字符串已经是UTF-8,在Windows上,您可以使用/utf-8
编译,这将为您提供主要操作系统的便携式Unicode支持。
例如,您甚至不能使用C 20中的U8字符串编写Hello World程序(https://godbolt.org/z/e6rvj5(:
std::cout << u8"Hello, world!n"; // won't compile in C++20
在带有MSVC和PER-C 20的Windows上,情况甚至更糟,因为U8字符串可能会被静默损坏。例如:
std::cout << "Привет, мир!n";
将产生有效的UTF-8,该UTF-8可能会根据当前代码页面显示在控制台中时,
std::cout << u8"Привет, мир!n";
几乎肯定会给您带来无效的结果,例如╨а╤Я╨б╨В╨а╤С╨а╨Ж╨а┬╡╨бтАЪ, ╨а╤Ш╨а╤С╨б╨В!
。
我应该创建一个新的utf8string吗?
不,它已经在那里。P0482不仅提出了char8_t
,而且还提出了std::basic_string
的新专业化char8_t
字符类型,名为std::u8string
。因此,这已经使用TRUNK中的clang
和libc++
编译:
const std::u8string str = u8"●";
std::string
u8
-文字断裂的构造是不幸的。从提案中:
此提案没有指定除保留其弃用界面外的任何向后兼容性功能。作者认为这种功能是必要的,但是一组此类功能会不必要地损害该提案的目标。相反,期望实施将提供选项以启用更多细性粒度兼容性功能。
但我想大多数以上的初始化应该是 grep
-可供某些自动clang
工具修复。
当前看起来像在总线下,倡导者的UTF8无处不在,C 20提供又有缺陷的不完整选项,可以考虑如何处理如何处理Portable Code的字符编码。char8_t进一步弄乱了一些已经很脏的水。我能够提出的最好的方法是使用MSVC OptionPreview的停止差距 - 最新的C 工作草稿(/STD:C 最新(的功能是...
#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
这很丑陋,效率低下且令人讨厌。但是它允许替换所有U8"用u8" quot"在传统的"无处不在"代码中。我计划避开char8_t,直到产品更加连贯和完整(或永远(。我们应该拭目以待,看看C 20最终达到了什么。目前,char8_t令人失望。
如果有人有兴趣,我在GitHub(对于Visual Studio社区(上发布了我自己的UTF8响应的开源示例。https://github.com/jackheeley/app3dev
将使用U8文字用作const char*
的另一种方法将是用户定义的文字(请参阅https://en.cppreference.com/w/cpp/langueage/user_literal(:
std::string operator"" S(const char8_t* str, std::size_t) {
return reinterpret_cast< const char* >(str);
}
char const* operator"" C(const char8_t* str, std::size_t) {
return reinterpret_cast< const char* >(str);
}
用法:然后可以像这样使用:
std::string myString = u8"●"S;
SetConsoleOutputCP(CP_UTF8);
std::cout << u8"Привет, мир!"C << std::endl;
说明
上面的代码定义了两个用户定义的文字u8"…"S
和u8"…"C
(请记住:C 20中的文字u8"…"
是const char8_t*
类型(。S
文字创建了std::string
,C
字面创建const char *
。
这意味着u8"…"C
表格的所有文字都可以像"…"
文字一样使用,而u8"…"S
表格的所有文字都可以像"…"s
文字一样使用。
ps:我不确定,如果允许它定义不在台下" _"的文字。但是,当我在Visual Studio中尝试时,代码没有问题。但是cppreference
中的所有示例均为下划线。
可能不方便,但您使用此信息: (const char*)u8"こんにちは"
或用参数制作2个函数" const char*&quot"and&quot" const char8_t*&quot"
- std::visit and std::variant usage
- Visual Studio 2019 C++ and std::filesystem
- Threads with Classes and std::packaged_task
- Cython C++ and std::map handling
- C++20 with u8, char8_t and std::string
- std :: set and std :: unordered_set构造元素与emplace()如何
- 混合std :: wcout and std :: cout会犯错,什么错
- std::is_same and std::get together
- C++ concepts and std::cout
- Use boost strand and std::mutex
- STD :: MAP,STD :: set and std :: Priority_queue中的比较器
- C++ - vsprintf_s and std::string?
- is_assignable and std::unique_ptr
- 使用std :: future and std ::通过非std ::螺纹承诺安全吗?
- std::experimental::ostream_joiner and std::pair
- 为什么BOOST :: fileSystem :: path and std :: filesystem ::路径含量含
- unique_ptr push_back and std::list
- 为什么要使用std ::少用作默认函数来比较std :: map and std :: set中的键
- 使用std :: bind and std ::功能
- vector::push_back and std::move