【问题标题】:libc++ vs VC++: Can non-UTF conversions be done with wstring_convert?libc++ vs VC++:可以用 wstring_convert 完成非 UTF 转换吗?
【发布时间】:2011-11-27 19:25:29
【问题描述】:

C++11 的 std::wstring_convert 非常适合标准 UTF-8 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 的受保护析构函数”

Visual Studio 允许它(尽管它缺少该语言环境,但这是另一回事),因为它的 wstring_convert 将 facet 指针的生命周期管理典当到它作为成员持有的语言环境对象,并且语言环境知道如何删除指向各个方面。

Visual Studio 是对的,而 libc++ 错了吗?

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

【问题讨论】:

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


    【解决方案1】:

    我承认这个答案有偏见。但我将尝试通过引用 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()的规格是什么?

    这可以在同一部分的 p17 中找到([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"));
    

    希望这会有所帮助。

    【讨论】:

    • 它还表示模板参数 Codecvt meets the requirements of the standard code-conversion facet std::codecvt&lt; (§ 22.3.3.2.2/3)。并且 std::codecvt 是用受保护的 dtor 定义的。也许“应删除cvtptr”并不意味着“与delete cvtptr;相同”?不过感谢您的包装。
    • 我会打开一个查询。在这一点上,我不确定最好的分辨率是什么。花费创建一个新的locale 来保存Codecvt* 对我来说似乎是一种耻辱,否则一个简单的指针存储就可以做到。
    • 哦,刚刚查了一下。该问题已经打开并决定NAD:open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#721
    • @Howard :将问题标记为 NAD 因为“codecvt 不适合初学者”似乎有点逃避。有没有可能重新打开这个问题?
    • @Bo :除了在这种情况下,“按设计工作”显然意味着“没有额外的、毫无意义的努力就无法工作”。 :-/ (另外,我确实注意到您提交了原始问题,所以我认为您可以提供更多见解。:-])
    猜你喜欢
    • 2015-01-15
    • 1970-01-01
    • 2013-10-11
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多