Search code examples
c++setidiomssyntactic-sugar

Most C++'ish way to check if value belongs to certain static set


Let's say that I want to write something like this (the {1, 3, 7, 42, 69, 550123} set is known before compilation):

int x;
...
if (x == 1 || x == 3 || x == 7 || x == 42 || x == 69 || x == 5550123)
{
  ...
}

The condition looks ugly because we have 9 extra symbols ("|| x ==") for each possible value. How can I rewrite it in a more C++'ish way?

My best guess is:

int x;
...
const std::unordered_set<int> v = {1, 3, 7, 42, 69, 5550123};
if (v.count(x))
{
  ...
}

It has O(1) average complexity with some memory and time overhead, but still looks kinda ugly.


Solution

  • Edit: I just noticed c++14 tag. Note that my implementation of in relies on C++17. It can be done in C++14 as well using recursion, but that involves much more boilerplate, and a bit slower compilation.

    One could use a template to generate a function with a logical operator sequence, such as the one in nvoigt's answer:

    template<auto... ts, class T>
    constexpr bool
    in(const T& t) noexcept(noexcept(((t == ts) || ...))) {
        return ((t == ts) || ...);
    }
    
    // usage
    if (in<1, 3, 7, 42, 69, 5550123>(x))
    

    That said, hiding the set of magic numbers behind a named function probably makes a lot of sense:

    constexpr bool
    is_magical(int x) noexcept {
        return in<1, 3, 7, 42, 69, 5550123>(x);
    }