已弃用标头<codecvt>替换

log*_*led 54 c++ utf-8 utf-16 codecvt c++17

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

但现在当它被弃用时,我想知道执行相同任务的新常用方法是什么?

(根本不介意使用Boost,但除此之外我更喜欢尽可能靠近标准库.)

xml*_*lmx 24

别担心.

根据相同的信息来源:

该库组件应随后退回附件D, 直到合适的替代品标准化.

因此,您仍然可以使用它,直到完成新的标准化,更安全的版本.

  • 不幸的是,这是一厢情愿的想法.弃用[已应用于C++ 17](https://isocpp.org/files/papers/p0636r0.html).建议显然是:*"用户应该使用专用的文本处理库."*Visual Studio 2017将在使用时发出弃用警告. (7认同)
  • 如果随意改变“标准”而没有提供合适的替代品,那么“标准”有什么用呢?也许“标准”毕竟不是那么标准。难道“标准”委员会没有考虑到因弃用而没有合适的替代品而浪费的工时吗? (7认同)
  • 什么是专用的文本处理库? (2认同)
  • 我们希望如此,因为仅仅弃用某些东西而不提供替代方案有点太容易了。 (2认同)

eer*_*ika 18

std::codecvt<locale>不推荐使用自己的模板.对于UTF-8到UTF-16,仍然有std::codecvt<char16_t, char, std::mbstate_t>专业化.

但是,由于std::wstring_convert并且std::wbuffer_convert与标准转换方面一起被弃用,因此没有任何简单的方法来使用构面转换字符串.

因此,正如Bolas已经回答的那样:自己实施(或者你可以像往常一样使用第三方库)或继续使用已弃用的API.

  • 但根据[P0618](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html),*不推荐使用*codecvt>标头的所有*.不只是typedef; `std :: codecvt`完全被弃用. (5认同)
  • @NicolBolas该提议似乎没有建议对`[locale.codecvt]`进行任何更改,其中定义了`<locale>`标头的codecvt_base和codecvt.但是,阅读文档,我可以看到w {string,buffer} _convert也被弃用了,据我所知,这是实际使用codecvt facet的唯一标准函数.因此,即使不推荐使用codecvt,也没有任何简单的方法可以使用它们.你认为文件中遗漏`std :: codecvt`是偶然的吗? (4认同)
  • @ user2079303`basic_filebuf`使用它. (4认同)
  • @RichardSmith根据[P0636R0](https://isocpp.org/files/papers/p0636r0.html),P0618R0应用于C++ 17,这意味着折旧自标准修订版起生效. (4认同)

Bul*_*aza 17

由于没有人真正回答这个问题并提供可用的替换代码,这里有一个但仅适用于 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.data(), (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.data(), (int)string.size(), result.data(), 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.data(), (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.data(), (int)wide_string.size(), result.data(), size_needed, nullptr, nullptr);
    return result;
}
Run Code Online (Sandbox Code Playgroud)


Nic*_*las 5

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

但目前,没有。

  • 问题是:我需要最便携的方式来做到这一点。当然总是有icu、iconv和其他各种库之类的东西,但以前有一个相当简单的方法,涉及三行代码,现在完全是一团糟。 (10认同)
  • @login_not_failed 不是“曾经”,它仍然是,因为它没有被删除(并且暂时不会被删除) (5认同)
  • 写了很长时间的C++,然后尝试Rust,然后回来做一些C++项目;我承认 Rust 好多了。我不明白为什么他们不推荐使用此功能而不提供替代品。 (2认同)