# std::codecvt

< cpp‎ | locale

定义于头文件 `<locale>` |  |
template< class InternT, class ExternT, class State > class codecvt; |  |

类模板 `std::codecvt` 封装字符串的转换，包括宽和多字节，从一种编码到另一种。通过 std::basic_fstream<CharT> 进行的所有 I/O 操作都使用流中感染的 std::codecvt<CharT, char, std::mbstate_t> 本地环境平面。

继承图

标准库提供以下独立（本地环境无关）特化：

定义于头文件 `<locale>`
std::codecvt<char, char, std::mbstate_t> | 恒等转换
std::codecvt<char16_t, char, std::mbstate_t> | 在 UTF-16 和 UTF-8 间转换 (C++11 起)(C++20 中弃用)
std::codecvt<char16_t, char8_t, std::mbstate_t> | 在 UTF-16 和 UTF-8 间转换 (C++20 起)
std::codecvt<char32_t, char, std::mbstate_t> | 在 UTF-32 和 UTF-8 间转换 (C++11 起)(C++20 中弃用)
std::codecvt<char32_t, char8_t, std::mbstate_t> | 在 UTF-32 和 UTF-8 间转换 (C++20 起)
std::codecvt<wchar_t, char, std::mbstate_t> | 在系统原生宽和单字节窄字符集间转换

另外， C++ 程序中构造每个的 locale 对象实装上述特化其自身的（本地环境特定）版本。

### 成员类型

成员类型 | 定义
`intern_type` | `InternT`
`extern_type` | `ExternT`
`state_type` | `State`

### 成员函数

(构造函数) | 构造新的 codecvt 平面 (公开成员函数)
(析构函数) | 销毁 codecvt 平面 (受保护成员函数)
out | 调用 `do_out` (公开成员函数)
in | 调用 `do_in` (公开成员函数)
unshift | 调用 `do_unshift` (公开成员函数)
encoding | 调用 `do_encoding` (公开成员函数)
always_noconv | 调用 `do_always_noconv` (公开成员函数)
length | 调用 `do_length` (公开成员函数)
max_length | 调用 `do_max_length` (公开成员函数)

### 成员对象

成员名 | 类型
`id` [静态] | std::locale::id

### 受保护成员函数

do_out [虚] | 从 internT 转换字符串为 externT 转换字符串，如在写入文件时 (虚受保护成员函数)
do_in [虚] | 从 externT 转换字符串为 internT ，如在从文件读取时 (虚受保护成员函数)
do_unshift [虚] | 为不完整转换生成 externT 字符的终止字符序列 (虚受保护成员函数)
do_encoding [虚] | 返回产生一个 internT 字符所需的 externT 字符数，若此值为常数 (虚受保护成员函数)
do_always_noconv [虚] | 测试平面编码是否对所有合法值为恒等转换 (虚受保护成员函数)
do_length [虚] | 计算转换成给定的 internT 缓冲区会消耗的 externT 字符串长度 (虚受保护成员函数)
do_max_length [虚] | 返回能转换成单个 internT 字符的最大 externT 字符数 (虚受保护成员函数)

## 继承自 std::codecvt_base

成员类型 | 定义
enum result { ok, partial, error, noconv }; | 无作用域枚举类型

枚举常量 | 定义
`ok` | 完成转换而无错误
`partial` | 未转换所有源字符
`error` | 遇到非法字符
`noconv` | 不要求转换，输入与输出类型相同

### 示例

下例示例用在 codecvt<wchar_t, char, mbstate_t> 实现 UTF-8 转换的本地环境读取 UTF-8 环境，并用 std::codecvt 的标准特化转换 UTF-8 字符串为 UTF-16

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <locale>
    #include <iomanip>
    #include <codecvt>

    // 工具包装器，用于为 wstring/wbuffer 适配绑定到 locale 的平面
    template<class Facet>
    struct deletable_facet : Facet
    {
        template<class ...Args>
        deletable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}
        ~deletable_facet() {}
    };

    int main()
    {
        // UTF-8 窄多字节编码
        std::string data = reinterpret_cast<const char*>(+u8"z\u00df\u6c34\U0001f34c");
                           // 或 reinterpret_cast<const char*>(+u8"zß水🍌")
                           // 或 "\x7a\xc3\x9f\xe6\xb0\xb4\xf0\x9f\x8d\x8c"

        std::ofstream("text.txt") << data;

        // 使用系统提供的本地环境的 codecvt 平面
        std::wifstream fin("text.txt");
        // 从 wifstream 的读取将使用 codecvt<wchar_t, char, mbstate_t>
        // 此 locale 的 codecvt 从 UTF-8 转换到 UCS4 （在如 Linux 的系统上）
        fin.imbue(std::locale("en_US.UTF-8"));
        std::cout << "The UTF-8 file contains the following UCS4 code points: \n";
        for (wchar_t c; fin >> c; )
            std::cout << "U+" << std::hex << std::setw(4) << std::setfill('0') << c << '\n';

        // 使用标准（本地环境无关） codecvt 平面
        std::wstring_convert<
            deletable_facet<std::codecvt<char16_t, char, std::mbstate_t>>, char16_t> conv16;
        std::u16string str16 = conv16.from_bytes(data);

        std::cout << "The UTF-8 file contains the following UTF-16 code points: \n";
        for (char16_t c : str16)
            std::cout << "U+" << std::hex << std::setw(4) << std::setfill('0') << c << '\n';
    }

输出：

    The UTF-8 file contains the following UCS4 code points:
    U+007a
    U+00df
    U+6c34
    U+1f34c
    The UTF-8 file contains the following UTF-16 code points:
    U+007a
    U+00df
    U+6c34
    U+d83c
    U+df4c

### 参阅

字符转换 | 本地环境定义多字节 (UTF-8, GB18030) | UTF-8 | UTF-16
--- | --- | --- | ---
UTF-16 | `mbrtoc16` / `c16rtomb`(有 C11 的 DR488) | `codecvt`<char16_t, char, mbstate_t> `codecvt_utf8_utf16`<char16_t> `codecvt_utf8_utf16`<char32_t> `codecvt_utf8_utf16`<wchar_t> | N/A
UCS2 | `c16rtomb`(无 C11 的 DR488) | `codecvt_utf8`<char16_t> `codecvt_utf8`<wchar_t>(Windows) | `codecvt_utf16`<char16_t> `codecvt_utf16`<wchar_t>(Windows)
UTF-32 | `mbrtoc32` / `c32rtomb` | `codecvt`<char32_t, char, mbstate_t> `codecvt_utf8`<char32_t> `codecvt_utf8`<wchar_t>(非 Windows) | `codecvt_utf16`<char32_t> `codecvt_utf16`<wchar_t>(非 Windows)
系统宽 UTF-32(非 Windows) UCS2(Windows) | `mbsrtowcs` / `wcsrtombs` `use_facet`<`codecvt` <wchar_t, char, mbstate_t>>(`locale`) | 无 | 无

codecvt_base | 定义字符转换错误 (类模板)
codecvt_byname | 为具名本地环境构造 codecvt 平面 (类模板)
codecvt_utf8 (C++11)(C++17 中弃用) | 在 UTF-8 与 UCS2/UCS4 间转换 (类模板)
codecvt_utf16 (C++11)(C++17 中弃用) | 在 UTF-16 与 UCS2/UCS4 间转换 (类模板)
codecvt_utf8_utf16 (C++11)(C++17 中弃用) | 在 UTF-8 与 UTF-16 间转换 (类模板)