0

given enum class Foo

enum class Foo : uint8_t
{
    A, B, C
};

why does this cast fail?

uint8_t X = 1;
Foo& X_ref = *static_cast<Foo*>(&X);

but reinterpret cast does not fail?

uint8_t X = 1;
Foo& X_ref = *reinterpret_cast<Foo*>(&X);

I'm wondering if this cast is safe and I can safely assign enum values of Foo to X_ref and expect X to be changed accordingly as long as type of X is same as underlying type of enum class (in this case uint8_t)

M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
  • 1
    The beauty of `reinterpret_cast` is it's the Word of God. The compiler does exactly what you tell it to do no matter how stupid. You can't really make a `reinterpret_cast` fail at the compiler. You did something else wrong if it looks like you did. Unfortunately, it's laughably easy to make the result fail at runtime. – user4581301 Jan 30 '23 at 22:41
  • Oh cool, actually i haven't tested in my program yet (I've tested with an online compiler and it worked) but I thought I would ask first before proceeding. @user4581301 – M.kazem Akhgary Jan 30 '23 at 22:44
  • 2
    Anyway you're trying to convert pointers, NOT the enum. `Foo X_ref = static_cast(X);` will convert politely. – user4581301 Jan 30 '23 at 22:44
  • 1
    `Foo& X_ref = *static_cast(&X);` if the RHS compiled (not tested) it would create an rvalue and you can't bind a non-const lvalue reference to an rvalue. – Richard Critten Jan 30 '23 at 22:46
  • But... You want a reference. when you convert you get a temporary variable, and references to temporaries are useless. The temporary is gone before you can use the reference. Yeah. What Richard just said. – user4581301 Jan 30 '23 at 22:46
  • Clang gives a really good error message explaining the above: https://godbolt.org/z/rGf361n9E – user4581301 Jan 30 '23 at 22:49
  • @user4581301 That code is unrelated to the code in the question. – 273K Jan 30 '23 at 22:51
  • @RichardCritten It does not compile. What r-value are you talking about? – 273K Jan 30 '23 at 22:51
  • @273 Yes. Deliberately simplified to prove a point. – user4581301 Jan 30 '23 at 22:52
  • but the reinterpret cast does not create a temporary right? how about this one?`reinterpret_cast(X);` @user4581301 – M.kazem Akhgary Jan 30 '23 at 22:53
  • Can't say I've ever tried to cast something to a reference. I'd have to do some diving to see what that one does. – user4581301 Jan 30 '23 at 22:55
  • think long and hard before using enums at all - usually a sign of basically very weak typing - whenever i think of writing an enum in my code, i think "whoa, design error" – Neil Butterworth Jan 30 '23 at 22:56
  • Pretty much the whole point of `enum class` is it makes it hard to play games like this and spits out errors when you do it. You use `enum class` when you **don't** want people converting from integers. – user4581301 Jan 30 '23 at 22:58
  • 1
    Poked around at `reinterpret_cast(X);`. The `reinterpret_cast` means look at the variable as if it was a different type. It's not going to give you a temporary, so you're safe on that count. And since the underlying type of `Foo` is `uint8_t` I don't think you're violating strict aliasing. If there is undefined behaviour lurking in there, it looks like it's the type that'll consistently manifest the way you expect on regular platforms. – user4581301 Jan 30 '23 at 23:23

0 Answers0