Getting around the reinterpret cast limitation with constexpr
c++, c++11, constexpr, reinterpret-cast
Solution
I can't see how a reinterpret cast in this or similar cases can be any different from arithmetic operators
It isn't portable.
You are probably aware of the fact that your code causes undefined behavior, since you dereference a type punned pointer and thus break strict aliasing. Moreover, since C++14, operations that would invoke undefined behavior aren't even constant expressions anymore and should thus produce a compiler error.
What you are basically trying to do is alias the `float` object with an integral glvalue. The first step is to obtain that glvalue; the second to perform an lvalue-to-rvalue conversion.
In C++14, the first step is impossible to accomplish in constant expressions. `reinterpret_cast` is explicitly forbidden. And casts to and from `void*`, like `static_cast<char const*>(static_cast<void const*>(&x))`, don't work either (N3797, [expr.const]/2*):
— a conversion from type cv `void *` to a pointer-to-object type;
Keep in mind that a c-style cast like `(char*)` is reduced to either `static_cast` or `reinterpret_cast` whose limitations are listed above. `(unsigned*)&x` therefore reduces to `reinterpret_cast<unsigned*>(&x)` and doesn't work.
In C++11, the cast to `void const*` and then to `char const*` does not constitute a problem (according to standard; Clang still complains about the latter). The lvalue-to-rvalue conversion is one nonetheless:
an lvalue-to-rvalue conversion (4.1) unless it is applied to — a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression, or — a glvalue of literal type that refers to a non-volatile object defined with `constexpr`, or that refers to a sub-object of such an object, or — a glvalue of literal type that refers to a non-volatile temporary object whose lifetime has not ended, initialized with a constant expression;
The first two bullets can't apply here; Neither has any `char`/`unsigned`/etc. object been initialized precedingly, nor did we define any such object with `constexpr`.
The third bullet doesn't apply either. If we write
char ch = *(char const*)(void const*)&x;
we don't create a `char` object in the initializer. We access the stored value of `x` through a glvalue of type `char`, and use that value to initialize `ch`.
Therefore I'd say that such aliasing isn't possible in constant expressions. You may get around this in some implementations with relaxed rules.
* The paragraph is a list that starts with something like
A conditional-expression is a core constant expression unless [...]
(The text differs from N3337 to N3797.)
Problem
In c++11, a `constexpr` expression cannot contain reinterpret casts. So for instance, if one wanted to manipulate the bits in a floating point number, say to find the mantissa of the number: ``` constexpr unsigned int mantissa(float x) { return ((*(unsigned int*)&x << 9) >> 9); }; ``` The above code would fail to be `constexpr`. In theory, I can't see how a reinterpret cast in this or similar cases can be any different from arithmetic operators, but the complier (and the standard) don't allow it. Is there any clever way of getting around this limitation?