如何将字符串字面量转换为char参数包实现编译期字符串拼接?
解决static_string与普通字符串字面量的编译期拼接问题
核心问题是普通字符串字面量作为const char*参数时,str[Is]无法成为常量表达式——因为指针退化为运行时类型,编译器无法确认其指向的是编译期可见的数组。解决思路是让编译器推导字符串字面量的编译期数组类型,而非指针,再通过std::index_sequence生成编译期索引来展开字符。
1. 修复make_static_string,支持编译期数组转换
利用模板推导数组大小,结合std::index_sequence生成编译期索引序列,确保str[Is]是常量表达式:
#include <utility> template<size_t Size> struct static_string { char data[Size]{}; // 接收字符参数的constexpr构造函数 constexpr static_string(char... chars) : data{chars...} {} // static_string之间的拼接逻辑 template<size_t OtherSize> constexpr auto operator+(const static_string<OtherSize>& other) const { static_string<Size + OtherSize> result; // 编译期复制数据 for (size_t i = 0; i < Size; ++i) { result.data[i] = data[i]; } for (size_t i = 0; i < OtherSize; ++i) { result.data[Size + i] = other.data[i]; } return result; } }; // 辅助实现:通过索引序列展开字符 template<size_t N, size_t... Is> constexpr auto make_static_string_impl(const char (&str)[N], std::index_sequence<Is...>) { // N包含末尾的'\0',生成Size=N-1的static_string return static_string<N-1>{str[Is]...}; } // 对外接口:推导字符串数组大小,生成索引序列 template<size_t N> constexpr auto make_static_string(const char (&str)[N]) { return make_static_string_impl(str, std::make_index_sequence<N-1>{}); } // 自定义字面量(复用原有实现) constexpr static_string<sizeof(str)-1> operator""_ss(const char* str, size_t size) { return make_static_string(str); }
2. 添加与普通字符串字面量的拼接运算符
为static_string和const char[]重载operator+,直接复用已有static_string间的拼接逻辑:
// static_string + 普通字符串字面量 template<size_t LhsSize, size_t RhsSize> constexpr auto operator+(const static_string<LhsSize>& lhs, const char (&rhs)[RhsSize]) { return lhs + make_static_string(rhs); } // 普通字符串字面量 + static_string template<size_t LhsSize, size_t RhsSize> constexpr auto operator+(const char (&lhs)[LhsSize], const static_string<RhsSize>& rhs) { return make_static_string(lhs) + rhs; }
3. 测试示例
constexpr auto hello = "Hello"_ss; constexpr auto hello_world = hello + "World"; // hello_world是static_string<10>,编译期内容为"HelloWorld" constexpr auto hi_world = "Hi" + hello_world; // hi_world是static_string<12>,编译期内容为"HiHelloWorld"
关键原理说明
- 使用
const char (&str)[N]作为参数时,编译器会推导字符串字面量的编译期数组大小N,此时str[Is]是常量表达式(数组是编译期可见的,索引Is由std::index_sequence生成,也是编译期常量)。 - 若参数为
const char*,编译器无法确认指针指向的是编译期数组,因此str[Is]无法在模板展开时作为常量表达式使用。
内容的提问来源于stack exchange,提问作者mezo
相关产品推荐
相关产品推荐

