Reputation: 10859
From some C legacy code I get a number of constants as int *
. In the C++ part, I have an enum of underlying type int. Conversion between the enum and int on a single value basis works. However, conversion between int *
and enum *
is not possible. See code example below.
Why is that and how would I convert a pointer to some int values to a pointer to int enums and vice versa? I kind of expect it to work since the single value conversions work and the underlying types are the same. I read about What happens if you static_cast invalid value to enum class? but could not determine if potentially invalid values play a role here.
int i = 3;
enum E : int;
E e;
e = static_cast<E>(i); // ok
i = static_cast<int>(e); // ok
int *j;
E * f;
j = static_cast<int *>(&i); // ok
f = static_cast<E *>(&i); // 'static_cast': cannot convert from 'int *' to 'E *'
j = static_cast<int *>(&e); // 'static_cast': cannot convert from 'E *' to 'int *'
// now use j and f
*j = *f;
Upvotes: 10
Views: 4142
Reputation: 8589
The default 'base type' of an enum is int
and can be explicitly specified in the OP. Logically the value stored at E* e
where E is an enumeration with base type int
is an int
. It can't be statically cast.
There's no guarantee in C++ that an enum
of base type (say) is layout compatible with short
but even if the language tightened up that point there could be issues of type compatibility/
One issue is that E*
to int*pi
would violate type-safety because pi
could be used to quietly set values outside the enumeration.
Similarly int*
to E*
may violate type safety if the integer value isn't in the enumeration.
Note however the standard makes a clear note that there's nothing to preclude an enum taking a value outside its defined set of values:
This set of values is used to define promotion and conversion semantics for the enumeration type. It does not preclude an expression of enumeration type from having a value that falls outside this range.
See here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf (see note 95 bottom of p. 156)
The only case that could (if layout-compatibility were assured) be valid is E*
to const int*
because all values of E*
are int
s and the value cannot be (correctly) modified through the int *
pointer without a further violation of the type system.
But I think the language definition is not that subtle.
Upvotes: 2
Reputation: 17483
Why is that?
From the compiler point of view int*
and E*
are pointers of different non-related types, that is why static_cast
is not applicable here.
How would I convert a pointer to some int values to a pointer to int enums and vice versa?
You might try reinterpret_cast
instead of static_cast
:
f = reinterpret_cast<E *>(&i);
j = reinterpret_cast<int *>(&e);
From reinterpret_cast
:
Any pointer to object of type T1 can be converted to pointer to object of another type cv T2
However, note, that dereferencing f
or j
(i.e. with *f
or *j
) will be a violation of the strict aliasing rule (for more details see the discussion below). This means that this kind of conversion, though strictly possible, is usually not useful.
Upvotes: 9