[英]Why is `std::deque` not `constexpr` friendly?
I'm learning the c++ STL and it came to my attention that while most functionalities supported by std::vector
and std::array
(contiguous storage) are marked with constexpr
, that's not the case for std::deque
and other non-contiguous storages.我正在学习c++ STL ,我注意到虽然std::vector
和std::array
(连续存储)支持的大多数功能都标有constexpr
,但std::deque
和其他非连续存储。 So I spent some time doing some research, I found a proposal in 2019, Making std::deque
constexpr , and std::deque
still has not implemented constexpr
for its methods.所以我花了一些时间做了一些研究,我在 2019 年发现了一个提案, Making std::deque
constexpr ,而std::deque
仍然没有为其方法实现constexpr
。
My confusion is that std::array
guarantees that its elements are stored on the stack;我的困惑是std::array
保证其元素存储在堆栈中; just like a normal C-style array, so it should be computed at compile time, but std::vector
allocates memory on the heap so if it's evaluated at compile time, so is deque, right?就像一个普通的 C 风格的数组,所以它应该在编译时计算,但是std::vector
在堆上分配内存,所以如果它是在编译时计算的,那么双端队列也是如此,对吗?
Thanks!谢谢!
According to https://github.com/cplusplus/papers/issues/665 which keeps a log of the progression of the proposal through the standards committee process, there seem to have been some doubts whether a constexpr
std::deque
can be implemented without core language changes.根据https://github.com/cplusplus/papers/issues/665通过标准委员会流程记录提案的进展情况,似乎有人怀疑是否可以实施constexpr
std::deque
无需更改核心语言。
Unfortunately it doesn't say what the specific concern is.不幸的是,它没有说明具体问题是什么。 Probably some common implementation makes use of some language construct that specifically is not allowed in constant expressions or the implementation relies on some construct that is undefined behavior according to the standard.可能一些常见的实现使用了一些在常量表达式中明确不允许的语言构造,或者实现依赖于一些根据标准未定义的行为的构造。 The latter is usually not a problem for the standard library, since it is not bound by the language rules and can make assumptions about the particular compiler's behavior.后者对于标准库来说通常不是问题,因为它不受语言规则的约束并且可以对特定编译器的行为做出假设。 However in constant expressions core language undefined behavior is always a hard error and therefore such constructs might often not be usable in constant expression contexts without introducing magic compiler workarounds.然而,在常量表达式中,核心语言未定义的行为总是一个硬错误,因此如果不引入神奇的编译器变通方法,这样的构造可能通常无法在常量表达式上下文中使用。
As mentioned in the linked github issue, there seem to also be some library facilities which need to have constexpr
added to make this work as well.如链接的 github 问题中所述,似乎还有一些库设施需要添加constexpr
才能使其正常工作。
Aside from such issues, generally, I don't think there is any reason to not make all containers and container adaptors constexpr
-friendly now that std::allocator
can be used in constant expressions.除了这些问题,一般来说,我认为没有任何理由不让所有容器和容器适配器对constexpr
友好,因为std::allocator
可以在常量表达式中使用。 They probably just want to make sure that they can be properly implemented as constexpr
first.他们可能只是想确保它们可以首先正确地实现为constexpr
。 My guess is that for the same reason only std::string
and std::vector
were done with C++20, since these are the simplest and most important allocator-aware containers to apply constexpr
to.我的猜测是,出于同样的原因,只有std::string
和std::vector
是用 C++20 完成的,因为它们是应用constexpr
的最简单和最重要的分配器感知容器。 ( std::array
has been constexpr
for longer since it doesn't require any dynamic allocations.) ( std::array
已经constexpr
的时间更长了,因为它不需要任何动态分配。)
Although, looking at the date of the last entry in the issue (as well as the accompanying issues for std::list
, std::priority_queue
, etc.) it seems to not have progressed in the last two years, maybe because the author of the proposal did not pursue it further, but I can't really tell.虽然,查看问题中最后一个条目的日期(以及std::list
、 std::priority_queue
等的随附问题),它似乎在过去两年中没有进展,可能是因为作者的建议没有进一步追究,但我真的不能说。
In either case, when we say that std::vector
(or other allocator-aware containers) are constexpr
-friendly, this means something else than it does for eg std::array
.在任何一种情况下,当我们说std::vector
(或其他分配器感知容器)是constexpr
友好的时,这意味着它与例如std::array
不同。 You can declare a constexpr std::array
variable and use it as you would use a const std::array
variables, but you can't declare a constexpr std::vector
variable (generally at all) and use it as you would a const std::vector
.您可以声明一个constexpr std::array
变量并像使用const std::array
变量一样使用它,但是您不能声明一个constexpr std::vector
变量(通常根本没有)并像使用它一样使用它const std::vector
。
What you can do however is use a std::vector
variable in eg a constexpr
function to do some calculations, as long as the variable is created after the evaluation of the constant expression starts and is destroyed before it ends.但是,您可以做的是在例如constexpr
函数中使用std::vector
变量来进行一些计算,只要该变量是在常量表达式的评估开始之后创建并在它结束之前被销毁的。 Currently this is not possible with eg a std::list
which is not constexpr
-friendly.目前这是不可能的,例如std::list
不是constexpr
友好的。
The reason for this is that the compiler will not actually allocate memory at compile-time for the container and then transfer it in some way into a runtime allocation (whether static or dynamic).原因是编译器实际上不会在编译时为容器分配内存,然后以某种方式将其转移到运行时分配中(无论是静态的还是动态的)。 Instead dynamic allocations at compile-time are separate from runtime ones and must be deallocated before the constant expression evaluation in which they were allocated ends.相反,编译时的动态分配与运行时的分配是分开的,并且必须在分配它们的常量表达式评估结束之前解除分配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.