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

时间:2011-09-29 15:15:54

标签: c++ c++11 non-unicode

对于标准的UTF-8&lt; - &gt;,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

1 个答案:

答案 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"));

希望这有帮助。