Note that the code you posted counts the even numbers in the vector, not the odd ones:
count_if(vec.begin(), vec.end(),
bind(logical_not<bool>(),
bind(modulus<int>(), placeholders::_1, 2)));
The count_if is an algorithm that returns the number of elements in the specified range satisfying specific criteria:
count_if(first, last, criteria)
In your case, first is vec.begin() and last is vec.end(): so the whole vector is considered for the count.
Now let's focus the attention on the criteria part.
Starting from inner and going outer:
modulus<int> is a function object that returns the remainder of an integer division (just like % operator). It takes two arguments: the first is expressed as placeholders::_1, which is the generic element in the source vector. Think of it as a variable x that scans the entire vector content.
The second argument is the number 2, since to check if an integer is even or odd, you can calculate x % 2 and compare the result with 0:
x % 2 == 0 --> even number
x % 2 == 1 --> odd number
bind is used to specify the arguments of the modulus function object.
The result of this modulus operation is given as input to another function object: logical_not<bool>. This just negates the input, e.g. if the input was false (0), logical_not<bool> returns true, and viceversa.
So, the "counting criteria" is expressed by this flow of operations:
- Calculate:
placeholders::_1 % 2, i.e. <<generic vector element>> % 2, using modulus.
- If the result of the above operation is
0 (false), return true (and viceversa), using logical_not.
So, if a number is even:
even number % 2 == 0
- negating 0 you get
true.
Instead, if a number is odd:
odd number % 2 == 1
- negating 1 you get
false.
Since count_if counts the number of elements for which the criteria is true, you are counting the even numbers in the vector.
If you really want to count the odd numbers in the vector, you can just get rid of the logical inversion (i.e. logical_not):
auto odds = count_if(vec.begin(), vec.end(),
bind(modulus<int>(), placeholders::_1, 2));
Note that in this case the functional approach using modulus and logical_not seems too complicated: using a lambda (or even an ad hoc IsEven() simple function) would be clearer.
Consider the following code (live here on Ideone) for a comparison between the three approaches:
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
using namespace std;
bool IsEven(int n) {
return (n % 2) == 0;
}
int main() {
// Test vector
vector<int> vec{ 11, 22, 33, 44, 55 };
// Using functional approach
auto n = count_if(vec.begin(), vec.end(),
bind(logical_not<bool>(),
bind(modulus<int>(), placeholders::_1, 2)));
cout << n << endl;
// Using lambdas
n = count_if(vec.begin(), vec.end(),
[](int n) { return (n % 2) == 0; });
cout << n << endl;
// Using boolean returning ad hoc function
n = count_if(vec.begin(), vec.end(), IsEven);
cout << n << endl;
}