将字符串存储在 constexpr 结构中
Posted
技术标签:
【中文标题】将字符串存储在 constexpr 结构中【英文标题】:store a string in a constexpr struct 【发布时间】:2019-12-31 10:22:59 【问题描述】:是否可以将字符串存储在constexpr
结构中:
到目前为止,我只能想出:
struct A
constexpr A(std::string_view n): m_name(n)
constexpr auto name() return m_name;
std::string_view m_name; // This might become dangling!!
如果这个类只像这样使用,这显然是个好主意
A a = "Hello";
constexpr A b = "World";
不是这样的
auto makeA(std::string n) return An;
A a = makeA("Hello"); // Dangling internal std::string_view
我需要constexpr
在编译时构造结构。
是否有可能在运行时使其更安全,因为使用std::string_view
,它不是。
【问题讨论】:
拍一个 "char_sequence",像 operator ""_cs 这样的东西可能会有所帮助。 制作 2 个相似类型怎么样。一个是std::string_view
,一个是std::string
?在编译时使用std::string_view
类型,在其他时候使用std::string
类型。也许添加从编译时到运行时类型的隐式转换。
要使用 constexpr,您需要牢记编译器需要知道 constexpr 元素的最终值,否则它不能是 const。
【参考方案1】:
这并不是一个真正的安全问题,而是一个语义问题。没有什么能阻止你在编译时做同样的事情:
constexpr A blub()
char str[] = "asdf";
return str ;
由于无法在核心常量表达式中调用此函数,因此包含此类代码的程序格式不正确,不需要诊断 [dcl.constexpr]/5,这实际上并不比在运行时…
编译时与否,你必须问自己一个问题:这个结构应该拥有一个字符串还是引用一个现有的字符串?我强烈建议不要让你的结构在运行时上下文中拥有一个字符串,并在编译时上下文中引用一个现有的字符串,即使你找到了一种在理论上实现这一点的方法。我们在这里讨论的是完全不同的语义。完全不同的语义通常应该由不同的类型更好地建模,而不是一种类型会根据上下文完全改变其含义……
如果你想让一个 constexpr 结构拥有一个字符串,你目前必须求助于一些 constexpr 字符串实现,例如,this one。由于您的问题标有c++20,请注意std::string
将可用于以C++20 [basic.string] 开头的constexpr 上下文。因此,在 C++20 中,您将能够让成员成为 std::string
...
【讨论】:
"注意 std::string 可以在以 C++20 开头的 constexpr 上下文中使用" 除了这样的字符串不能在constexpr
上下文之外生存。 【参考方案2】:
你可以这样做:
template<typename Char, Char... Cs>
struct CharSeq
static constexpr const Char s[] = Cs..., 0; // The unique address
;
// That template uses the extension
template<typename Char, Char... Cs>
constexpr CharSeq<Char, Cs...> operator"" _cs()
return ;
如果您不能使用扩展名,请参阅String-interning at compiletime for profiling 的回答以使用 MAKE_STRING
宏(对于接受的字符串长度确实更冗长且硬编码限制)。
然后
struct A
template <char ... Cs>
constexpr A(CharSeq<char, Cs...>) : m_name(CharSeq<char, Cs...>::s)
constexpr auto name() return m_name;
std::string_view m_name;
;
只有有效的用法类似于:
A a = "Hello"_cs;
constexpr A b = "World"_cs;
【讨论】:
以上是关于将字符串存储在 constexpr 结构中的主要内容,如果未能解决你的问题,请参考以下文章
使用 constexpr 函数替代 reinterpret_cast