将字符串存储在 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

将函数指针分配给 constexpr 结构中的 typedef 函数的正确 C++ 方法是啥?

constexpr 和不推荐使用的转换警告

字符串文字与整数中的C ++ constexpr vs宏

如何从预处理器#if 指令调用 constexpr 函数?

初始化constexpr std ::数组对