对于标准的UTF-8< - >,C ++ 11的std::wstring_convert
非常适用于 *
。 UTF-16 / UCS2 / UCS4转换。但是,当我尝试使用不是<codecvt>
的方面实例化wstring_convert或wbuffer_convert时,它没有按预期工作:
// works as expected
std::wstring_convert<std::codecvt_utf8<wchar_t>> ucs4conv;
// Now, by analogy, I want to try this:
std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> gbconv(
new std::codecvt_byname<wchar_t, char, std::mbstate_t>("zh_CN.gb18030"));
Clang ++错误地说“在~wstring_convert中调用codecvt&lt;&gt;的受保护的析构函数”
Visual Studio允许它(尽管它缺少该语言环境,但这是另一个故事),因为它的wstring_convert将facet指针的生命周期管理作为成员的一个区域设置对象进行处理,并且locales知道如何删除指向所有方面。
Visual Studio是否正确,libc ++是错误的?
在clang ++ - 2.9 / libc ++ - svn和Visual Studio 2010 EE SP1中实现的 *
,以下示例适用于两者,但不适用于GCC,遗憾的是:https://ideone.com/hywz6
答案 0 :(得分:10)
我承认在这个答案中有偏见。但我会尝试通过引用N3290(不幸的是不再公开)来支持我的主张。我也将提供解决方案。
<强>分析:强>
[conversions.string] / p2中wstring_convert
的概要包括:
private:
byte_string byte_err_string; // exposition only
wide_string wide_err_string; // exposition only
Codecvt *cvtptr; // exposition only
state_type cvtstate; // exposition only
size_t cvtcount; // exposition only
“仅展示”意味着wstring_convert
不必通过此拼写按此顺序拥有这些成员。但是“仅限博览会”的成员用于描述各种成员的影响,而
所以问题似乎变成了:
~wstring_convert()
的规格是什么?
这可以在同一部分的第17页([conversions.string])中找到:
~wstring_convert();
效果:析构函数应删除
cvtptr
。
这意味着我必须可以访问~Codecvt()
,因此libc ++遵循C ++ 11规范。
我也同意这是对手的皇室痛苦。
<强>解决方案:强>
让所有C ++ 98/03方面都具有受保护的析构函数已经证明是非常不方便的。这是一个可以采用任何方面并为其提供公共析构函数的适配器:
template <class Facet>
class usable_facet
: public Facet
{
public:
template <class ...Args>
usable_facet(Args&& ...args)
: Facet(std::forward<Args>(args)...) {}
~usable_facet() {}
};
您现在可以在代码中使用此通用适配器:
typedef usable_facet<std::codecvt<wchar_t, char, std::mbstate_t>> C;
std::wstring_convert<C> gbconv(new C("zh_CN.gb18030"));
希望这有帮助。