Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way to say x == Foo::A || x == Foo::B || x == Foo::C || ...?

Tags:

Let's say I have a bunch of well-known values, like this (but const char * is just an example, it could be more complicated):

const char *A = "A", *B = "B", *C = "C", *D = "D", *E = "E", *F = "F", *G = "G";

Now let's say I want to behave in a particular way if the result of some expression is in a subset of those:

if (some_complicated_expression_with_ugly_return_type == A ||
    some_complicated_expression_with_ugly_return_type == C ||
    some_complicated_expression_with_ugly_return_type == E ||
    some_complicated_expression_with_ugly_return_type == G)
{
    ...
}

I find myself typing this sort of thing often enough that I would like a shorthand for it.

If the language was Python, I could easily say:

if some_complicated_expression_with_ugly_return_type in [A, C, E, G]:
    ...

Is there a well-known, portable way for me to express this similarly in C++03?

Note that the return type is itself ugly (almost as ugly as the return type of lambda expressions), so I certainly don't want to store it in a local variable.

But the return type does not have to match that of the constants -- for example, if the return type was std::string, it would not be implicitly convertible to const char *, but operator == would be perfectly fine for the comparison.

So far, the best solution I have is to say something like:

const char *items[] = { A, C, E, G };
if (std::find(items, items + sizeof(items) / sizeof(*items),
              some_complicated_expression_with_ugly_return_type)
    != items + sizeof(items) / sizeof(*items))
{
    ...
}

but it's pretty darn ugly. Is there a better way, which also works for non-PODs?

like image 538
user541686 Avatar asked Sep 02 '12 21:09

user541686


People also ask

What does FOO mean in C++?

Foo (pronounced FOO) is a term used by programmers as a placeholder for a value that can change, depending on conditions or on information passed to the program. Foo and other words like it are formally known as metasyntactic variables.

What does || mean in typescript?

The logical OR ( || ) operator (logical disjunction) for a set of operands is true if and only if one or more of its operands is true. It is typically used with boolean (logical) values.

What does *= mean?

The *= operator first multiplies the value of the expression (on the right-hand side of the operator) by the value of the variable or property (on the left-hand side of the operator). The operator then assigns the result of that operation to the variable or property.

What is the meaning of +=?

The addition assignment operator ( += ) adds the value of the right operand to a variable and assigns the result to the variable.


2 Answers

If you have C++11:

auto res = some_complicated_expression_with_ugly_return_type;
if (res == A
    || res == C
    || res == E
    || res == G) {
}

if not, you can still eliminate the type declaration by using a template function:

template <class T>
bool matches(T t) {
    return t == A || t == C || t == E || t == G;
}

if (matches(some_complicated_expression_with_ugly_return_type)) {
}
like image 76
Pete Becker Avatar answered Oct 16 '22 00:10

Pete Becker


You could factor your current best solution into a template:

template<class A, class B, size_t n>
inline bool is_in(const A &a, B (&bs)[n]) {
  return std::find(bs, bs + n, a) != bs + n;
}

which you can use like

X items[] = { A, C, E, G };
if (is_in(some_complicated_expression_with_ugly_return_type, items))
  …
like image 37
MvG Avatar answered Oct 15 '22 23:10

MvG