为什么“ std :: Deque”不是constexpr`友好?
我正在学习 c ++ stl ,我注意到,尽管大多数功能都支持大多数功能。 std :: vector
和std :: array
(连续存储)用constexpr
标记,std ::不是这样Deque
和其他非连续储藏。 因此,我花了一些时间进行一些研究,在2019年找到了一项建议,制作std :: Deque
constexpr 和std :: Deque
仍然未实现其方法的constexpr
。
我的困惑是std ::数组
保证其元素存储在堆栈中;就像普通的C风格数组一样,应该在编译时计算出来,但是std :: vector
将内存分配在堆上,因此如果在编译时进行了评估,Deque也是吗?
谢谢!
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.
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.
My confusion is that std::array
guarantees that its elements are stored on the stack; 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?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据 https://github.com/cplus.com/cplusplus/ppapers/papers/papers/issues/665通过标准委员会流程保留提案进步的日志,似乎有一些疑问是否可以在没有核心语言更改的情况下实现
constexpr
std :: Deque
deque 。不幸的是,它没有说明什么是特定的问题。可能某些常见的实现利用了某种语言构造,这些构造在恒定表达式中不允许使用,或者实现依赖于某些根据标准的不确定行为的结构。后者通常不是标准库的问题,因为它不受语言规则的约束,并且可以对特定编译器的行为做出假设。但是,在恒定表达式中,核心语言不确定的行为始终是一个严重的错误,因此,如果不引入魔术编译器解决方法,这种结构通常在恒定的表达上下文中可能无法使用。
如链接的GitHub问题所述,似乎还有一些图书馆设施需要添加
constexpr
才能使此工作。除了这样的问题外,通常我认为没有任何理由不制作所有容器和容器适配器
constexpr
friendly,现在std :: Aralocator
都可以使用在恒定表达式中。他们可能只想确保可以首先正确实现为constexpr
。我的猜测是,出于相同的原因,只有std :: string
和std :: vector
是使用C ++ 20完成的,因为这些是最简单,最重要的分配器 - 知道将constexpr
应用于。 (std :: array
已经constexpr
更长,因为它不需要任何动态分配。)尽管查看问题中最后一个条目的日期(如以及
std :: list
,std :: Pirstition_queue
等的随附问题)似乎在过去两年中没有进展,也许是因为该提案没有进一步追求,但我真的不知道。无论哪种情况,当我们说
std :: vector
(或其他分配器 - 感知容器)是constexpr
- 友好时,这意味着与EGstd ::数组。您可以声明
constexpr std :: array
变量并按照使用const std :: array
变量,但是您无法声明constexpr std :: vector
变量(通常是完全),并像const std :: vector
一样使用它。但是,您可以做的是使用
std :: vector
在constexpr
函数中进行一些计算,只要在评估常数后创建变量表达开始并在结束之前被破坏。当前,如果不是std :: list
不是constexpr
- friendly,这是不可能的。这样做的原因是,编译器实际上不会在编译时为容器分配内存,然后以某种方式将其传输到运行时分配(无论是静态还是动态)。取而代之的是,在编译时的动态分配与运行时分配分配,并且必须在分配末端的恒定表达式评估之前对进行 。
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.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.Aside from such issues, generally, I don't think there is any reason to not make all containers and container adaptors
constexpr
-friendly now thatstd::allocator
can be used in constant expressions. They probably just want to make sure that they can be properly implemented asconstexpr
first. My guess is that for the same reason onlystd::string
andstd::vector
were done with C++20, since these are the simplest and most important allocator-aware containers to applyconstexpr
to. (std::array
has beenconstexpr
for longer since it doesn't require any dynamic allocations.)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.In either case, when we say that
std::vector
(or other allocator-aware containers) areconstexpr
-friendly, this means something else than it does for e.g.std::array
. You can declare aconstexpr std::array
variable and use it as you would use aconst std::array
variables, but you can't declare aconstexpr std::vector
variable (generally at all) and use it as you would aconst std::vector
.What you can do however is use a
std::vector
variable in e.g. aconstexpr
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. Currently this is not possible with e.g. astd::list
which is notconstexpr
-friendly.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.