C++ Coding Reference: count and count_if


Novice C++ programmers usually write a simple for loop if they want to count number of particular elements in the array – which could be entirely replaced by STL::count or STL::count_if.

std::count()

For example, given the following vector/array.

vector<int> nums({ 1, 2, 3, 4, 5, 3});

If we want to count the number of 3’s, we can use the std::count(). The first two parameters of the count() specify the range of the vector, and the third parameter is the target element.

cout << count(begin(nums), end(nums), 3); // prints 2.

The count() is defined in C++ header xutility and has the following template definitions:

// FUNCTION TEMPLATE count
template<class _InIt,
	class _Ty>
	_NODISCARD inline _Iter_diff_t<_InIt> count(const _InIt _First, const _InIt _Last, const _Ty& _Val)
	{	// count elements that match _Val
	_Adl_verify_range(_First, _Last);
	auto _UFirst = _Get_unwrapped(_First);
	const auto _ULast = _Get_unwrapped(_Last);
	_Iter_diff_t<_InIt> _Count = 0;

	for (; _UFirst != _ULast; ++_UFirst)
		{
		if (*_UFirst == _Val)
			{
			++_Count;
			}
		}

	return (_Count);
	}

#if _HAS_CXX17
template<class _ExPo,
	class _FwdIt,
	class _Ty,
	_Enable_if_execution_policy_t<_ExPo> = 0>
	_NODISCARD inline _Iter_diff_t<_FwdIt> count(_ExPo&& _Exec,
		const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) noexcept;
#endif /* _HAS_CXX17 */

std::count_if()

What if you are looking to count something more complex e.g. the even numbers in the array/vector. We can use the std::count_if() which the third parameter is the specified predicate condition – you can pass in a lambda function.

vector<int> nums({ 1, 2, 3, 4, 5, 3});
cout << count_if(begin(nums), end(nums), [](auto &a) { 
   return a % 2 == 0; 
});  // print 2 because there are 2 even numbers: 2 and 4.

The std::count_if is defined in C++ header file algorithm and its definition based on template is as follows:

// FUNCTION TEMPLATE count_if
template<class _InIt,
	class _Pr>
	_NODISCARD inline _Iter_diff_t<_InIt> count_if(_InIt _First, _InIt _Last, _Pr _Pred)
	{	// count elements satisfying _Pred
	_Adl_verify_range(_First, _Last);
	auto _UFirst = _Get_unwrapped(_First);
	const auto _ULast = _Get_unwrapped(_Last);
	_Iter_diff_t<_InIt> _Count = 0;
	for (; _UFirst != _ULast; ++_UFirst)
		{
		if (_Pred(*_UFirst))
			{
			++_Count;
			}
		}

	return (_Count);
	}

#if _HAS_CXX17
template<class _ExPo,
	class _FwdIt,
	class _Pr,
	_Enable_if_execution_policy_t<_ExPo> = 0>
	_NODISCARD inline _Iter_diff_t<_FwdIt> count_if(_ExPo&& _Exec,
		const _FwdIt _First, const _FwdIt _Last, _Pr _Pred) noexcept;
#endif /* _HAS_CXX17 */

count() and count_if() are self explanatory which means you don’t need to even put comments. Using the std::count() and std::count_if() from the STL, you probably don’t need to write your own loop to count the elements in the STL containers anymore!

std::algorithms vs ranges

In modern C++, there are two variants of count_if, each coming from a different header:

  • algorithm: Classic iterator‑based algorithm, since C++98.
  • ranges: Range‑aware algorithm: since C++20.

Using algorithm the classic way to do count or count_if.

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

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6};

    auto n = std::count_if(v.begin(), v.end(),
                           [](int x){ return x % 2 == 0; });

    std::cout << n << '\n';   // prints 3
}

Using the ranges version:

#include <algorithm>   // provides std::ranges::count_if in C++20
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6};

    auto n = std::ranges::count_if(v,
                                   [](int x){ return x % 2 == 0; });

    std::cout << n << '\n';   // prints 3
}

since C++20 the Ranges library includes std::ranges::count in the header.

Why use the ranges version?

  • No need to spell out begin(v) / end(v) — it deduces them for you.
  • Accepts any range that meets the input_range concept, not just containers with iterators.
  • Safer overload set: it avoids accidental pointer arithmetic errors that can occur with the classic iterator pair.

So if you are on C++20 or later, std::ranges::count is available right alongside std::ranges::count_if.

C/C++ Programming

–EOF (The Ultimate Computing & Technology Blog) —

804 words
Last Post: How to Reorder Data in Log Files using the Custom Sorting Algorithm?
Next Post: C++ Coding Reference: next_permutation() and prev_permutation()

The Permanent URL is: C++ Coding Reference: count and count_if (AMP Version)

Leave a Reply