为什么wstring_convert抛出range_error

Why is wstring_convert throwing a range_error?

本文关键字:range error 抛出 convert wstring 为什么      更新时间:2023-10-16

我正在编写一些代码,需要使用系统区域设置在字节字符串和宽字符串之间进行转换。当从文件中读取时,这是非常容易做到的。我可以先用std::wifstream,再用std::locale(""),然后只用std::getline

根据cppreference的codecvt页面,wifstream只是使用codecvt<wchar_t, char, mbstate_t>,所以我认为我可以通过使用std::stringstd::wstring之间转换:

// utility wrapper to adapt locale-bound facets for wstring/wbuffer
convert
template<class Facet>
struct deletable_facet : Facet
{
    template<class ...Args>
    deletable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}
    ~deletable_facet() {}
};
std::locale::global(std::locale(""));
std::wstring_convert<
    deletable_facet<std::codecvt<wchar_t, char, std::mbstate_t>>> wconv;
std::wstring wstr = wconv.from_bytes(data);

然而,当我试图运行这个,我得到一个range_errorwstring_convert抛出。我做了一些谷歌搜索,显然这是当wstring_convert无法转换字符串时发生的情况。

然而,这些字符串显然完全能够使用wfstream进行转换,这应该使用与wstring_convert相同的codecvt。那么为什么wifstream起作用,而wstring_convert不起作用呢?

是否有一种方法可以让我在string s和wstring s之间转换使用系统的区域设置?

这里是我的问题的完整示例,改编自codecvt页面,输出是:

sizeof(char32_t) = 4
sizeof(wchar_t)  = 4
The UTF-8 file contains the following UCS4 code points: 
U+007a
U+00df
U+6c34
U+1f34c
The UTF-8 string contains the following UCS4 code points: 
U+007a
U+00df
U+6c34
U+1f34c
terminate called after throwing an instance of 'std::range_error'
  what():  wstring_convert
Aborted (core dumped)

您的wifstreamwstring_convert使用不同的facet

wifstream正在使用语言环境相关的转换facet;通过std::use_facet

将其从注入的std::locale("")中取出。

wstring_convert被赋予了一个独立于语言环境的独立编码面,而你的实现提供的编码面显然不会将UTF-8转换成任何合适的内容;试着直接调用它,看看它是怎么做的。

获取依赖于语言环境的facet的一种简单方法是按名称请求它,如std:: codecvt_byname

相关文章: