C++20 constexpr 向量和字符串不起作用

Vla*_*lad 33 c++ stdstring visual-c++ constexpr c++20

constexpr std::string尝试创建and对象时出现奇怪的编译器错误std::vector

#include <vector>
#include <string>

int main()
{
    constexpr std::string cs{ "hello" };
    constexpr std::vector cv{ 1, 2, 3 };
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨“表达式必须具有常量值”:

编译器错误

我错过了什么吗?我使用的是最新的 Microsoft Visual Studio 2019 版本:16.11.4,并且参考(https://en.cppreference.com/w/cpp/compiler_support)指出constexpr此编译器版本支持字符串和向量:

在此输入图像描述

我也尝试过constexpr std::array,它确实有效。该问题是否与向量相关的动态内存分配有关?

Bar*_*rry 44

您的程序实际上格式不正确,尽管该错误可能很难理解。constexprC++20 中的分配支持是有限的 - 您只能进行临时分配。也就是说,分配必须在持续评估结束时完全解除分配。

所以你不能这样写:

int main() {
    constexpr std::vector<int> v = {1, 2, 3};
}
Run Code Online (Sandbox Code Playgroud)

因为v的分配是持续的 - 它是非暂时性的。这就是错误告诉您的内容:

<source>(6): error C2131: expression did not evaluate to a constant
<source>(6): note: (sub-)object points to memory which was heap allocated during constant evaluation
Run Code Online (Sandbox Code Playgroud)

v不能是常量,因为它仍然保留堆分配,并且不允许这样做。

但你可以这样写:

<source>(6): error C2131: expression did not evaluate to a constant
<source>(6): note: (sub-)object points to memory which was heap allocated during constant evaluation
Run Code Online (Sandbox Code Playgroud)

这里,v的分配是暂时的——返回时内存被释放f()。但我们仍然可以使用a std::vectorwhile constexpr


mar*_*inj 5

正如 @barry 所解释的,您无法创建需要动态分配且在运行时仍然可用的变量。我相信这是通过以下排除来解释的:

表达式 E 是核心常量表达式,除非对 E 的求值遵循抽象机 ([intro.execution]) 的规则,将求值以下其中一项:

https://eel.is/c++draft/expr.const#5.17

new 表达式 ([expr.new]),除非所选分配函数是可替换的全局分配函数 ([new.delete.single]、[new.delete.array]),并且分配的存储空间在E;

尽管如此,您仍然可以利用这些新功能做出令人惊奇的事情。例如连接字符串:

constexpr std::string join(std::vector<std::string> vec, char delimiter) {
  std::string result = std::accumulate(std::next(vec.begin()), vec.end(),
    vec[0],
    [&delimiter](const std::string& a, const std::string& b) {
      return a + delimiter + b;
    });
  return result;
}

static_assert(join({ "one", "two", "three" }, ';') == "one;two;three"sv);
Run Code Online (Sandbox Code Playgroud)

  • 你好!:) 看起来很酷,但我没有成功重现您的代码:https://godbolt.org/z/K7KbEWW4Y (3认同)