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

libc++ vs VC++: Can non-UTF conversions be done with wstring_convert?

本文关键字:utf 转换 convert vc++ vs 可以使 wstring libc++      更新时间:2023-10-16

c++ 11的std::wstring_convert工作得很好 * 用于标准UTF-8 <> UTF-16/UCS2/UCS4转换。然而,当我试图实例化一个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"));

clang++错误提示"在~wstring_convert中调用codecvt<>受保护的析构函数"

Visual Studio允许这样做(尽管它缺乏区域设置,但那是另一回事),因为它的wstring_convert将facet指针的生命周期管理转移到它作为成员持有的区域设置对象上,并且区域设置知道如何删除指向所有方面的指针。

是Visual Studio正确和libc++错误吗?

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

我承认我对这个答案有偏见。但我将尝试用N3290(不幸的是它不再公开可用)来支持我的说法。我也会提供一个解决方案。

分析:

[转换]中wstring_convert的概要。字符串)/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

"exposition only"表示wstring_convert不必按照这种拼写顺序拥有这些成员。但是"仅展示"成员用于描述各种成员的效果,这些规范绑定的。

那么问题就变成了:

~wstring_convert()的规格是什么?

这在同一节([conversion .string])的p17中找到:

~wstring_convert();

效果:析构函数将删除cvtptr

这对我来说意味着~Codecvt()必须是可访问的,因此libc++遵循c++ 11规范。

我也同意,这是一个皇家痛苦的屁股。

解决方案:

让所有c++ 98/03的facet都有保护析构函数是非常不方便的。下面是一个适配器,它可以接受任何facet,并给它一个公共析构函数:

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