An enumeration is a distinct type (3.9.2) with named constants. [...] Each enumeration defines a type that is different from all other types. [...] Two enumeration types are layout-compatible if they have the same underlying type.
[dcl.enum] (§7.2)
The underlying type specifies the layout of the enum in memory, not its relation to other types in the type system (as the standard says, it's a distinct type, a type of its own). A pointer to an enum : int {}
can never implicitly convert to an int*
, the same way that a pointer to a struct { int i; };
cannot, even though they all look the same in memory.
So why does the implicit conversion to int
work in the first place?
For an enumeration whose underlying type is fixed, the values of the
enumeration are the values of the underlying type. [...] The value of
an enumerator or an object of an unscoped enumeration type is
converted to an integer by integral promotion (4.5).
[dcl.enum] (§7.2)
So we can assign values of an enum to an int
because they are of type int
. An object of enum type can be assigned to an int
because of the rules of integer promotion. By the way, the standard here specifically points out that this is only true for C-style (unscoped) enums. This means that you still need the static_cast<int>
in the first line of your example, but as soon as you turn the enum class : int
into an enum : int
it will work without the explicit cast. Still no luck with the pointer type though.
Integral promotions are defined in the standard at [conv.prom] (§4.5). I'll spare you the details of quoting the full section, but the important detail here is that all rules in there apply to prvalues of non-pointer types, so none of this applies to our little problem.
The final piece of the puzzle can be found in [expr.static.cast] (§5.2.9), which describes how static_cast
works.
A value of a scoped enumeration type (7.2) can be explicitly converted
to an integral type.
That explains why your cast from enum class
to int
works.
But note that all of the static_cast
s allowed on pointer types (again, I won't quote the rather lengthy section) require some relationship between the types. If you remember the beginning of the answer, each enum is a distinct type, so there is no relationship to their underlying type or other enums of the same underlying type.
This ties in with @MarkB's answer: Static-casting a pointer enum
to a pointer to int
is analogous to casting a pointer from one integral type to another - even if both have the same memory layout underneath and values of one will implicitly convert to the other by the rules integral promotions, they are still unrelated types, so static_cast
will not work here.