Mapping enums to enums
There is sometimes the need to translate one enumerate value to another. For example let's have the case of enum 'A' and 'B':
enum A
{
eA0 = 0,
eA1,
eA2,
};
enum B
{
eB0 = 0,
eB1,
eB2,
};
A simple translation without asserting on non existing values could work as follow:
B Translate(A eA)
{
B e = eB0;
switch (eA)
{
case eA0: e = eB0; break;
case eA1: e = eB1; break;
case eA2: e = eB2; break;
}
return e;
}
This is a straightforward one to one mapping. With Compiler explorer one can see that the Visual Studio 2019 compiler translates this in a bunch of compare and jump statements:
B Translate(A) PROC
test ecx, ecx
je SHORT $LN4@
Translate
sub ecx, 1
je SHORT $LN5@
Translate
cmp ecx, 1
jne SHORT $LN4@
Translate
mov eax, 2
ret 0
$LN5@
Translate
:
mov eax, 1
ret 0
$LN4@
Translate
:
xor eax, eax
ret 0
B
Translate
(A) ENDP
In this case the value are exact the same so a more optimal solution would be that it just uses the value:
B Translate2(A eA)
{
return static_cast<B>(eA);
}
In Compiler explorer it can be seen now that this is denser and faster:
B
Translate2
(EA) PROC
mov eax, ecx
ret 0
EB
Translate2
(EA) ENDP
It seems that Visual Studio doesn't recognize this optimization by itself.
More robust
Above cast can be dangerous if values do not correspond. One can trap for this and for accidental changes by adding some static_asserts
enum A
{
eAbegin = 0,
eA0 = ABegin,
eA1,
eA2,
eAend
};
B Translate2(A eA)
{
static_assert(eAbegin == eBbegin);
static_assert(eAend == eBend);
// or (verbose and requires updating after adding an enum):
static_assert(eA0 == eB0);
static_assert(eA1 == eB1);
static_assert(eA2 == eB2);
return static_cast<B>(eA);
}