-2

I am wondering if in c++11 you can calculate this:

if (a == b || a == c) {
    // do something
}

In a much shorter and more concise way such as something like this:

if (a == (b || c)) {
    // do something
}

(I know that the above code would not work [it would calculate if b or c and then check if the result is equal to a]. I am wondering if there is a similar way to implement the code before: if (a == b || a == c) {})

Snail5008
  • 59
  • 1
  • 9
  • 6
    This sounds like an XY problem. Why do you want to rewrite this condition? Original works perfectly well. One way to rewrite is preferably a function or macro. BTW there is a short circuit while calculating the value. – Mohit Jain Jan 02 '22 at 04:56
  • 3
    Are you trying to save keystrokes, or to make the code faster? – Sneftel Jan 02 '22 at 04:57
  • @Sneftel I am just trying to clean up my code a little bit and make it easier to read. – Snail5008 Jan 02 '22 at 05:01
  • 3
    With a sufficiently modern compiler, you could write `if (std::set{b, c}.contains(a))`, but I'm not sure this is an improvement. – Igor Tandetnik Jan 02 '22 at 05:02
  • @IgorTandetnik This is a good soulution for bools, but I am comparing strings, and this function seems to only allow for bools. [please correct me if I'm wrong] – Snail5008 Jan 02 '22 at 05:06
  • @AdrianMole Thanks, for noticing that, I meant ||, I'll edit it now. – Snail5008 Jan 02 '22 at 05:07
  • It would work with any type that could be put into an `std::set`, including `std::string` – Igor Tandetnik Jan 02 '22 at 05:08
  • I'm sort of lost here, what types are we talking about? I can see optimizations but for bools and ints for example, perhaps for strings too. But these are different paths of solution. –  Jan 02 '22 at 05:12
  • Yes. Assuming `c` is appropriate type. – Eljay Jan 02 '22 at 05:14
  • use ternary operator – A.A Noman Jan 02 '22 at 05:25
  • For chars, you could do: if (strchr(a, “bcdefg”) != NULL) – Jeremy Friesner Jan 02 '22 at 05:36
  • 2
    If you want to cleanup your code (and a,b,c aren't char's) then give them more readable names and put your or's in a function with a name what the logic is doing. Also note that 'or' and 'and' are smart enough to stop evaluating early : e.g. for 'or' if (a==b) is true then it doesn't evaluate (a==c) since it already knows the end result will be true. So actually your way of writing it down will be fast (a lot faster then using std::set) – Pepijn Kramer Jan 02 '22 at 05:54
  • You could use variadic templates for this. [Here's](https://gcc.godbolt.org/z/aqj6nPK4Y) an example where you call a compare function recursively, peeling of the arguments one by one and comparing it with the first one. – jignatius Jan 02 '22 at 07:05

1 Answers1

0

What you are basically doing is testing if a equals a value in a set. And yes std::set can be used but its slow. This example is a bit slower then hard coding the full expression. But it shows what is being calculated and the righthand side will look like a set/collection.

#include <utility> // for std::size_t

template<typename type_t, std::size_t N>
inline constexpr bool is_any_of(const type_t& lhs, const type_t(&set)[N])
{
    for (const auto& rhs : set)
    {
        if (lhs == rhs) return true;
    }
    return false;
}

int main()
{
    constexpr int a = 1;
    constexpr int b = 3;
    constexpr int c = 2;
    constexpr int d = 1;

    static_assert(!is_any_of(a, { b, c }));
    static_assert(is_any_of(a, { b, d }));
    static_assert(is_any_of(a, { b, c, d }));
    
    return 0;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19