NoDataDumpNoContribution
NoDataDumpNoContribution

Reputation: 10859

How to convert between int * and enum *?

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

Answers (2)

Persixty
Persixty

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 ints 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

Edgar Rokjān
Edgar Rokjān

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

Related Questions