【问题标题】:Deprecated header <codecvt> replacement不推荐使用的标头 <codecvt> 替换
【发布时间】:2021-07-31 10:39:37
【问题描述】:

有点前景:我的任务需要将 UTF-8 XML 文件转换为 UTF-16(当然要使用正确的标题)。所以我搜索了将 UTF-8 转换为 UTF-16 的常用方法,发现应该使用来自 &lt;codecvt&gt; 的模板。

但现在是deprecated,我想知道做同样任务的新常用方法是什么?

(完全不介意使用 Boost,但除此之外,我更喜欢尽可能接近标准库。)

【问题讨论】:

    标签: c++ utf-8 c++17 utf-16 codecvt


    【解决方案1】:

    别担心。

    根据the same information source

    此库组件应与附件 D 一起退出, 直到合适的替代品被标准化

    因此,在新的标准化、更安全的版本完成之前,您仍然可以使用它。

    【讨论】:

    • 不幸的是,这是一厢情愿的想法。弃用was applied to C++17。建议显然是:“用户应该改用专用的文本处理库。” Visual Studio 2017 将在使用时发出弃用警告。
    • 什么专用的文本处理库?
    • 希望如此,因为在没有替代方案的情况下弃用某些东西有点太容易了。
    【解决方案2】:

    &lt;locale&gt; 中的std::codecvt 模板本身并未被弃用。对于 UTF-8 到 UTF-16,还有 std::codecvt&lt;char16_t, char, std::mbstate_t&gt; 特化。

    但是,由于 std::wstring_convertstd::wbuffer_convert 与标准转换构面一起被弃用,因此没有任何简单的方法可以使用构面转换字符串。

    所以,正如 Bolas 已经回答的那样:自己实现(或者您可以像往常一样使用第三方库)或继续使用已弃用的 API。

    【讨论】:

    • 但根据P0618 标头的all 已弃用。不仅仅是类型定义; std::codecvt 已完全弃用。
    • @NicolBolas 该提案似乎没有建议对[locale.codecvt] 进行任何更改,其中定义了&lt;locale&gt; 标头的codecvt_base 和codecvt。但是,阅读文档,我可以看到 w{string,buffer}_convert 也已弃用,据我所知,这是唯一实际使用 codecvt 方面的标准函数。因此,即使 codecvt 没有被弃用,也没有任何简单的方法可以使用它们。您认为文档中std::codecvt 的省略是偶然的吗?
    • @user2079303 basic_filebuf 使用它。
    • P0618 只是标准委员会一名成员的提议,尽管是一个有影响力的提议。它没有说明该提案是否已被接受;如果是这样,它在下一个标准(可能在 2020 年代中期)之前不会被弃用,并且可能要到 2030 年左右才会被删除。我想编译器会继续支持它一段时间。
    • @RichardSmith 根据P0636R0,P0618R0 已应用于 C++17,这意味着自该标准修订版以来折旧生效。
    【解决方案3】:

    新方法是……你自己写。或者只是依赖已弃用的功能。希望标准委员会不会真正删除 codecvt,直到有一个有效的替代品。

    但目前还没有。

    【讨论】:

    • 问题出在:我需要最便携的方式来执行此操作。当然,总是有 icu、iconv 和其他各种 lib 之类的东西,但以前有一种相当直接的方法,涉及三行代码,现在完全是一团糟。
    • @login_not_failed 不是“曾经”,它仍然是,因为它没有被删除(并且暂时不会被删除)
    【解决方案4】:

    由于没有人真正回答问题并提供可用的替换代码,这里有一个,但它仅适用于 Windows:

    #include <string>
    #include <stdexcept>
    #include <Windows.h>
    
    std::wstring string_to_wide_string(const std::string& string)
    {
        if (string.empty())
        {
            return L"";
        }
    
        const auto size_needed = MultiByteToWideChar(CP_UTF8, 0, &string.at(0), (int)string.size(), nullptr, 0);
        if (size_needed <= 0)
        {
            throw std::runtime_error("MultiByteToWideChar() failed: " + std::to_string(size_needed));
        }
    
        std::wstring result(size_needed, 0);
        MultiByteToWideChar(CP_UTF8, 0, &string.at(0), (int)string.size(), &result.at(0), size_needed);
        return result;
    }
    
    std::string wide_string_to_string(const std::wstring& wide_string)
    {
        if (wide_string.empty())
        {
            return "";
        }
    
        const auto size_needed = WideCharToMultiByte(CP_UTF8, 0, &wide_string.at(0), (int)wide_string.size(), nullptr, 0, nullptr, nullptr);
        if (size_needed <= 0)
        {
            throw std::runtime_error("WideCharToMultiByte() failed: " + std::to_string(size_needed));
        }
    
        std::string result(size_needed, 0);
        WideCharToMultiByte(CP_UTF8, 0, &wide_string.at(0), (int)wide_string.size(), &result.at(0), size_needed, nullptr, nullptr);
        return result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多