2

是否可以将字符串存储在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 A{n}; }
A a = makeA("Hello"); // Dangling internal std::string_view

我需要constexpr在编译时构造结构。是否有可能在运行时使其更安全,因为std::string_view它不是。

4

2 回答 2

2

这实际上不是一个安全问题,而是一个语义问题。没有什么能阻止你在编译时做同样的事情:

constexpr A blub()
{
    char str[] = "asdf";
    return { str };
}

由于无法在核心常量表达式中调用此函数,因此包含此类代码的程序格式错误,不需要诊断[dcl.constexpr]/5,这实际上并不比调用未定义的行为更好在运行时…

编译时与否,你必须问自己一个问题:这个结构应该拥有一个字符串还是引用一个现有的字符串?我强烈建议不要让你的结构在运行时上下文中拥有一个字符串,并在编译时上下文中引用一个现有的字符串,即使你找到了一种在理论上实现这一点的方法。我们在这里讨论的是完全不同的语义。完全不同的语义通常应该由不同的类型更好地建模,而不是一种类型会根据上下文完全改变其含义……

如果你想让一个 constexpr 结构拥有一个字符串,你目前必须求助于一些 constexpr 字符串实现,例如this one。由于您的问题标有,请注意这std::string将在以 C++20 [basic.string]开头的 constexpr 上下文中使用。因此,在 C++20 中,您将能够让成员成为std::string……

于 2019-12-31T14:16:08.827 回答
1

你可能会这样做:

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 获得的答案,以获取宏(实际上更冗长,并且接受字符串长度的硬编码限制)。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};
于 2020-01-01T19:58:11.973 回答