You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写模板函数,基于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;
}

关键细节说明

  1. 模板分支处理:

    • 使用if constexpr在编译时判断模板参数类型,避免运行时开销(需要C++17及以上)。
    • 如果要兼容C++11/14,可以注释掉主模板,改用下方的模板特化版本。
  2. 跨平台编码转换:

    • Windows平台:依赖MultiByteToWideChar并指定CP_UTF8编码页,确保UTF-8到UTF-16(Windows的wchar_t为16位)的正确转换。
    • Linux/macOS平台:使用std::mbsrtowcs,需要确保程序运行环境的LC_CTYPE设置为UTF-8(现代系统默认已配置),否则可能出现转换乱码。
  3. 错误处理:添加了空指针检查、转换失败抛出异常的逻辑,避免潜在的内存越界或乱码问题。

注意事项

  • 输入的const char*必须是UTF-8编码的字符串,否则转换会出现乱码。如果你的窄字符串是其他编码(比如GBK),需要调整转换函数中的编码参数(比如Windows下把CP_UTF8换成CP_ACP)。
  • C++17中std::wstring_convert被弃用,因此这里使用平台原生转换函数,兼容性更好。
  • 若需要支持char8_t等其他字符类型,可以扩展模板的分支判断逻辑。

内容的提问来源于stack exchange,提问作者Saddle Point

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:20:12