In languages such as python, there is an in operator that is used to check if element is in a range:

if 5 in [1, 2, 3, 4, 5]: print("There is a 5")

What’s nice about this, is the almost english type readability of it. Let’s look at how we can implement such an operator in C++14.

No Macros

Using the infix adaptor in the Fit library, we can define named infix operators without having to resort to dangerous macros(such as #define in ). Here’s a simple example:

auto plus = infix([](int x, int y) { return x + y; }); auto three = 1 <plus> 2;

Searching the range

Now, we can use the general purpose std::find to search, however, associative containers such as map or set provide there own find function that is either faster, or allows searching just by key. So let’s write a find_iterator functions that will search by the member function find if found, else it will search using std::find :

FIT_STATIC_LAMBDA_FUNCTION(find_iterator) = fit::conditional( [](const auto& r, const auto& x) -> decltype(r.find(x)) { return r.find(x); }, [](const auto& r, const auto& x) { using std::begin; using std::end; return std::find(begin(r), end(r), x); } );

The trailing decltype in the function (ie -> decltype(r.find(x)) ) constraints the function such that if r.find can’t be called the function won’t be called either(so the next function, ie the std::find version, will be called instead).

There is one problem with this function. It doesn’t work with std::string . As the black sheep of the family, the find in std::string returns an index instread of an iterator. So we can easily add another overload for std::string that converts the index to an iterator:

FIT_STATIC_LAMBDA_FUNCTION(find_iterator) = fit::conditional( [](const std::string& s, const auto& x) { auto index = s.find(x); if (index == std::string::npos) return s.end(); else return s.begin() + index; }, [](const auto& r, const auto& x) -> decltype(r.find(x)) { return r.find(x); }, [](const auto& r, const auto& x) { using std::begin; using std::end; return std::find(begin(r), end(r), x); } );

Putting it together

Well, now we can write the in function, that calls find_iterator and check for the end:

FIT_STATIC_LAMBDA_FUNCTION(in) = fit::infix( [](const auto& x, const auto& r) { using std::end; return find_iterator(r, x) != end(r); } );

So now we can use it for std::vector :

std::vector<int> numbers = { 1, 2, 3, 4, 5 }; if (5 <in> numbers) std::cout << "Yes" << std::endl;

Or with an std::string :

std::string s = "hello world"; if ("hello" <in> s) std::cout << "Yes" << std::endl;

Or even with an std::map :

std::map<int, std::string> number_map = { { 1, "1" }, { 2, "2" }, { 3, "3" }, { 4, "4" } }; if (4 <in> number_map) std::cout << "Yes" << std::endl;

Now, when we want to negate the in operator, we will need extra parenthesis because of operator precedence: