可以在constexpr中使用std :: string吗?


175

使用C ++ 11,Ubuntu 14.04和GCC默认工具链

此代码失败:

constexpr std::string constString = "constString";

错误:constexpr变量'constString'的类型'const string {aka const std :: basic_string}'不是字面量...因为...'std :: basic_string'具有非平凡的析构函数

是否有可能使用std::stringconstexpr?(显然不是...)如果是这样,怎么办?有没有在字符串中使用字符串的替代方法constexpr


2
std::string不是文字类型
Piotr Skotnicki 2014年

7
@PiotrS-问题说……
矢量

4
@Vector我问过您constexpr是干什么的,或者为什么要std::string成为constexpr?在SO上有几种编译时字符串实现。如果您理解错误消息并知道只能将文字类型设置为constexpr,那么问您是否可以使非文字类型的constexpr有什么意义呢?以及为什么有人想要一个constexpr实例的原因有很多,所以我建议您澄清一下问题
Piotr Skotnicki 2014年

2
是的@PiotrS。说,那里有constexpr字符串实现。std::string不是其中之一。
tenfour 2014年

3
@PiotrS- 在SO上有几种编译时字符串实现 -好的,谢谢,理解。这对我来说不是一个选择,但它回答了我的问题:std :: string无法正常工作。正如我对tenfour所说的那样,我想知道是否有一种方法可以使用std :: string。我当然不知道很多技巧。
矢量

Answers:


167

不,您的编译器已经为您提供了全面的说明。

但是您可以这样做:

constexpr char constString[] = "constString";

在运行时,可用于std::string在需要时构造一个。


78
为什么不constexpr auto constString = "constString";呢?无需使用这种丑陋的数组语法;-)
stefan 2014年

80
在这个问题的背景下,这一点更加清楚。我的意思是您可以选择哪种字符串类型。char[]auto我要强调要使用的数据类型更冗长/清晰。
tenfour 2014年

7
@tenfour是的,这很不错。我想我有时过于专注于使用auto;-)
stefan 2014年

1
@FelixDombek没有,但与C ++ 17可以使用constexpr auto s = "c"sv;,由于引进string_view
至极

6
在那种情况下constexpr一个char数组有意义吗?如果您使用它来构造字符串,则无论如何都要复制它。将文字传递给字符串的构造函数与将这样的constexpr数组传递给它有什么区别?
KjMag '17年

167

C ++ 20开始,是的。

C ++ 17开始,您可以使用string_view

constexpr std::string_view sv = "hello, world";

A string_viewstring类对象,它充当对任何char对象序列的不可变的,没有所有权的引用。


6
请注意,每当将此常量传递给const std::string&采用新std :: string 的函数时,都必须构造它。这通常与创建常量时所想到的相反。因此,我倾向于说这不是一个好主意。至少您必须要小心。
拉姆·拉蒙

29
@RamboRamon string_view不能隐式转换为string,因此string从a 意外构造a的危险很小string_view。相反,char const* 可以隐式转换为string,因此string_view从这个意义上讲,使用实际上更安全。
约瑟夫·汤姆森

4
感谢您的澄清。我完全同意,确实忘记了string_view不能隐式转换为string。IMO我提出的问题仍然有效,但不适用于string_view特定情况。实际上,正如您提到的那样,在这方面更安全。
Rambo Ramon '18

5
如果这个答案能说更多有关什么string_view的信息,而不仅仅是一个链接,那就太好了。
eric '18

22

C ++ 20将添加constexpr字符串和向量

显然已接受以下提议:http : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0980r0.pdf并添加了以下构造函数:

// 20.3.2.2, construct/copy/destroy
constexpr
basic_string() noexcept(noexcept(Allocator())) : basic_string(Allocator()) { }
constexpr
explicit basic_string(const Allocator& a) noexcept;
constexpr
basic_string(const basic_string& str);
constexpr
basic_string(basic_string&& str) noexcept;

除了所有/大多数方法的constexpr版本。

自GCC 9.1.0起不提供支持,以下内容无法编译:

#include <string>

int main() {
    constexpr std::string s("abc");
}

与:

g++-9 -std=c++2a main.cpp

错误:

error: the type const string {aka const std::__cxx11::basic_string<char>’} of constexpr variable s is not literal

std::vector讨论在:无法创建constexpr std :: vector

在Ubuntu 19.04中测试。


19

由于问题是非平凡的析构函数,因此,如果从中删除了析构函数std::string,则可以定义constexpr该类型的实例。像这样

struct constexpr_str {
    char const* str;
    std::size_t size;

    // can only construct from a char[] literal
    template <std::size_t N>
    constexpr constexpr_str(char const (&s)[N])
        : str(s)
        , size(N - 1) // not count the trailing nul
    {}
};

int main()
{
    constexpr constexpr_str s("constString");

    // its .size is a constexpr
    std::array<int, s.size> a;
    return 0;
}

18
这基本上就是C ++ 17 string_view的,但string_view最让你的功能,你知道,从std::string
至极
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.