switch is not optimized for mapping between enums

M

MariuszC

Hello,
I have used some library where is defined enum like:

typedef enum Enum1 { ENUM1_1, ENUM1_2, ENUM1_3, ENUM1_4, ENUM1_5 };

In my code I have defined:

typedef enum Enum2 { ENUM2_1, ENUM2_2, ENUM2_3, ENUM2_4, ENUM2_5 };

My map function looks like:

Enum2 mapEnum1toEnum2( Enum1 enum )
{
switch( enum )
{
case ENUM1_1: return ENUM2_1;
case ENUM1_2: return ENUM2_2;
case ENUM1_3: return ENUM2_3;
case ENUM1_4: return ENUM2_4;
case ENUM1_5: return ENUM2_5;
default: throw "UNKNOWN ENUM1!!!";
}
}

I have analised asm code generated by compiler, and the results is not
optimal as it can be. Because the enums can map 1:1 I have expected that
compiler creates code similar to:

Enum2 mapEnum1toEnum2( Enum1 enum )
{
if ( enum < ENUM1_1 || enum > ENUM1_5 )
throw "UNKNOWN ENUM1!!!";
return reinterpret_cast<Enum2>( enum );
}

In example above both enums are continuous, but in case if one of enums
is not continuous there is another possibility - create hash table e.g.
typedef enum Enum2 { ENUM2_1 = -1, ENUM2_2 = 33, ENUM2_3 = 55, ENUM2_4 =
1234, ENUM2_5 = 5533 };

Enum2 mapEnum1toEnum2( Enum1 enum )
{
static const Enum2 hash[] = { ENUM2_1, ENUM2_2, ENUM2_3, ENUM2_4,
ENUM2_5 };
if ( enum < ENUM1_1 || enum > ENUM1_5 )
throw "UNKNOWN ENUM1!!!";
return hash[enum];
}


Do you know any implementation to create mapEnum1toEnum2 function which
is better optimized than switch construction. Maybe there is possible
to use metaprogramming for this issue.

Best Regards
MariuszC
 
I

Ian Collins

MariuszC wrote:

You don't have to ask twice.
Hello,
I have used some library where is defined enum like:

typedef enum Enum1 { ENUM1_1, ENUM1_2, ENUM1_3, ENUM1_4, ENUM1_5 };

In my code I have defined:

typedef enum Enum2 { ENUM2_1, ENUM2_2, ENUM2_3, ENUM2_4, ENUM2_5 };

My map function looks like:

Enum2 mapEnum1toEnum2( Enum1 enum )
{
switch( enum )
{
case ENUM1_1: return ENUM2_1;
case ENUM1_2: return ENUM2_2;
case ENUM1_3: return ENUM2_3;
case ENUM1_4: return ENUM2_4;
case ENUM1_5: return ENUM2_5;
default: throw "UNKNOWN ENUM1!!!";
}
}

I have analised asm code generated by compiler, and the results is not
optimal as it can be. Because the enums can map 1:1 I have expected that
compiler creates code similar to:
Is this a problem to your application?

If the list is quite long and a switch is inefficient, you could try a
std::map<Enum1,Enum2>.

The only way to tell which is better is to profile your application.
 
G

Gianni Mariani

Ian said:
MariuszC wrote: ....
Is this a problem to your application?

If the list is quite long and a switch is inefficient, you could try a
std::map<Enum1,Enum2>.

The only way to tell which is better is to profile your application.


std::map is way more expensive than a switch.

Perhaps you could do something like this.


enum OldEnum
{
OA=1,
OB,
OC
};

enum {
g_smallest_old = OA,
g_largest_old = OC
};

enum NewEnum
{
NA=10,
NB,
NC,
BAD=-1
};


template <int w_enum>
struct OldEnumMap
{
static const NewEnum m_value = BAD;
};


template <NewEnum w_enum>
struct NewEnumMap
{
static const NewEnum m_value = w_enum;
};

// define the mapping between old and new enums
template <> struct OldEnumMap<OA> : NewEnumMap<NA> {};
template <> struct OldEnumMap<OB> : NewEnumMap<NB> {};
template <> struct OldEnumMap<OC> : NewEnumMap<NC> {};

NewEnum enummap[] = {
OldEnumMap<0>::m_value,
OldEnumMap<1>::m_value,
OldEnumMap<2>::m_value,
OldEnumMap<3>::m_value,
OldEnumMap<4>::m_value,
// ... fill in to your heart's content
};

NewEnum Convert( OldEnum i_val )
{
if ( i_val < int(g_smallest_old) )
{
return BAD;
}

if ( i_val > int(g_largest_old) )
{
return BAD;
}

return enummap[ i_val ];
}



#include <iostream>
int main()
{
// dynamic conversion
std::cout << Convert(OB) << "\n";

// static (compile time) conversion
std::cout << OldEnumMap<OB>::m_value << "\n";

}
 
M

MariuszC

Ian said:
MariuszC wrote:

You don't have to ask twice.

In first version I made mistake in condition, there was && instead of
||. I was deleting first post before sending second corrected one.

Mariusz
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top