如何编写模板函数,基于const char*生成char/wchar_t字符串?
实现支持窄字符串到char/wchar_t字符串转换的模板函数
要实现你需要的模板函数,核心是处理窄字符串(UTF-8编码的const char*)到宽字符串(wchar_t)的编码转换,而当模板参数是char时直接返回原字符串即可。下面是完整的实现方案,包含跨平台兼容的转换逻辑:
核心实现思路
- 当模板参数
T为char时:直接将输入的const char*包装成std::string返回,无需转换。 - 当模板参数
T为wchar_t时:需要把UTF-8编码的窄字符串转换为对应平台的宽字符编码(Windows下是UTF-16,Linux/macOS下是UTF-32)。
完整代码实现
#include <string> #include <stdexcept> #include <clocale> #include <type_traits> #ifdef _WIN32 #include <windows.h> #endif // 辅助函数:UTF-8转std::wstring std::wstring utf8_to_wstring(const char* utf8_str) { if (!utf8_str) { return {}; } #ifdef _WIN32 // Windows平台使用MultiByteToWideChar处理UTF-8转UTF-16 int wide_len = MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, nullptr, 0); if (wide_len == 0) { throw std::runtime_error("Failed to convert UTF-8 to wide string"); } std::wstring wide_str(wide_len - 1, L'\0'); int result = MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, wide_str.data(), wide_len); if (result == 0) { throw std::runtime_error("Failed to write wide string data"); } return wide_str; #else // Linux/macOS平台使用mbsrtowcs(需确保系统LC_CTYPE为UTF-8) std::wstring wide_str; const char* ptr = utf8_str; std::mbstate_t state = std::mbstate_t(); // 先计算所需宽字符长度 size_t len = std::mbsrtowcs(nullptr, &ptr, 0, &state); if (len == static_cast<size_t>(-1)) { throw std::runtime_error("Invalid UTF-8 sequence detected"); } wide_str.resize(len); std::mbsrtowcs(wide_str.data(), &ptr, len + 1, &state); return wide_str; #endif } // 模板函数主实现(C++17及以上支持if constexpr) template<typename T> std::basic_string<T> test(const char* str) { if constexpr (std::is_same_v<T, char>) { return std::string(str); } else if constexpr (std::is_same_v<T, wchar_t>) { return utf8_to_wstring(str); } else { // 仅允许char和wchar_t作为模板参数 static_assert(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>, "Template parameter must be char or wchar_t"); return {}; } } // 兼容C++11/14的模板特化版本(可选) // template<> // std::basic_string<char> test<char>(const char* str) { // return std::string(str); // } // // template<> // std::basic_string<wchar_t> test<wchar_t>(const char* str) { // return utf8_to_wstring(str); // } // 测试代码 #include <iostream> int main() { try { std::string a = test<char>("haha"); std::wstring b = test<wchar_t>("哈哈"); std::cout << "std::string result: " << a << std::endl; std::wcout << L"std::wstring result: " << b << std::endl; } catch (const std::exception& e) { std::cerr << "Error occurred: " << e.what() << std::endl; return 1; } return 0; }
关键细节说明
模板分支处理:
- 使用
if constexpr在编译时判断模板参数类型,避免运行时开销(需要C++17及以上)。 - 如果要兼容C++11/14,可以注释掉主模板,改用下方的模板特化版本。
- 使用
跨平台编码转换:
- Windows平台:依赖
MultiByteToWideChar并指定CP_UTF8编码页,确保UTF-8到UTF-16(Windows的wchar_t为16位)的正确转换。 - Linux/macOS平台:使用
std::mbsrtowcs,需要确保程序运行环境的LC_CTYPE设置为UTF-8(现代系统默认已配置),否则可能出现转换乱码。
- Windows平台:依赖
错误处理:添加了空指针检查、转换失败抛出异常的逻辑,避免潜在的内存越界或乱码问题。
注意事项
- 输入的
const char*必须是UTF-8编码的字符串,否则转换会出现乱码。如果你的窄字符串是其他编码(比如GBK),需要调整转换函数中的编码参数(比如Windows下把CP_UTF8换成CP_ACP)。 - C++17中
std::wstring_convert被弃用,因此这里使用平台原生转换函数,兼容性更好。 - 若需要支持
char8_t等其他字符类型,可以扩展模板的分支判断逻辑。
内容的提问来源于stack exchange,提问作者Saddle Point
相关产品推荐
相关产品推荐

