libc ++ vs VC++:可以使用wstring_convert完成非UTF转换吗?

Cub*_*bbi 8 c++ non-unicode c++11

在C++ 11的std::wstring_convert作品极大*为标准的UTF-8 < - > UTF-16/UCS2/UCS4转换.但是,当我尝试使用不是from的facet实例化wstring_convert或wbuffer_convert时<codecvt>,它没有按预期工作:

// 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"));
Run Code Online (Sandbox Code Playgroud)

Clang ++错误地说"在~wstring_convert中调用codecvt <>的受保护的析构函数"

Visual Studio允许它(尽管它缺少该语言环境,但这是另一个故事),因为它的wstring_convert将facet指针的生命周期管理作为成员的一个区域设置对象进行处理,并且locales知道如何删除指向所有facet的指针.

Visual Studio是正确的,libc ++是错误的吗?

*在clang ++ - 2.9/libc ++ - svn和Visual Studio 2010 EE SP1中实现,以下示例适用于两者,但不是在GCC中,遗憾的是:https://ideone.com/hywz6

How*_*ant 10

我承认在这个答案中有偏见.但我会尝试通过引用N3290(不幸的是不再公开)来支持我的主张.我也将提供解决方案.

分析:

wstring_convert[conversions.string]/p2 的概要包括:

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
Run Code Online (Sandbox Code Playgroud)

"仅展示"意味着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() {}
};
Run Code Online (Sandbox Code Playgroud)

您现在可以在代码中使用此通用适配器:

typedef usable_facet<std::codecvt<wchar_t, char, std::mbstate_t>> C;
std::wstring_convert<C> gbconv(new C("zh_CN.gb18030"));
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.