Using the OR | w/ an enum

T

Travis

So I have been doing C++ for quite awhile but have never had too many
occasions to use |.

What I'm trying to provide is ability to say enum myEnum = myEnum::eek:ne
| myEnum::two.

I'm not sure if this makes sense so I'll use my actual situation as an
example.

I am doing a menu system where each button the screen has an access
role as does the user. So the simplest example would be.

User is Susie;

Button 1 should be available to Susie or Johnny.

So Button1.Access = myEnum::Susie | myEnum::Johnny.

Is that the best way to do it? Is it even possible? Thanks for the
help.
 
T

Travis

So I have been doing C++ for quite awhile but have never had too many
occasions to use |.

What I'm trying to provide is ability to say enum myEnum = myEnum::eek:ne
| myEnum::two.

I'm not sure if this makes sense so I'll use my actual situation as an
example.

I am doing a menu system where each button the screen has an access
role as does the user. So the simplest example would be.

User is Susie;

Button 1 should be available to Susie or Johnny.

So Button1.Access = myEnum::Susie | myEnum::Johnny.

Is that the best way to do it? Is it even possible? Thanks for the
help.


Oh I forgot to add that I got this idea that using | might work
because I didn't want to have to go through and do all the different
combinations like myEnum::Susie, myEnum::Johnny,
myEnum::JohnnyANDSusie, etc.
 
V

Victor Bazarov

In most cases you cannot do that (nor do you really want to). If you
think that the inclusive-or combination of those two values should
also be a valid value in your 'myEnum', add it there *explicitly* in
the definition of the 'myEnum' enumeration.
Oh I forgot to add that I got this idea that using | might work
because I didn't want to have to go through and do all the different
combinations like myEnum::Susie, myEnum::Johnny,
myEnum::JohnnyANDSusie, etc.

It would work if you don't try to make 'Button1.Access' of the type
'myEnum'. It should be of type 'int' or 'unsigned' (or some such)
and when you need to check if 'Johnny' has access you would also do
the 'and' operation:

myEnum john_smith = Johnny; //
...
if (john_smith & Button1.Access) // Does 'john_smith' have access?
...

V
 
J

Jim Langston

Travis said:
So I have been doing C++ for quite awhile but have never had too many
occasions to use |.

What I'm trying to provide is ability to say enum myEnum = myEnum::eek:ne
| myEnum::two.

I'm not sure if this makes sense so I'll use my actual situation as an
example.

I am doing a menu system where each button the screen has an access
role as does the user. So the simplest example would be.

User is Susie;

Button 1 should be available to Susie or Johnny.

So Button1.Access = myEnum::Susie | myEnum::Johnny.

Is that the best way to do it? Is it even possible? Thanks for the
help.

The problem is, | is bitwise. It looks at the bits, not the values.
Meaning it would work best with the values 1 2 4 8 16 32 64 128, etc...
powers of 2 which is each bit. However, enums generally start at 0 and
increment 1 unless you override them. 0 1 2 3 4 etc... You would also be
limiting the distinct users to the number of bits in your value. Also, are
you really wanting to hard code your users into the code? when Susie leaves
and Debbie takes her place, are you going to change your code to reflect
that?

Now, the way I've handled this type of things in the past is with simple
access levels. Give each user an access level, I generally used a number
from 0 to 100. 100 was full access. 10 was minimal access, etc... In my
documentation it would be like:
10 User can view insensitive data
20 User can add new insensitive data
30 User can view sensitive data
40 User can add new sensitive data
50 User can delete insensitive data
60 User can delete sensitive data
80 User can Add up to level 40 users
90 User can Add up to level 80 users
100 User can do anything

So then in my code I would do things like:

static const int Del_Insens
if ( User.level() >= Del_Insens )
Button1.Active( true )

or whatever. I would generally const define the levels.

There are many different ways to do security schemes. This way is one of
the simplest I've found.
This is one way to do it, there are others. I would never hard code user
information into code however
 
J

James Kanze

So I have been doing C++ for quite awhile but have never had too many
occasions to use |.
What I'm trying to provide is ability to say enum myEnum = myEnum::eek:ne
| myEnum::two.
I'm not sure if this makes sense so I'll use my actual situation as an
example.
I am doing a menu system where each button the screen has an access
role as does the user. So the simplest example would be.
User is Susie;
Button 1 should be available to Susie or Johnny.
So Button1.Access = myEnum::Susie | myEnum::Johnny.
Is that the best way to do it? Is it even possible?

You have to define the enum values as bit masks, e.g.:

enum E
{
Susie = 0x01,
Johnny = 0x02,
// ...
} ;

You can then overload the | and the |= operators:

E
operator|( E lhs, E rhs )
{
return static_cast< E >(
static_cast< unsigned >( lhs )
| static_cast< unsigned >( rhs ) ) ;
}

E operator|=( E& lhs, E rhs )
{
lhs = lhs | rhs ;
}

If you do this, you may want to add an enum value none = 0,
since you can't pass 0 as an argument to a function expecting an
E. (Note that this sort of thing is a very frequent use of
enums in C++.)
 
J

James Kanze

In most cases you cannot do that (nor do you really want to).

Nonsense. The standard does it in many cases: ios::state, for
example.
If you think that the inclusive-or combination of those two
values should also be a valid value in your 'myEnum', add it
there *explicitly* in the definition of the 'myEnum'
enumeration.

That's not always reasonable, if the number of cases is large.

[...]
It would work if you don't try to make 'Button1.Access' of the
type 'myEnum'.

It works very well if Button1.Access has an enumerated type as
well. I do it all the time.
It should be of type 'int' or 'unsigned' (or some such)
and when you need to check if 'Johnny' has access you would also do
the 'and' operation:
myEnum john_smith = Johnny; //
...
if (john_smith & Button1.Access) // Does 'john_smith' have access?
...

You can apply the built-in | or & directly to the enum type, but
the results will have the underlying integral type (and that
should be:
if ( (john_smith & Button1.Access) != 0 )
unless you're into obfuscation). But since enum's are user
defined types, you can also overload the |, & and ~ operators
for them, to get the correct types. (Another alternative would
be to overload + and -, to add or remove an element, and use a
function contains() to test whether the enum contained the
element.)

Despite their name, enum, in C++, is not necessarily an
enumerated type, in the classical sense. It can be used as
such, but it can also be used as a small set of named elements.
Such use is very idiomatic C++.
 

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

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,151
Latest member
JaclynMarl
Top