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

如何在C++20中基于通用字符类型创建字符串字面量?

在C++20中基于通用字符类型创建字符串字面量

我们可以借助C++20的非类型模板参数扩展特性,实现一个通用的字符串字面量转换工具gstring,支持将任意字符类型的字面量转换为目标字符类型的编译期字符串。

核心实现代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>

namespace detail {
    // 编译期单个字符类型转换
    template<typename DestChar, typename SrcChar>
    constexpr DestChar char_cast(SrcChar c) noexcept {
        return static_cast<DestChar>(c);
    }

    // 编译期字符串转换模板,生成目标字符数组
    template<typename DestChar, std::size_t N, typename SrcChar>
    struct converted_string {
        constexpr converted_string(const SrcChar (&src)[N]) noexcept {
            for (std::size_t i = 0; i < N; ++i) {
                data[i] = char_cast<DestChar>(src[i]);
            }
        }
        DestChar data[N];
    };

    // 自动推导源字符串的长度与类型
    template<typename DestChar, typename SrcChar, std::size_t N>
    converted_string(const SrcChar (&)[N]) -> converted_string<DestChar, N, SrcChar>;
}

// 字符串字面量包装器,用于捕获字面量内容作为非类型模板参数
template<std::size_t N>
struct StringLiteral {
    constexpr StringLiteral(const char (&str)[N]) noexcept {
        std::copy_n(str, N, value);
    }
    char value[N];
};

template<std::size_t N>
struct WideStringLiteral {
    constexpr WideStringLiteral(const wchar_t (&str)[N]) noexcept {
        std::copy_n(str, N, value);
    }
    wchar_t value[N];
};

// 推导指南,简化包装器的使用
template<std::size_t N>
StringLiteral(const char (&)[N]) -> StringLiteral<N>;

template<std::size_t N>
WideStringLiteral(const wchar_t (&)[N]) -> WideStringLiteral<N>;

// 对外接口:将包装后的字面量转换为目标字符类型的字符串指针
template<typename StringLiteral, typename DestChar>
constexpr const DestChar* gstring() noexcept {
    static constexpr detail::converted_string<DestChar> conv{StringLiteral{}.value};
    return conv.data;
}

测试用例验证

int main(int argc, char const* argv[]) {
    {
        constexpr wchar_t const* v = gstring<StringLiteral<12>("hello world"), wchar_t>();
        std::wcout << v << std::endl;
        std::wcout << std::wcslen(v) << std::endl;
    }
    {
        constexpr char const* v = gstring<WideStringLiteral<12>(L"world hello"), char>();
        std::cout << v << std::endl;
        std::cout << std::strlen(v) << std::endl;
    }
    return 0;
}

输出结果

hello world
11
world hello
11

实用场景示例

在模板函数中,无需为不同字符类型编写重复的字符串字面量:

template <typename TChar>
void AddFoo(std::basic_string<TChar> & s){
    s.append( gstring<StringLiteral<4>("foo"), TChar>() );
}

实现关键点

  1. 非类型模板参数捕获字面量:通过StringLiteral和WideStringLiteral包装结构体,将字符串字面量的内容作为非类型模板参数传递,符合C++20的语法规则
  2. 编译期转换:所有转换逻辑都在编译期完成,运行时无额外开销
  3. 通用适配:支持任意源字符类型到目标字符类型的转换,可扩展char_cast函数处理复杂字符集(如UTF-8/16转换)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:55:26