C++17/20中std::codecvt_utf8_utf16<char16_t>替代方案及编译问题求助
解决方案汇总
一、临时解决std::wstring_convert的LNK2001错误
虽然std::wstring_convert已被C++17弃用,但如果要先让现有代码编译通过,针对MSVC编译器需注意:
- 必须包含头文件:
#include <locale>和#include <codecvt> - 添加编译宏
_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING屏蔽弃用警告 - 不要用
__int16替代char16_t:char16_t是C++标准定义的UTF-16字符类型,__int16仅为16位整数,类型不匹配必然无效。另外确认项目编译模式(静态/动态链接标准库)配置正确,避免链接错误。
二、替代std::wstring_convert的UTF-8/UTF-16转换实现
既然官方已弃用该组件,推荐两种可靠替代方案:
方案1:Windows原生API(仅Windows平台)
利用系统API实现稳定转换,无需依赖标准库弃用组件:
#include <string> #include <windows.h> // UTF-8转UTF-16(std::wstring) std::wstring utf8_to_utf16(const std::string& utf8_str) { if (utf8_str.empty()) return {}; int wide_len = MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), (int)utf8_str.size(), nullptr, 0); std::wstring wide_str(wide_len, 0); MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), (int)utf8_str.size(), wide_str.data(), wide_len); return wide_str; } // UTF-16(std::wstring)转UTF-8 std::string utf16_to_utf8(const std::wstring& utf16_str) { if (utf16_str.empty()) return {}; int utf8_len = WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), (int)utf16_str.size(), nullptr, 0, nullptr, nullptr); std::string utf8_str(utf8_len, 0); WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), (int)utf16_str.size(), utf8_str.data(), utf8_len, nullptr, nullptr); return utf8_str; }
方案2:跨平台手动实现
如果需要跨平台运行,可以自己实现基础的编码转换逻辑,核心处理码点转换:
#include <string> #include <stdexcept> // UTF-8转UTF-16 std::u16string utf8_to_utf16(const std::string& utf8) { std::u16string result; size_t i = 0; while (i < utf8.size()) { unsigned char c = utf8[i]; uint32_t codepoint; if (c < 0x80) { codepoint = c; i++; } else if (c < 0xE0) { if (i + 1 >= utf8.size()) throw std::invalid_argument("Invalid UTF-8"); codepoint = ((c & 0x1F) << 6) | (utf8[i+1] & 0x3F); i += 2; } else if (c < 0xF0) { if (i + 2 >= utf8.size()) throw std::invalid_argument("Invalid UTF-8"); codepoint = ((c & 0x0F) << 12) | ((utf8[i+1] & 0x3F) << 6) | (utf8[i+2] & 0x3F); i += 3; } else { if (i + 3 >= utf8.size()) throw std::invalid_argument("Invalid UTF-8"); codepoint = ((c & 0x07) << 18) | ((utf8[i+1] & 0x3F) << 12) | ((utf8[i+2] & 0x3F) << 6) | (utf8[i+3] & 0x3F); i += 4; } if (codepoint <= 0xFFFF) { result += static_cast<char16_t>(codepoint); } else { // 处理UTF-16代理对 codepoint -= 0x10000; result += static_cast<char16_t>(0xD800 + (codepoint >> 10)); result += static_cast<char16_t>(0xDC00 + (codepoint & 0x3FF)); } } return result; } // UTF-16转UTF-8 std::string utf16_to_utf8(const std::u16string& utf16) { std::string result; size_t i = 0; while (i < utf16.size()) { char16_t c = utf16[i]; uint32_t codepoint; if (c >= 0xD800 && c <= 0xDBFF) { if (i + 1 >= utf16.size()) throw std::invalid_argument("Invalid UTF-16"); char16_t c2 = utf16[i+1]; if (!(c2 >= 0xDC00 && c2 <= 0xDFFF)) throw std::invalid_argument("Invalid UTF-16"); codepoint = ((static_cast<uint32_t>(c) - 0xD800) << 10) + (static_cast<uint32_t>(c2) - 0xDC00) + 0x10000; i += 2; } else { codepoint = c; i++; } if (codepoint <= 0x7F) { result += static_cast<char>(codepoint); } else if (codepoint <= 0x7FF) { result += static_cast<char>(0xC0 | (codepoint >> 6)); result += static_cast<char>(0x80 | (codepoint & 0x3F)); } else if (codepoint <= 0xFFFF) { result += static_cast<char>(0xE0 | (codepoint >> 12)); result += static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F)); result += static_cast<char>(0x80 | (codepoint & 0x3F)); } else { result += static_cast<char>(0xF0 | (codepoint >> 18)); result += static_cast<char>(0x80 | ((codepoint >> 12) & 0x3F)); result += static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F)); result += static_cast<char>(0x80 | (codepoint & 0x3F)); } } return result; }
三、解决std::from_chars/std::to_chars的支持问题
如果编译器提示找不到这些函数,按以下步骤排查:
- 升级编译器版本:MSVC从VS2017 15.5版本开始才完整支持
std::from_chars/std::to_chars的整数转换,旧版本需升级到VS2017 15.5+或更高(如VS2019/2022)。 - 检查项目配置:右键项目→属性→配置属性→C/C→语言→C语言标准,选择
ISO C++17 标准 (/std:c++17)或更高;旧版VS可尝试选择预览 - 最新C++工作草案标准 (/std:c++latest)。 - 确认头文件:
std::from_chars/std::to_chars定义在<charconv>头文件中,必须包含该文件,而非<string>等其他头文件。
若仍无法解决,可暂时改用std::stoi/std::to_string等兼容函数,或平台特定转换接口(如Windows的_wtoi/_itow_s)。
内容的提问来源于stack exchange,提问作者wpf
相关产品推荐
相关产品推荐

