th**********@gmail.com wrote:
Hey all.
I have bit shifted my enum values all the way to 31 items. I feel that
this api that i am using continues to grow, i will be stuck with out
any more items in my enum.
I would like to promote the enum to a long if possible so that it will
be 64 bits long. Thanks.
I try to move totally away from enums and switch statements unless there
is a very select small number of them and even then I usually stick
enums into a class equivalent thing.
Firstly, the use of switch statements inevitably becomes way too complex
as you add new enums. So I use a static const reference to a class
instance that provides all the services for that "enum". This may take
a little more code and maybe less but I never have problems when I mix
bit masks of different things or have to go scrummaging through complex
code looking for switch statements just to make them more complex.
If I need to make collections of them I put them in a std::set or
similar container. I can also teach this container about valid sets of
things that can be added, sometimes even statically so the errors show
up at compile time rather than run time.
So code like this below is what I'm talking about. I've done a bit more
using templates in other code where the template type itself performs
compile time checks for invalid combinations. The compile time check
only works for simple combinations and dynamic combinations can only be
checked at run time.
BTW, as an observation, this is not unlike the "typeid" standard
implementation.
#include <set>
// the basic class than embodies the thing you're doing.
class Things
{
friend class Thing_Impl;
private:
Things();
Things( const Things & );
Things & operator=( const Things & );
public:
bool operator<( const Things & i_rhs ) const
{
return this < & i_rhs;
}
// some thing methods
virtual const char * Name() = 0;
// put more methods here instead of
// switch statements littered through the code
// nominate all the different things that you need
static const Things & Thing1;
static const Things & Thing2;
static const Things & Thing3;
};
// Then I might implement an operator| like so.
// first I need somthing for my std::set to hold
// a reference to a Things object reference.
class ThingsRef
{
public:
ThingsRef(
const Things & i_foo
)
: m_fooref( i_foo )
{
}
bool operator<( const ThingsRef & i_rhs ) const
{
return this->m_fooref < i_rhs.m_fooref;
}
const Things & m_fooref;
};
// my set of things type
class ThingSet
{
std::set<ThingsRef l_set;
public:
ThingSet(
const Things & i_thing
) {
l_set.insert( i_thing );
}
ThingSet(
const Things & i_lhs,
const Things & i_rhs
) {
l_set.insert( i_lhs );
l_set.insert( i_rhs );
}
ThingSet(
const ThingSet & i_lhs,
const Things & i_rhs
)
: l_set( i_lhs.l_set )
{
l_set.insert( i_rhs );
}
ThingSet(
const Things & i_lhs,
const ThingSet & i_rhs
)
: l_set( i_rhs.l_set )
{
l_set.insert( i_lhs );
}
ThingSet(
const ThingSet & i_lhs,
const ThingSet & i_rhs
)
: l_set( i_lhs.l_set )
{
l_set.insert( i_rhs.l_set.begin(), i_rhs.l_set.end() );
}
};
ThingSet operator|( const Things & i_lhs, const Things & i_rhs )
{
return ThingSet( i_lhs, i_rhs );
}
ThingSet operator|( const ThingSet & i_lhs, const Things & i_rhs )
{
return ThingSet( i_lhs, i_rhs );
}
ThingSet operator|( const Things & i_lhs, const ThingSet & i_rhs )
{
return ThingSet( i_lhs, i_rhs );
}
ThingSet operator|( const ThingSet & i_lhs, const ThingSet & i_rhs )
{
return ThingSet( i_lhs, i_rhs );
}
int main()
{
// Create a thingset from a single thing
ThingSet l_test1( Things::Thing1 );
ThingSet l_test2(
Things::Thing1 | Things::Thing2 | Things::Thing3
);
ThingSet l_test3( Things::Thing1 | l_test1);
ThingSet l_test4( l_test2 | l_test1 );
}
// in a totally separate file hidden from the rest of the world
//
//
Things::Things()
{
}
class Thing_Impl
: public Things
{
const char * name;
public:
Thing_Impl( const char * name )
: name( name )
{
}
const char * Name()
{
return name;
}
};
// implement all the different "Things"
//
const Thing_Impl Thing_Impl1( "Thingy 1" );
const Things & Things::Thing1 = Thing_Impl1;
const Thing_Impl Thing_Impl2( "Thingy 1" );
const Things & Things::Thing2 = Thing_Impl2;
const Thing_Impl Thing_Impl3( "Thingy 1" );
const Things & Things::Thing3 = Thing_Impl3;