繁体   English   中英

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

[英]C++20 constexpr vector and string not working

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

#include <vector>
#include <string>

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

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

编译器错误

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

在此处输入图像描述

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

您的程序实际上格式不正确,尽管错误可能难以理解。 C++20 中的constexpr分配支持是有限的——你只能有瞬态分配。 也就是说,分配必须在持续评估结束时完全解除分配。

所以你不能这样写:

int main() {
    constexpr std::vector<int> v = {1, 2, 3};
}

因为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

v不能保持不变,因为它仍在保持堆分配,并且不允许这样做。

但是你可以这样写:

constexpr int f() {
    std::vector<int> v = {1, 2, 3};
    return v.size();
}

static_assert(f() == 3);

在这里, v的分配是暂时的 - 当f()返回时 memory 被释放。 但是我们仍然可以在constexpr时间内使用std::vector

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

表达式 E 是核心常量表达式,除非 E 的评估遵循抽象机 ([intro.execution]) 的规则,将评估以下之一:

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

新表达式 ([expr.new]),除非选定的分配 function 是可替换的全局分配 function ([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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM