如何让 wstring_convert::to_bytes 抛出 range_error 异常?
How can I get wstring_convert::to_bytes to throw a range_error exception?
我正在使用 std::wstring_convert
将 wstring 转换为多字节字符串,如下所示:
// convert from wide char to multibyte char
try
{
return std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(wideMessage);
}
// thrown by std::wstring_convert.to_bytes() for bad conversions
catch (std::range_error& exception)
{
// do something...
}
为了对我评论为 do something...
的块进行单元测试,我希望传递一个将引发 std::range_error
异常的 wstring。
但是,我无法制定这样一个会导致此类转换失败的 wstring。 wstring 将使用 UTF16,我一直在阅读有关高代理和低代理的信息。例如,D800 后跟 "b" 的 UTF16 字符应该是无效的。 std::wstring(L"\xd800b");
可能无法基于相同的理由进行编译。如果我创建如下所示的 wstring,它不会在转换时抛出异常:
std::wstring wideMessage(L" b");
wideMessage[0] = L'\xd800';
// doesn't throw
std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(wideMessage);
是否有合适的 wstring 可用于在转换期间抛出异常?
我试过 this link 的 5.1、5.2 和 5.3。我正在使用 Visual Studio 2015.
Microsoft 的 std::codecvt_utf8
实现似乎可以成功地将任何 UTF-16 代码单元转换为 UTF-8——包括代理项对。这是一个错误,因为代理不可编码。 libc++ (LLVM) 和 libstdc++ (GCC) 都会正确抛出 std::range_error
并且无法转换未配对的代理。
查看他们的代码,似乎它抛出的唯一方法是字符大于方面的 Maxcode
模板参数。例如:
std::wstring_convert<std::codecvt_utf8<wchar_t, 0x1>>
正如 一二三(接受的答案)所指出的那样,Microsoft 的 codecvt_utf8
实施似乎存在漏洞。
我知道我处理的字符串总是UTF16,我想转换成UTF8。我最终将实现更改如下:
// convert from wide char to multibyte char
try
{
return std::wstring_convert<std::codecvt_utf8_utf16 <wchar_t>>().to_bytes(wideMessage);
}
// thrown by std::wstring_convert.to_bytes() for bad conversions
catch (const std::range_error & exception)
{
// do something...
}
现在可以正确抛出以下内容:
std::wstring wideMessage(L" b");
wideMessage[0] = L'\xd800';
// throw std::range_error
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(wideMessage);
如果没有单元测试,我永远不会发现这个错误!
我正在使用 std::wstring_convert
将 wstring 转换为多字节字符串,如下所示:
// convert from wide char to multibyte char
try
{
return std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(wideMessage);
}
// thrown by std::wstring_convert.to_bytes() for bad conversions
catch (std::range_error& exception)
{
// do something...
}
为了对我评论为 do something...
的块进行单元测试,我希望传递一个将引发 std::range_error
异常的 wstring。
但是,我无法制定这样一个会导致此类转换失败的 wstring。 wstring 将使用 UTF16,我一直在阅读有关高代理和低代理的信息。例如,D800 后跟 "b" 的 UTF16 字符应该是无效的。 std::wstring(L"\xd800b");
可能无法基于相同的理由进行编译。如果我创建如下所示的 wstring,它不会在转换时抛出异常:
std::wstring wideMessage(L" b");
wideMessage[0] = L'\xd800';
// doesn't throw
std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(wideMessage);
是否有合适的 wstring 可用于在转换期间抛出异常?
我试过 this link 的 5.1、5.2 和 5.3。我正在使用 Visual Studio 2015.
Microsoft 的 std::codecvt_utf8
实现似乎可以成功地将任何 UTF-16 代码单元转换为 UTF-8——包括代理项对。这是一个错误,因为代理不可编码。 libc++ (LLVM) 和 libstdc++ (GCC) 都会正确抛出 std::range_error
并且无法转换未配对的代理。
查看他们的代码,似乎它抛出的唯一方法是字符大于方面的 Maxcode
模板参数。例如:
std::wstring_convert<std::codecvt_utf8<wchar_t, 0x1>>
正如 一二三(接受的答案)所指出的那样,Microsoft 的 codecvt_utf8
实施似乎存在漏洞。
我知道我处理的字符串总是UTF16,我想转换成UTF8。我最终将实现更改如下:
// convert from wide char to multibyte char
try
{
return std::wstring_convert<std::codecvt_utf8_utf16 <wchar_t>>().to_bytes(wideMessage);
}
// thrown by std::wstring_convert.to_bytes() for bad conversions
catch (const std::range_error & exception)
{
// do something...
}
现在可以正确抛出以下内容:
std::wstring wideMessage(L" b");
wideMessage[0] = L'\xd800';
// throw std::range_error
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(wideMessage);
如果没有单元测试,我永远不会发现这个错误!