Atilla Filiz
Atilla Filiz

Reputation: 2432

What is the simplest way to map a combination of flags into an enumeration?

I have been given an enum type that looks more or less like this

enum foo{
X,
XandY,
XandZ,
XandYandZ,
none,
Y,
Z,
YandZ,
someSpecialCase,
anotherSpecialCase
};

I have several message objects that pass through a pipeline, and a particular stage decides if this message has X or not, another one decides if it has Y or not etc. Ultimately the message needs to be labeled with one of these labels. I design the message object but the enum is already defined. I don't want to assume any numerical values given to the enumerations. So I put boolean flags like hasX, hasY which can be individually set during different stages. Is there a better way than just writing a couple of layers of nested if-else clauses?

Edited for clarity
Edited again, changed the variable names.

Upvotes: 0

Views: 256

Answers (1)

Component 10
Component 10

Reputation: 10507

If I've understood the problem correctly then essentially what you are talking about is a multiplexer. i.e. combining several streams of information into one. This can be easily achieved using a look up table and the implementation of this is up to you.

You could combine the various input streams into a key object. I've included some code below but don't have time to check / run it so please treat it as pseudocode rather than verbatim.

Using a map

struct MyKey
{
    MyKey( bool X, bool Y, bool Z, bool SC1, bool SC2 ) :
        X_(X), Y_(Y), Z_(Z), SC1_(SC1), SC2_(SC2) {}

    bool X_;
    bool Y_;
    bool Z_;
    bool SC1_;
    bool SC2_;
};

You'll also need a operator<() function in order to use this in an associative container. Then you set up a mapping collection such as a map:

typedef enum foo FooEnum;
std::map< MyKey, FooEnum > myMap;

This map needs to be set up when your application starts and be loaded up similar to below:

myMap.insert( std::make_pair< MyKey, FooEnum >( MyKey(true,false,true,false,false), XandZ ) );

This maps X and Z only being true to XandZ so you need this for every permutation.

Once you come to do the check all you then need would be:

std::map< MyKey, FooEnum >::const_iterator it = myMap.find( MyKey(X,Y,Z,SC1,SC2) );
if ( it != myMap.end() )
{
    enum foo valueINeed = it.second;
    // ...

Using a vector / array

There are some variations on this. For example you could combine values of your input streams as bits in a mask (5 bits here) and use an array or vector of 32 elements to map each permutation to a separate element.

If you do that you could even create the collection at compile time. It will probably also run a bit faster though you'd have to test it. The drawback would be that the code is perhaps a little more esoteric but then again there's no law against documentation!

Upvotes: 2

Related Questions