C++ libc++;vs VC++;:非UTF转换可以通过wstring\U convert完成吗?

C++ libc++;vs VC++;:非UTF转换可以通过wstring\U convert完成吗?,c++,c++11,non-unicode,C++,C++11,Non Unicode,C++11的std::wstring_convert对于标准UTF-8 UTF-16/UCS2/UCS4转换非常有效。但是,当我尝试实例化一个wstring\u convert或wbuffer\u convert时,它没有按照预期工作: // works as expected std::wstring_convert<std::codecvt_utf8<wchar_t>> ucs4conv; // Now, by analogy, I want to try this

C++11的
std::wstring_convert
对于标准UTF-8 UTF-16/UCS2/UCS4转换非常有效。但是,当我尝试实例化一个wstring\u convert或wbuffer\u 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"));
//按预期工作
std::wstring_转换ucs4conv;
//现在,打个比方,我想试试这个:
std::wstring_convert gbconv(
新标准:编解码器名称(“zh_CN.gb18030”);
“在~wstring\u convert中调用codecvt的受保护析构函数”时出错

VisualStudio允许它(尽管它缺少该区域设置,但这是另一回事),因为它的wstring_convert将刻面指针的生存期管理转移到它作为成员持有的区域设置对象,并且区域设置知道如何删除指向所有刻面的指针

visualstudio是对的,libc++是错的吗


*
正如在clang++-2.9/libc++-svn和Visual Studio 2010 EE SP1中实现的那样,下面的示例在这两个版本上都有效,但在GCC中却不起作用,遗憾的是:

我承认在这个答案上有偏见。但我将尝试引用N3290(不幸的是,N3290不再公开)来支持我的主张。我还将提供一个解决方案

分析:

[conversions.string]/p2中的
wstring\u 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
“exposition only”表示
wstring\u convert
不必按此拼写将这些成员按此顺序排列。但“仅说明”成员用于描述各种成员的效果,这些规范具有约束力

因此,问题似乎变成了:

~wstring\u convert()
的规范是什么

这可以在同一节([conversions.string])的第17页找到:

~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() {}
};
模板
类可用的切面
:公共方面
{
公众:
模板
可用面(Args&&…Args)
:Facet(std::forward(args)…{}
~u facet(){}
};
现在,您可以在代码中使用此通用适配器:

typedef usable_facet<std::codecvt<wchar_t, char, std::mbstate_t>> C;
std::wstring_convert<C> gbconv(new C("zh_CN.gb18030"));
typedef-C;
std::wstring_convert gbconv(新C(“zh_CN.gb18030”);

希望这有帮助。

它还说模板参数codevt
满足标准代码转换方面的要求std::codevti将打开一个查询。在这一点上,我不确定最好的解决方案是什么。对我来说,花钱创建一个新的
locale
来保存
Codecvt*
,否则一个简单的指针存储就可以了。哦,只是查了一下。这个问题已经被公开并决定了。NAD:@Howard:将这个问题标记为NAD,因为“codevt不适合初学的程序员”看起来有点像是在逃避责任。有没有可能重新讨论这个问题?@Bo:除了在这种情况下,“按设计工作”显然意味着“没有额外的、毫无意义的努力就无法工作”。:-/(另外,我注意到您提交了原始版本,因此我认为您可以提供更多的见解。:-])