我一直在读一些关于Unicode的主题 - 特别是UTF-8 - (非)支持C++ 11,我希望Stack Overflow上的大师可以向我保证我的理解是正确的,或指出我在哪里误解或错过了某些情况.
首先,好的:您可以在源代码中定义UTF-8,UTF-16和UCS-4文字.此外,<locale>标头包含几个std::codecvt可以在UTF-8,UTF-16,UCS-4和平台多字节编码之间进行转换的实现(虽然API看起来很温和,但不是直截了当).这些codecvt实现可以imbue()在流上进行,以允许您在读取或写入文件(或其他流)时进行转换.
[ 编辑: Cubbi在评论中指出我忽略了提到<codecvt>标题,它提供了std::codecvt不依赖于语言环境的实现.此外,std::wstring_convert和wbuffer_convert函数可以使用这些codecvt来直接转换字符串和缓冲区,而不是依赖于流.
C++ 11还包括C99/C11 <uchar.h>标头,其中包含将来自平台多字节编码(可能是或不是UTF-8)的单个字符转换为UCS-2和UCS-4的功能.
但是,这是关于它的程度.虽然你当然可以将UTF-8文本存储在a中std::string,但我无法看到任何对它有用的东西.例如,除了在代码中定义文字之外,您不能将字节数组验证为包含有效的UTF-8,您无法找到长度(即Unicode字符的数量,对于某些"字符"的定义)包含UTF-8 std::string,并且不能std::string以字节为单位以任何方式迭代a .
同样,即使添加C++ 11 std::u16string也不支持UTF-16,但只支持较旧的UCS-2 - 它不支持代理对,只留下BMP.
鉴于UTF-8是在几乎所有Unix派生系统(包括Mac OS X和*Linux)上处理Unicode的标准方式,并且已经在很大程度上成为Web上事实上的标准,现代C++中缺乏支持似乎像一个相当严重的遗漏.即使在Windows上,新std::u16string功能并不真正支持UTF-16 这一事实似乎有些令人遗憾.
*由于在评论中指出,并明确提出在这里的Mac OS使用UTF-8的BSD衍生的部分,而可可使用UTF-16.
如果你设法阅读了所有这些,谢谢!只是几个简单的问题,因为这毕竟是Stack Overflow ...
以上分析是否正确,或者我是否缺少任何其他支持Unicode的设施?
在过去几年中,标准委员会在快速推进C++方面做得非常出色.他们都很聪明,我认为他们很清楚上述缺点.是否有一个众所周知的原因,即Unicode支持在C++中仍然很差?
展望未来,是否有人知道有任何纠正这种情况的建议?快速搜索isocpp.org似乎没有透露任何信息.
编辑:感谢大家的回复.我不得不承认,我发现它们有点令人沮丧 - 看起来现状在不久的将来不太可能改变.如果在认知方面存在共识,似乎完全的Unicode支持太难了,并且任何解决方案必须重新实现大多数ICU才被认为是有用的.
我个人不同意这一点; 我认为可以找到有价值的中间立场.例如,对于UTF-8和UTF-16的验证和归一化算法是由Unicode财团以及指定的,并且可以通过标准库中,比方说自由函数,一个被提供std::unicode的命名空间.仅这些对于需要与期望Unicode输入的库接口的C++程序来说是一个很大的帮助.但基于下面的答案(微笑,必须说,带着一丝苦涩),似乎Puppy关于这种有限功能的提议并不受欢迎.
一点前景:我的任务需要将UTF-8 XML文件转换为UTF-16(当然还有正确的标题).所以我搜索了将UTF-8转换为UTF-16的常用方法,并发现应该使用来自的模板<codecvt>.
但现在当它被弃用时,我想知道执行相同任务的新常用方法是什么?
(根本不介意使用Boost,但除此之外我更喜欢尽可能靠近标准库.)
C11和C++ 11都引入了uchar.h/ cucharheader定义char16_t和char32_t明确的16和32位宽字符,添加了文字语法,u""并U""用于编写具有这些字符类型的字符串,以及宏,__STDC_UTF_16__并__STDC_UTF_32__告诉您它们是否对应于UTF-16和UTF-32代码单元.这有助于消除wchar_t在一些平台上16位且通常用于保存UTF-16代码单元的模糊性,并且在某些平台上是32位并且通常用于保存UTF-32代码单元; 假设现在设置了这些宏,您现在可以编写引用UTF-16和UTF-32的可移植,明确的代码.__STDC_ISO_10646__也可以用作代理来确定是否wchar_t能够保持UTF-32值; 如果它不能,你不一定会认为它拥有UTF-16,但它可能是一个足够近似的便携式.
他们还增加了功能mbrtoc16,mbrtoc32,c16rtomb,并c32rtomb为多字节字符和这些类型之间的转换.在这些和现有mbstowcs的函数系列之间,可以在UTF-16,UTF-32,平台多字节字符集和平台宽字符集之间进行可移植的转换(尽管不一定是无损的,除非平台定义了多字节和宽字符集是UTF;特别是,似乎这些函数在Windows上相当无用,其中语言环境定义的多字节编码不允许每个字符使用两个以上的字节).
此外,他们还添加了u8""编写文字UTF-8编码字符串的语法.由于UTF-8的编码是与经营的大部分功能兼容char *和std::string,这是最有用的新增加的一个.
但是,它们似乎未能添加任何方式来在UTF-8,UTF-16和UTF-32之间进行可移植转换.的mbtoc16实现中定义多字节编码和UTF-16或32之间,并且相关的功能转换; 但你不能依赖这是UTF-8.在类Unix的平台上,它依赖于语言环境,并且其中许多默认情况下在其语言环境中使用UTF-8,即使它不是默认语言,您至少可以将语言环境设置为UTF-8语言环境以便知道"多字节"表示UTF-8.但是,在Windows上,您明确不能使用UTF-8或任何其他需要超过两个字节的编码.
我只是遗漏了一些东西,或者是UTF-8字符串类型没有任何方式将其转换为其他类型的字符串:平台定义的多字节,平台定义的宽字符,UTF-16或UTF-32?甚至无法判断您的系统多字节编码是否为UTF-8?是否有任何理由不包括这种支持(具体来说,我正在寻找C或C++标准委员会的实际书面理由或讨论,而不仅仅是猜测)?是否有任何工作要改善这种情况; 是否有可能在未来改善?
或者,是目前最好的解决办法,如果你想支持UTF-8在便携时尚,写自己的实现,拉库的依赖,或使用特定于平台的功能,如iconv和MultiByteToWideChar?
我必须经历一些文本并根据字符模式编写UTF8输出.我认为如果我可以使用代码点并将其转换为UTF8将会很容易.我一直在阅读有关unicode和UTF8的内容,但无法找到一个好的解决方案.任何帮助将不胜感激.