4th Edit: the original question title is:
Why
constexpr
specifier is not allowed for non-emptystd::vector
?
This title, as @Barry points out, is a duplicate to C++20 constexpr vector and string not working. But there is a difference in my question description: I am allocating constexpr vector
in consteval
function instead of normal runtime function or constexpr
function.
I understand that during compile-time computing, only transient allocation is allowed, as @Barry answered in the linked question.
What I was confused about is that: for consteval
function:
- any of its local variables will be dealloacted after it returns
- it only returns in compile-time, since it will only be called in compile-time
- so
constexpr vector
, as a local variable, will be deallocated in compile-time - then why is it not allowed?
And my other edits below answered this confusion.
-----------------Below is the orignal question description----------
Why the following code does not compile:
consteval int foo() {
constexpr std::vector<int> vec{1};
return vec[0];
}
As I learned, std::vector
and std::string
can be used in compile time as long as both the allocation and deallocation happens in compile time. And if I delete the constexpr
specifier, this code will compile.
But adding constexpr
still does not violate this rule, right? Why is it not allowed?
I got this error when compiled with gcc 13 but I don't understand it:
/opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/allocator.h:195:52: error:
'std::vector<int>(std::initializer_list<int>{((const int*)(& const int [1]{1})), 1}, std::allocator<int>())' is not a constant expression because it refers to a result of 'operator new'
195 | return static_cast<_Tp*>(::operator new(__n));
|
Edit:
My question is not a duplicate to any other questions. There is only one duplicate constexpr specifier on std::vector doesn't work, but with wrong answer about why constexpr
is not allowed: it states that "compile-time std::vector
should be allocated and deallocated in compile-time, so it is not allowed", but the code above does not violate this rule.
2nd Edit: Thanks for answers from @user4581301 and @chris. I learned that I got a wrong understanding of a rule:
Wrong: it will be fine if memory allocated via
new
in compile-time isdelete
d also in compile-time.
Correct: in compile-time, memory allocated via
new
must bedelete
d in the same constant expression context.
And the answer to my question is that constexpr vector<int>
will introduce a new constant expression context while vector<int>
does not.
3rd Edit: What are the conditions that `constexpr` will start a new constant expression context?