fda*_*dan 19 c++ constexpr c++20
我正在编译时使用计算一些数据std::vector,并希望将结果作为数组返回,以便可以在运行时进一步使用。我在不进行两次计算的情况下设置数组大小时遇到问题。
这是我迄今为止所做的事情的简化示例。代码按预期编译并运行。
constexpr auto make_vector() {
// complex calculation here
return std::vector{1, 2, 3};
}
constexpr auto make_array() {
const auto vec = make_vector();
std::array<int, make_vector().size()> result{};
std::copy(vec.cbegin(), vec.cend(), result.begin());
return result;
}
int main() {
constexpr auto result = make_array(); // std::array<int, 3>{1, 2, 3}
}
Run Code Online (Sandbox Code Playgroud)
我理解为什么不能用于vec.size()数组大小以及为什么make_vector().size()会产生编译时常量。做两次似乎不是正确的方法。
有没有办法避免调用make_vector两次?我在这里错过了一个基本概念吗?
Jan*_*tke 19
有没有办法避免调用
make_vector两次?我在这里错过了一个基本概念吗?
目前,没有。根本问题是它std::vector不是文字类型,因此您不能简单地将其存储在constexpr可以任意使用其大小和内容的变量中。Astd::vector只能在常量表达式(1)期间暂时存在。
在第一个常量表达式中,.size()不是常量表达式,并且无法“将其提升到该状态”。因此,您不知道要创建的数组的大小,并且第一次会浪费向量内容(2)。
这个问题也是P0784:更多 constexpr 容器(3)中的动机:
除此之外,缺乏可变大小的 [constexpr] 容器迫使它们在实现中使用原始的固定大小的数据结构,并解析输入的 JSON 字符串两次;一次确定数据结构的大小,一次将 JSON 解析为这些结构。
您不是第一个遇到这个问题的人,您只需要有耐心,直到 C++ 委员会和编译器开发人员解决这个问题。
解决此问题的最新论文是P1974:非瞬态 constexpr 分配。关键问题是任何T*在编译时分配并存储在constexpr变量中(直接或通过容器)的内容都可以指向可变内存。这个常量问题意味着 aconstexpr std::vector<std::string>将包含可变/不可变指针的混合(类似于char ** const),这打破了我们可以delete完全省略并保留静态内存的假设。请参阅论文了解更多详细信息。
(1)原因是即使std::vector可以在常量表达式中使用new,所有的内存也必须在常量表达式结束之前被释放。这称为“临时分配”。
(2)正如评论者 @HolyBlackCat 所指出的,您的编译器可能会记住对的调用make_vector(),以便即使您调用它两次,该函数也不需要计算两次。
(3)本文已被C++20接受,但尚未解决容器创建浪费的问题。
| 归档时间: |
|
| 查看次数: |
1108 次 |
| 最近记录: |