I need to write a condition that checks if an enum variable in range of values, like it can be done in E language:
enum EnumVariable {a, b, d, g, f, t, k, i};
if (EnumVariable in [ a, g, t, i]) {
...
}
Is there a better way in C++ than ask 4 times if EnumVariable==a or EnumVariable==b
etc.?
this is often/usually accomplished using bit fields in an enum (clearly, up to the number of bits of an integral type (usually 32 bits), that is the default type at the base of an enum):
that shortly can be seen just as:
There is not the same, compact syntax, but you can use
std::find
with anstd::initializer_list
. For example,This can easily be wrapper up in a helper function that takes the enum value, the list, and returns a
bool
. For example:usage:
Yet-another approach is to use a template to specify the list to match in, which for your
enum
case will presumably be known at compile time (otherwise even theswitch
approach is inapplicable). This allows a notation like:With optimisation enabled, this should be inlined and yield something equivalent to:
Implemention below (also ideone). I've not played with variadic templates much, so suggestions welcome. In particular, how to make it type-safe so given
enum E { E1 }; enum F { F1 };
,in<E1>(F1)
won't compile (without limiting it to a specificenum
type).Output:
It's absolutely not idiomatic, and probably to avoid, but the closest you can have (syntactically speaking) is to use named operators. Named operators actually correspond to an abuse of operator overloading.
Here is a working example on Coliru.
If you use C++14 and polymorphic lambdas, you can make the above example more generic:
In C++11 a brief way to express this is by using the brace-init syntax to construct a set, and calling
std::set::count
to test if the element is present:A compilable example:
Note about efficiency: since the question asked about a "comparison operator", the answer is written with the goal of providing a fairly readable and brief single expression that does not require a separate utility function. Since it builds a temporary
std::set
, it is not nearly as efficient as aswitch
statement, which is compiled into tests or jump tables by all relevant compilers.It appeared, that several people liked my comment and asked to post it as an answer, so:
You can actually use
switch
for integral types withoutbreak
-s between some values.For example, your code could look like:
This would be very efficient, but would work for integral types only, and not for
std::string
, for example. For other types, you may try to use some of the other answers' suggestions.It's a bit long for writing, but very, very efficient and does what you need.