reinterpret_cast error for enum
Asked Answered
I

4

13

Why i can't use reinterpret_cast operator for such a cast?

enum Foo { bar, baz };

void foo(Foo)
{
}

int main()
{
   // foo(0); // error: invalid conversion from 'int' to 'Foo'
   // foo(reinterpret_cast<Foo>(0)); // error: invalid cast from type 'int' to type 'Foo'
   foo(static_cast<Foo>(0)); 
   foo((Foo)0);
}
Ingather answered 1/9, 2012 at 14:26 Comment(4)
static_cast is the correct operation here.Graff
Why would it be valid? What do you think reinterpret_cast is for?Norton
I think that reinterpret_cast can be use for all types of casts, because it's force any type casts to another type with all side-effects of this conversion.Ingather
Here's a good explanation: https://mcmap.net/q/64043/-when-to-use-reinterpret_castDarcee
G
24

I think that reinterpret_cast can be use for all types of casts, because it's force any type casts to another type with all side-effects of this conversion.

That is a common misconception. Conversions which can be performed with reinterpret_cast are listed explicitly in 5.2.10 of the standard. int-to-enum and enum-to-int conversions are not in the list:

  • Pointer to integral type, so long as the integer is large enough to hold it
  • nullptr_t to integer
  • integral type or enum to pointer
  • function pointer to another function pointer of different type
  • object pointer to another object pointer of different type
  • nullptr_t to other pointer type
  • pointer-to-member of T1 to a different pointer-to-member of T2 in cases where both T1 and T2 are objects or functions

reinterpret_cast is typically used to tell the compiler: Hey, I know you think this region of memory is a T, but I'd like you to interpret it as a U (where T and U are unrelated types).

It is also worth noting that reinterpret_cast can have effects on the bits:

5.2.10.3

[ Note: The mapping performed by reinterpret_cast might, or might not, produce a representation dif- ferent from the original value. — end note ]

The C-style cast always works, because it included static_cast in its attempts.

Graff answered 1/9, 2012 at 14:34 Comment(0)
S
4

Because regular enum underlying type is int, there is nothing to reinterpret. Static cast is proper conversion for this case.

Simpson answered 1/9, 2012 at 14:33 Comment(9)
@Simpson that is not true. The standard guarantees that an emum's underlying type is an integral type, but not necessarily an int.Avouch
@tenfour Well, it was added in C++11. Don't know the reason. Possibly to allow some template tricks?Simpson
If "there is nothing to reinterpret" had anything to do with correctness, then this would fail: int x = 0; int* p = reinterpret_cast<int*>(&x);Graff
@TravisGockel Even reinterpret_cast<int>(x) is allowed. So what? It just means that reinterpret_cast don't actually reinterpret in some cases. So, shall we name it maybe_reinterpret_cast? ;-)Simpson
The reason enum-to-int can't be done through reinterpret_cast has nothing to do with the underlying type of the enum. If it was enum Foo : uint64_t { bar, baz }, reinterpret_cast<int> still wouldn't be allowed.Graff
@TravisGockel Still didn't get your logic. OK, we could not reinterpret_cast Foo to int due to different size. But why we could not reinterpret_cast it to uint64_t or any integral of sufficient size?Simpson
Because it isn't allowed. The C++ standard does not define an enum to an integral type cast with reinterpret_cast.Graff
@TravisGockel I know that is not allowed, I can read standard. The question is why it is not allowed. The reason?Simpson
Probably for the same reason reinterpret_cast<long>(int(9)); isn't allowed -- it wouldn't add anything useful to the language because those types of casts are what static_cast is for.Graff
P
0

Other answers fail to get to the point directly. Despite being a bad use of reinterpret_cast, compilation fails because you can't apply reinterpret_cast on values directly. You can apply it only to convert pointers of reference expressions. (in particular, it can't convert literal constants.)

So this compiles,

enum Foo { bar, baz };

void foo(Foo)
{
}

int main()
{
   // foo(0);
   int zero = 0;
   foo(reinterpret_cast<Foo&>(zero)); // error: invalid cast from type 'int' to type 'Foo'
   foo(static_cast<Foo>(0)); 
   foo((Foo)0);
}

https://godbolt.org/z/x6MP1e5eo

Precinct answered 31/5, 2023 at 7:58 Comment(0)
C
0

reinterpret_cast is used only for pointers, to be able to convert between the address and an integral type, or between two otherwise incompatible pointer types.

However, if you absolutely wish to use reinterpret_cast for enums, you can! You can do reinterpret_cast<Foo&>(value) or, in this case reinterpret_cast<const Foo&>(static_cast<const std::underlying_type_t<Foo>&>(0)). This is a well-defined operation, resulting in *reinterpret_cast<Foo*>(&value). This works because std::underlying_type_t<Foo> is either signed or unsigned type corresponding to Foo and thus accessible through the pointer.

Causeway answered 25/6 at 18:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.