Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is const_cast valid in a constant expression? (C++14, C++17)

The specific issue that a came across is that there is some inconsistency in how compilers handle it.

For instance this code (https://godbolt.org/z/08Z-zi):

    constexpr auto value = 1;
    static_assert(*const_cast<int *>(&value), "value should be 1");

compiles fine with GCC, Clang and MSVC but fails with Intel C++ Compiler 19.0.1 with the following error:

error: expression must have a constant value
static_assert(*const_cast<int *>(&value), "value should be 1");

As far as I can tell the standard does not explicitly state that a const_cast is not permitted in a constant expression. Writing through the resulting pointer would be undefined and therefore not permitted but reading should be OK.

Considering that all the major compilers compile this code (including ICC < 19.0.1), it could just be a regression in ICC 19.0.1.

like image 997
andrey Avatar asked Apr 01 '19 08:04

andrey


1 Answers

What may or may not appear in a constant expression in C++ is defined by a black list of expressions or properties of expressions. The full list is in the section [expr.const], paragraph 2. There is nothing in the list that prohibits the const_cast itself. The only pertinent bit, as far as I can see, is §2.7

an lvalue-to-rvalue conversion unless it is applied to

  • a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile const object with a preceding initialization, initialized with a constant expression, or

  • a non-volatile glvalue that refers to a subobject of a string literal, or

  • a non-volatile glvalue that refers to a non-volatile object defined with constexpr, or that refers to a non-mutable subobject of such an object, or

  • a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e;

An lvalue-to-rvalue conversion is standardese for (roughly) "reading an object's stored value". That is what your example does. Now, those may not appear, in general, in constant expressions. Other than when one of the preceding bullets applies.

The third bullet applied in your case. The * operator produces an lvalue. Said lvalue is not volatile, and refers to a constexpr object (value). You code is therefore valid C++.

like image 180
StoryTeller - Unslander Monica Avatar answered Nov 18 '22 14:11

StoryTeller - Unslander Monica