如何从constexpr类对象中提取编译时处理后的字符串?
编译时修改字符串字面量的类:解决数组初始化大小错误问题
问题描述
我有一个可通过constexpr构造的类,用于在编译时修改字符串字面量。但尝试提取处理后的数据时编译报错,代码如下:
#include <cstdio> #include <cstddef> template <const char* S> struct cxprstring { constexpr cxprstring() : data_{S} { // ... // (further processing of data_) } constexpr static const char value[] = cxprstring<S>{}.data_; char data_[] = {}; }; template <const char* S> constexpr const char format_view[] = cxprstring<S>::value; constexpr const char a[] = "hello "; int main() { printf("%s\n", format_view<a>); }
编译报错信息:
<source>:12:59: error: initializer fails to determine size of 'cxprstring<S>::value' 12 | constexpr static const char value[] = cxprstring<S>{}.data_; | ~~~~~~~~~~~~~~~~^~~~~ <source>:18:53: error: initializer fails to determine size of 'format_view<S>' 18 | constexpr const char format_view[] = cxprstring<S>::value; | ^~~~~
解决方案
核心问题是C++无法从未知大小的柔性数组(char data_[])推导静态数组value的大小,且柔性数组在constexpr上下文行为受限。以下是两种可行修改方案:
方案1:用std::array固定大小(需提前计算字符串长度)
通过constexpr函数计算原字符串长度,用std::array替代柔性数组,确保编译时确定大小:
#include <cstdio> #include <array> #include <cstring> // constexpr函数计算字符串长度 constexpr size_t str_len(const char* s) { size_t len = 0; while (s[len] != '\0') ++len; return len; } template <const char* S> struct cxprstring { static constexpr size_t len = str_len(S); std::array<char, len + 1> data_; // +1存储终止符 constexpr cxprstring() { // 复制原字符串 for (size_t i = 0; i <= len; ++i) { data_[i] = S[i]; } // 示例处理:首字符转大写 if (len > 0 && data_[0] >= 'a' && data_[0] <= 'z') { data_[0] -= 32; } } constexpr static auto value = cxprstring<S>{}.data_; }; template <const char* S> constexpr auto format_view = cxprstring<S>::value; constexpr const char a[] = "hello "; int main() { printf("%s\n", format_view<a>.data()); // 输出:Hello }
方案2:直接用constexpr函数生成处理后的字符串
跳过类封装,直接通过constexpr函数处理字符串并返回固定大小的容器:
#include <cstdio> #include <cstring> #include <array> constexpr size_t str_len(const char* s) { size_t len = 0; while (s[len] != '\0') ++len; return len; } // constexpr函数处理字符串,返回std::array template <size_t N> constexpr auto process_string(const char (&s)[N]) { std::array<char, N> result{}; for (size_t i = 0; i < N; ++i) { result[i] = s[i]; } // 示例处理:反转字符串 for (size_t i = 0; i < (N-1)/2; ++i) { char temp = result[i]; result[i] = result[N-2 - i]; result[N-2 - i] = temp; } return result; } template <const char* S> constexpr auto format_view = process_string(S); constexpr const char a[] = "hello "; int main() { printf("%s\n", format_view<a>.data()); // 输出: olleh }
关键说明
- 柔性数组无法在
constexpr静态成员初始化中使用,编译器无法推导其大小。 std::array能在编译时确定大小,完全适配constexpr上下文。- 若需动态调整处理后字符串长度,C++20及以后可使用
constexpr std::string,但静态成员仍需固定大小,此时推荐方案2的函数式处理。
内容的提问来源于stack exchange,提问作者glades
相关产品推荐
相关产品推荐

