如何从constexpr std::string_view构造constexpr static_string?
从constexpr std::string_view构造static_string的问题
初始实现
用户实现的static_string模板如下:
template <std::size_t N> struct static_string { std::array<char, N + 1> elements_; constexpr static_string() noexcept : elements_{} {} constexpr static_string(const char (&data)[N + 1]) noexcept { for (size_t i = 0; i < N + 1; i++) { elements_[i] = data[i]; } } }; template <std::size_t N> static_string(const char (&)[N]) -> static_string<N - 1>;
使用constexpr static_string str1("this is a str");可正常编译运行。
添加string_view构造后的问题
为支持从constexpr std::string_view构造,添加了以下构造函数:
constexpr static_string(std::string_view sv) noexcept { for (size_t i = 0; i < N; ++i) { elements_[i] = sv[i]; } }
但运行以下代码时出现编译错误:
constexpr std::string_view sv = "this is a str"; constexpr static_string<sv.size()> str2(sv);
编译器错误信息
<source>: In function 'int main()': <source>:33:47: error: 'static_string<13>{std::array<char, 14>{std::__array_traits<char, 14>::_Type{'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 's', 't', 'r'}}}' is not a constant expression 33 | constexpr static_string<sv.size()> str2(sv); | ^ <source>:33:47: error: 'static_string<13>(sv)' is not a constant expression because it refers to an incompletely initialized variable
问题原因
- 数组未完全初始化:
elements_是大小为N+1的数组,但新增的构造函数仅复制了N个字符,未初始化最后一个位置的字符串终止符\0。在常量表达式求值语境中,对象的所有成员必须完成初始化,未初始化的成员会导致表达式无法被认定为常量表达式。 - 缺少长度校验:构造函数未在编译期校验
sv.size()是否等于N,若传入的string_view长度不匹配,会导致越界访问或未初始化问题,进一步违反常量表达式的求值规则。
可行的实现方案
修改构造函数,确保数组完全初始化,并添加编译期长度校验:
template <std::size_t N> struct static_string { std::array<char, N + 1> elements_; constexpr static_string() noexcept : elements_{} {} constexpr static_string(const char (&data)[N + 1]) noexcept { for (size_t i = 0; i < N + 1; i++) { elements_[i] = data[i]; } } constexpr static_string(std::string_view sv) noexcept { // 编译期强制校验长度匹配 static_assert(sv.size() == N, "string_view size must match static_string's template parameter N"); // 复制有效字符 for (size_t i = 0; i < N; ++i) { elements_[i] = sv[i]; } // 初始化字符串终止符 elements_[N] = '\0'; } }; template <std::size_t N> static_string(const char (&)[N]) -> static_string<N - 1>; // 辅助函数简化构造(C++20及以上) constexpr auto make_static_string(std::string_view sv) { return static_string<sv.size()>{sv}; }
使用示例
constexpr std::string_view sv = "this is a str"; // 方式1:显式指定模板参数 constexpr static_string<sv.size()> str2(sv); // 方式2:通过辅助函数自动推导 constexpr auto str3 = make_static_string(sv);
修改后的代码确保了elements_的所有成员都完成初始化,同时编译期校验避免了长度不匹配的问题,满足常量表达式的求值要求。
内容的提问来源于stack exchange,提问作者miyan
相关产品推荐
相关产品推荐

