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 that std::allocator
can be used in constant expressions. They probably just want to make sure that they can be properly implemented as constexpr
first. 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::array
has been constexpr
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) are constexpr
-friendly, this means something else than it does for e.g. 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
.
What you can do however is use a std::vector
variable in e.g. 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. Currently this is not possible with e.g. a std::list
which is not constexpr
-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.