Board index » cppbuilder » Shorter way to check equivalence to more than one enum?

Shorter way to check equivalence to more than one enum?


2005-03-16 06:19:57 AM
cppbuilder61
Is there a more elegant (i.e., shorter) way to check whether a value is
equivalent to more than one enum? For example, to check whether to call
TDataSet::Post, I write:
--------------------------------------------------------------
if (DataSet->State == dsEdit || DataSet->State == dsInsert)
--------------------------------------------------------------
I tried:
--------------------------------------------------------------
if (DataSet->State == (dsEdit || dsInsert))
--------------------------------------------------------------
and:
--------------------------------------------------------------
if (DataSet->State == (dsEdit | dsInsert))
--------------------------------------------------------------
but neither produced the desired result. Thanks.
 
 

Re:Shorter way to check equivalence to more than one enum?

C.R. Hinners wrote:
Quote
Is there a more elegant (i.e., shorter) way to check whether a value
is equivalent to more than one enum? For example, to check whether to
call TDataSet::Post, I write:

if (DataSet->State == dsEdit || DataSet->State == dsInsert)

I tried:

if (DataSet->State == (dsEdit || dsInsert))
|| interprets both as boolean value, so this will always return true,
and probably not what DataSet->State is.
Quote
and:
if (DataSet->State == (dsEdit | dsInsert))

but neither produced the desired result. Thanks.
Don't think about optimization before it is required. Writing readable
code is more important. Only if you see bottlenecks, and have profiled
your code, optimize those parts which are too slow. Not earlier.
But if you really must, this is an alternative:
switch(DataSet->State)
{
case dsEdit:
case dsInsert:
ShowMessage("Either dsEdit or dsInsert");
break;
default:
ShowMessage("Anything but dsEdit or dsInsert");
break;
}
I would prefer the simple version, though:
TDataSetState state = DataSet->State;
if (state == dsEdit || state == dsInsert)
ShowMessage("Either dsEdit or dsInsert");
else
ShowMessage("Anything but dsEdit or dsInsert");
It will probably be optimized by the compiler anyway. And that piece of
code is probably never a bottleneck, anyway.
--
Rudy Velthuis [TeamB] rvelthuis.bei.t-online.de
"Never mistake motion for action." -- Ernest Hemingway (1899-1961)
 

Re:Shorter way to check equivalence to more than one enum?

"C.R. Hinners" < XXXX@XXXXX.COM >writes:
Quote
Is there a more elegant (i.e., shorter) way to check whether a value
is equivalent to more than one enum? For example, to check whether to
call TDataSet::Post, I write:

--------------------------------------------------------------
if (DataSet->State == dsEdit || DataSet->State == dsInsert)
--------------------------------------------------------------
This works.
Quote
I tried:

--------------------------------------------------------------
if (DataSet->State == (dsEdit || dsInsert))
--------------------------------------------------------------
This doesn't work. It evaluates as follows:
if (DataSet->State == (dsEdit || dsInsert))
if (DataSet->State == (true)
if (DataSet->State == 1)
Quote
--------------------------------------------------------------
if (DataSet->State == (dsEdit | dsInsert))
--------------------------------------------------------------
This could work if your enumerators each have a unique single-bit
value (each a different power of two). Then you can use each bit in
the enum to indicate the presence or not of the enumerator. They can
be OR'ed together, and other types of boolean logic will apply.
Of course, this requires that you have control over the value of the
enum. If it's one supplied by the VCL or in a 3rd party library, you
can't go and change it. If it's not already bit-field compatible,
then forget this idea.
If you control the enum, and can make the values be whateve you want,
you still need to decide if it makes sense for more than one state at
a time to apply. That is, in a single enum, you can OR in multiple
states, and they are all simultaneously set.
So if you control the enum, and it makes sense, then you can do
something like this: (I'm just making these names up, but the numeric
values are important, since it's a nice, easy way to get powers
enum TDataSet {
dsEdit = (1<<0),
dsReadOnly = (1<<1),
dsInsert = (1<<2),
dsOverstrike = (1<<3),
dsWhatever = (1<<4),
};
Since each enumerator uses a different bit, then one enum variable can
hold each state seperately. Now you can check for diferrent things:
// Is our state Edit or Insert?
if (DataSet->State & (dsEdit | dsInsert))
However, the above example has a flaw: it makes no sense to be in both
Edit and ReadOnly state, nor does it make sense to simultaneously be
in insert and overstrike states. So if there are mutually exclusive
states like this, you should abandon any thoughts of using this
technique... it invites too many mistakes.
Low-level bit tweaking can be concise and straight forward, but it can
also be confusing if not done clearly.
--
Chris (TeamB);
 

{smallsort}

Re:Shorter way to check equivalence to more than one enum?

"Rudy Velthuis [TeamB]" < XXXX@XXXXX.COM >wrote in message
Quote
But if you really must, this is an alternative:
Do note that the generated machine code will do pretty much the same as the
original code - checking the values individually.
Gambit
 

Re:Shorter way to check equivalence to more than one enum?

"C.R. Hinners" < XXXX@XXXXX.COM >wrote in message
Quote
Is there a more elegant (i.e., shorter) way to check whether a value
is equivalent to more than one enum?
Runtime performance won't be improved much, but you can use a Set, ie:
typedef Set<TDataSetState, dsInactive, esOpeningt>DataSetStates;
DataSetStates ValidStates = DataSetStates() << dsEdit << dsInsert;
if( ValidStates.Contains(DataSet->State) )
//...
Gambit
 

Re:Shorter way to check equivalence to more than one enum?

Remy Lebeau (TeamB) wrote:
Quote

"Rudy Velthuis [TeamB]" < XXXX@XXXXX.COM >wrote in message
news:xn0dzsni35tm3dg01yrudys-toshiba@www.teamb.com...

>But if you really must, this is an alternative:

Do note that the generated machine code will do pretty much the same
as the original code - checking the values individually.
Yes, probably. For many values, the compiler may build a jump table,
though.
--
Rudy Velthuis [TeamB] rvelthuis.bei.t-online.de
"Man is the best computer we can put aboard a spacecraft... and the
only one that can be mass produced with unskilled labor."
-- Wernher von Braun
 

Re:Shorter way to check equivalence to more than one enum?

Dear all,
If more than 2 (better with 4 or more values), and the enumerator values are
tightly packed, you can use the switch statement which, the compiler will
generate a jump table. If the values are not tightly packed, 2 jumps will be
needed.
Regards,
Keith Lai.
"C.R. Hinners" < XXXX@XXXXX.COM >???
Quote
Is there a more elegant (i.e., shorter) way to check whether a value is
equivalent to more than one enum? For example, to check whether to call
TDataSet::Post, I write:

--------------------------------------------------------------
if (DataSet->State == dsEdit || DataSet->State == dsInsert)
--------------------------------------------------------------

I tried:

--------------------------------------------------------------
if (DataSet->State == (dsEdit || dsInsert))
--------------------------------------------------------------

and:

--------------------------------------------------------------
if (DataSet->State == (dsEdit | dsInsert))
--------------------------------------------------------------

but neither produced the desired result. Thanks.
 

Re:Shorter way to check equivalence to more than one enum?

On Tue, 15 Mar 2005 17:19:57 -0500, C.R. Hinners wrote:
Quote
For example, to check whether to call
TDataSet::Post, I write:
Why not use a switch?
switch(DataSet->State)
{
case dsEdit: case dsInsert:
// do something
break;
default:
// do other stuff
breakl
}
--
Good luck,
liz
 

Re:Shorter way to check equivalence to more than one enum?

Liz Albin wrote:
Quote
On Tue, 15 Mar 2005 17:19:57 -0500, C.R. Hinners wrote:

>For example, to check whether to call
>TDataSet::Post, I write:

Why not use a switch?

switch(DataSet->State)
{
case dsEdit: case dsInsert:
// do something
break;
default:
// do other stuff
breakl
}
Pah! See what I posted. <g>
--
Rudy Velthuis [TeamB] rvelthuis.bei.t-online.de
Bible, Dijkstra 5:15
"and the clueless shall spend their time reinventing the wheel while the
elite merely use the Wordstar key mappings" -- Ed Mulroy
 

Re:Shorter way to check equivalence to more than one enum?

Thanks all! Don't get me wrong, I am all in favor of readability over
"tricks"; this simply came up more out of curiosity when I saw that the Delphi
folks can apparently write the same thing as:
-----------------------------------------------------------
if (DataSet.State in [dsEdit, dsInsert])
-----------------------------------------------------------
which surprised me, given that State is an enum, not a Set, and sparked my
curiosity as to a C++ equivalent (switch statement aside) in some library
somewhere.
 

Re:Shorter way to check equivalence to more than one enum?

C.R. Hinners wrote:
Quote
-----------------------------------------------------------
if (DataSet.State in [dsEdit, dsInsert])
-----------------------------------------------------------

which surprised me, given that State is an enum, not a Set,
[dsInsert, dsEdit] is a set of enum values. Just like [0, 3, 5] is a
set of Byte values. In tests if the value is in the set, i.e. it is
more or less equivalent to mySet.Contains(aCertainValue).
--
Rudy Velthuis [TeamB] rvelthuis.bei.t-online.de
"The first half of our life is ruined by our parents and the second
half by our children." - Clarence Darrow.