简体   繁体   English

为什么`std::deque`对`constexpr`不友好?

[英]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::vectorstd::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::stringstd::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::liststd::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.

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