I always assumed:
const_cast
ed variable is UBSo I am confused why this code compiles:
constexpr int fn(){
int v = 42;
return [v]() {
const_cast<int&>(v)+=5;
return v;
}();
}
static constexpr auto val = fn();
int main() {
return val;
}
note: I know there is no reason to not allow this to work since it is obvious what the result should be, I am more interested in the legal explanation why is this allowed.
A template metaprogram runs at compile, but a constexpr function can run at compile time or runtime. Arguments of a template metaprogram can be types, non-types such as int , or templates. There is no state at compile time and, therefore, no modification.
constexpr implies const. A constexpr variable must satisfy the following requirements: it must be immediately constructed or assigned a value. the constructor parameters or the value to be assigned must contain only literal values, constexpr variables and functions.
constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.
This part is true:
there is no UB allowed in constexpr
This part is not:
writing to
const_cast
-ed variable is UB
The actual rule is, from [dcl.type.cv]/4:
Any attempt to modify ([expr.ass], [expr.post.incr], [expr.pre.incr]) a const object ([basic.type.qualifier]) during its lifetime ([basic.life]) results in undefined behavior.
Note that the relevant part is whether the object is const
or not - not whether any of the path that you took to get to it is const
. And in this case, v
is not a const
object and nor is the one created in the lambda when you're copying it.
However, if you declare v
to be const
, then the one declared in the lambda would also be declared const
, and thus the attempt to modify it would be undefined behavior. As a result, your code will no longer compile.
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