Note 2 to [expr.const]/2 implies that if we have a variable o
such that:
the full-expression of its initialization is a constant expression when interpreted as a constant-expression, except that if
o
is an object, that full-expression may also invoke constexpr constructors foro
and its subobjects even if those objects are of non-literal class types
then:
Within this evaluation,
std::is_constant_evaluated()
[...] returnstrue
.
Consider:
#include <type_traits>
int main() {
int x = std::is_constant_evaluated();
return x;
}
This program returns 0 when executed.
However, I don't see how the full-expression of the initialization of x
is not a constant expression. I do not see anything in [expr.const] that bans it. Therefore, my understanding of the note (which is probably wrong) implies that the program should return 1.
Now, if we look at the normative definition of std::is_constant_evaluated
, it is only true in a context that is "manifestly constant-evaluated", and the normative definition of the latter, [expr.const]/14, is more clear that the program above should return 0. Specifically, the only item that we really need to look at is the fifth one:
the initializer of a variable that is usable in constant expressions or has constant initialization ...
x
is not usable in constant expressions, and it doesn't have constant initialization because no automatic variable does.
So there are two possibilities here. The more likely one is that I haven't understood the note, and I need someone to explain to me why the note does not imply that the program should return 1. The less likely one is that the note contradicts the normative wording.
If you pass a non-constexpr argument to the PlusOne function, the compiler can't evaluate it at compile-time, and it will simply be a normal run-time function. Hint: "The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time."
A constant variable must be initialized at its declaration. To declare a constant variable in C++, the keyword const is written before the variable's data type. Constant variables can be declared for any data types, such as int , double , char , or string .
The full quote here is
A variable or temporary object
o
is constant-initialized if
- (2.1) either it has an initializer or its default-initialization results in some initialization being performed, and
- (2.2) the full-expression of its initialization is a constant expression when interpreted as a constant-expression, except that if
o
is an object, that full-expression may also invoke constexpr constructors foro
and its subobjects even if those objects are of non-literal class types. [Note 2: Such a class can have a non-trivial destructor. Within this evaluation,std::is_constant_evaluated()
([meta.const.eval]) returnstrue
. — end note]
The tricky bit here is that the term "is constant-initialized" (note: not "has constant initialization") doesn't mean anything by itself (it probably should renamed to something else). It's used in exactly three other places, two of which I'll quote below, and the last one ([dcl.constexpr]/6) isn't really relevant.
[expr.const]/4:
A constant-initialized potentially-constant variable
V
is usable in constant expressions at a pointP
ifV
's initializing declaration D is reachable from P and [...].
[basic.start.static]/2:
Constant initialization is performed if a variable or temporary object with static or thread storage duration is constant-initialized ([expr.const]).
Let's replace "constant-initialized" with something less confusing, like "green".
So
Outside of these two cases, the greenness of a variable doesn't matter. You can still compute whether it is green, but that property has no effect. It's an academic exercise.
Now go back to the definition of greenness, which says that a variable or temporary object is green if (among other things) "the full-expression of its initialization is a constant expression when interpreted as a constant-expression" with some exceptions. And the note says that during this hypothetical evaluation to determine the green-ness of the variable, is_constant_evaluated()
returns true
- which is entirely correct.
So going back to your example:
int main() {
int x = std::is_constant_evaluated();
return x;
}
Is x
green? Sure, it is. But it doesn't matter. Nothing cares about its greenness, since x
is neither static nor thread local nor potentially-constant. And the hypothetical computation done to determine whether x
is green has nothing to do with how it is actually initialized, which is governed by other things in the standard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With