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);
}
Coding Mash
  • 3,338
  • 5
  • 24
  • 45
FrozenHeart
  • 19,844
  • 33
  • 126
  • 242

3 Answers3

22

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.

Travis Gockel
  • 26,877
  • 14
  • 89
  • 116
4

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

Rost
  • 8,779
  • 28
  • 50
  • 2
    @Rost that is not true. The standard guarantees that an emum's underlying type is an *integral type*, but not necessarily an *int*. – Drew Dormann Sep 01 '12 at 14:38
  • @tenfour Well, it was added in C++11. Don't know the reason. Possibly to allow some template tricks? – Rost Sep 01 '12 at 14:40
  • 1
    If "there is nothing to reinterpret" had anything to do with correctness, then this would fail: `int x = 0; int* p = reinterpret_cast(&x);` – Travis Gockel Sep 01 '12 at 15:31
  • @TravisGockel Even `reinterpret_cast(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`? ;-) – Rost Sep 01 '12 at 15:43
  • 2
    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` still wouldn't be allowed. – Travis Gockel Sep 01 '12 at 15:50
  • @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? – Rost Sep 01 '12 at 21:07
  • Because it isn't allowed. The C++ standard does not define an `enum` to an integral type cast with `reinterpret_cast`. – Travis Gockel Sep 01 '12 at 21:24
  • @TravisGockel I know that is not allowed, I can read standard. The question is _why_ it is not allowed. The reason? – Rost Sep 01 '12 at 21:39
  • Probably for the same reason `reinterpret_cast(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. – Travis Gockel Sep 01 '12 at 21:50
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

alfC
  • 14,261
  • 4
  • 67
  • 118