The big STL Algorithms tutorial: all_of, any_of, none_of

Sandor Dargo - Feb 20 '19 - - Dev Community

In this first part of the big STL algorithm tutorial, I'll start with the first chunk of the non-modifying sequence operations.

Namely, in this post, you are going to read about all_of, any_of and none_of functions.

Their names are quite intuitive and as you might suspect it, they all return booleans and they operate on STL containers.

Unless you use ranges (that should be part of another post), you don't pass them directly a container, but rather two iterators on the same container. Those iterators define the range the function will work on.

After the two iterators, you pass in a predicate. That predicate can be a function pointer or a function object (including lambdas) returning a boolean or at least something that is convertible to boolean.

It means that the next code does NOT even compile:

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{

  auto nums = {1,2,3,4,5,3};
  if (std::any_of(std::begin(nums), std::end(nums), 3) {
      std::cout << "there is a 3 in the list" << std::endl;
  } else {
      std::cout << "there is NOT ANY 3 in the list" << std::endl;
  }

}

Enter fullscreen mode Exit fullscreen mode

Instead, let's see two implementation that works. The first one will use a function object:

#include <iostream>
#include <vector>
#include <algorithm>


class IsEqualTo {
public:
    IsEqualTo(int num) : m_num(num) {}

    bool operator()(int i) {
        return i == m_num;
    }
private:
    int m_num;
};

int main()
{

auto nums = {1,2,3,4,5,3};
if (std::any_of(std::begin(nums), std::end(nums), IsEqualTo(3))) {
      std::cout << "there is a 3 in the list" << std::endl;
  } else {
      std::cout << "there is NOT ANY 3 in the list" << std::endl;
}

}
Enter fullscreen mode Exit fullscreen mode

It's a bit long, but thanks to the well-named functor (function object) it is easily readable.

Now let's have a look at bersion with a lambda expression:

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{

  auto nums = {1,2,3,4,5,3};
  if (std::any_of(std::begin(nums), std::end(nums), [](int i){return i == 3;})) {
      std::cout << "there is a 3 in the list" << std::endl;
  } else {
      std::cout << "there is NOT ANY 3 in the list" << std::endl;
  }

}

Enter fullscreen mode Exit fullscreen mode

This version is a lot shorter, a lot more dense and instead of the whole definition of our class IsEqualTo you have only this lambda expression: [](int i){return i == 3;}).

Which one is better to use? It depends on the context. You can read some details about this question and on how to write lambdas in C++ in general in this article.

Now, let's talk a little bit about what the 3 mentioned functions do, but maybe it's already clear to you.

std::all_of

std::all_of will return true if the predicate is evaluated to true or can be converted to true for all the items, false otherwise.

That "can be converted" part means that the predicate doesn't have to return a boolean. It can return a number for example. But really anything that can be treated as a boolean.

std::any_of

std::any_of will return true if the predicate is evaluated to true or can be converted to true for any of the items, false otherwise. Meaning that if the predicate is true only for one element out of a hundred, std::any_of will return true.

std::none_of

std::none_of will return true if the predicate is evaluated to true or can be converted to true for none of the items, false otherwise. Turning it around, std::none_of return true if the predicate is false for all the items! If there is at least one returning true, the function itself will return false.

Conclusion

That's it for the first part. The three presented functions - all_of, any_of and none_of - can replace ugly loops with an if and a break inside your code, making it much more expressive and readable. Use them without moderation wherever you can and stay tuned for the next episodes!

This article has been originally published on my blog.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .