I asked a question in Why `constexpr` specifier is not allowed for non-empty `std::vector`? previously, after finding the answer, I have another question here.
I tested and found that it is valid to dynamically allocate memory in one constexpr
function and free it in another constexpr
function (via new
and delete
), so a constexpr
subroutines does not introduce a new context:
constexpr int* bar() {
return new int{2};
}
constexpr int foo() {
auto ptr = bar();
int val = *ptr;
delete ptr;
return val;
}
constexpr int i = foo(); // OK
Then I get another question, what are the conditions such that constexpr
will start a new context?
In a constant expression context (like in a consteval
function), why constexpr std::vector<int>
will start a new constant expression context (which make it invalid to declare because the memory allocated through new
will escape this context) while std::vector<int>
does not allocate memory in a new constant expression context?
I am a new learner about constexpr
and C++20, please point out if I get wrong assumptions or ask a wrong problem.
what are the conditions such that constexpr will start a new context?
Being a constant expression.
The initializer for a constexpr
or constinit
variable is a constant expression. The initializer for a template parameter is a constant expression. The expression in an if constexpr
is a constant expression. These expressions begin constant expression contexts.
Calling a constexpr
function is not a constant expression. Calling a constexpr
function while evaluating a constant expression happens within a constant expression context, but it is not a context by itself.
Calling a consteval
function is not itself a constant expression context, but you're not allowed to call one unless you're already within a constant expression context.