首页 > 解决方案 > C++20 P0784R7 与 P1004R2 constexpr std::vector 相比,非瞬态分配太脆弱

问题描述

我想constexpr在 C++20 中创建一个广泛的数据存储库。数以万计的本机 C++ 对象作为“文本段”加载,即需求分页到进程中并在实例之间共享(生成代码)。

这些对象相互引用,需要通过各种属性、交叉引用等进行索引,所有这些都希望在编译时完成。这需要constexpr(关联)容器,但不能使用模板化(按大小、哈希大小等)容器来完成,因为一切都需要保持多态性。

首先这似乎是不可能的,因为 C++20 P0784R7说非瞬态分配太脆弱,即不允许动态分配的内存从constexpr评估中泄漏出来。

同时 C++20 P1004R2表示constexpr std::vector要支持。在后一篇论文中,我看到了所有成员,包括标记为 的修改成员constexpr。所以除非我遗漏了一些东西,否则我可以在std::vectors内部constexpr评估中添加元素(编译器还不支持它,所以我不能尝试)。

// 21.3.11.5, modifiers
template<class... Args> constexpr reference emplace_back(Args&&... args);
constexpr void push_back(const T& x);
constexpr void push_back(T&& x);
...

但是为什么我不能allocator<T>围绕 a构建一个std::vector<T>并且仍然有非瞬态分配呢?这两种能力不是“计算等效”,即constexpr std::vector 需要实现非瞬态分配,因此它也可以提供吗?

编译器何时会最终支持它?……或者这种疑似矛盾甚至是延迟的原因?

标签: c++stdvectorconstexprc++20

解决方案


您对瞬态分配有误解。瞬态分配是完全存在于持续评估中的分配。例如:

constexpr std::size_t summation(std::vector<unsigned int> const &vi)
{
  std::size_t ret = 0;
  for(auto i : vi)
    ret += i;
  return ret;
}

constexpr auto sum = summation({20, 44, 98});

在 的调用中summation,最终输入源(braced-init-list 及其值)在编译时是完全已知的。是的,有一个vector,但这完全存在于常量表达式求值中。该vector对象用于计算常量值,但它vector本身永远不会留下常量表达式代码。

这种完全存在于不断评估中的分配称为“瞬态分配”。根据 C++20 的规则,此类分配是允许的。

非瞬态分配将数据“加载为'文本段'”,这是不允许的。所以你的第一印象是正确的。


推荐阅读