WarningThe
std::min
is very different fromstd::min_element
!!
☕The Story
It was a typical day at the office, and I was working on optimizing some code. The task seems easy: find the minimum item in a std::vector
container. Confidently, I typed out what I thought was the correct line of code😎:
const auto numbers = std::vector<int>{9, 0, 2, 3, 6, 8, 7, 1};
const auto min = std::min(numbers.cbegin(), numbers.cend());
Great, the program is compiled, and I thought I had nailed it😏 and the result is trivially to be 0
. However, as I started running the application, the results were far from what I expected. Instead of getting the smallest element in the vector, the program was producing bizarre outcomes and it was 9
😱.
Perplexed, I dug deeper and soon realized my mistake. I had confused std::min
with std::min_element
. Although they look similar by their names, their functionalities are quite different. This small oversight led to unexpected behavior in my code.
🤔Understanding the Difference
The difference is trivial.
std::min
is used to find the smaller of 2 values.std::min_element
is used to find the smallest element in a range.
Remark
In math, the
std::min
is a binary operation while the input ofstd::min_element
is a group of something.
🚭The Mistake
When I used std::min(numbers.cbegin(), numbers.cend())
, the compiler interpreted it as comparing the two iterators numbers.cbegin()
and numbers.cend()
🫢. Therefore, I am actually comparing the minimum value of 2 memory address of pointers!
✏Can we do better?
From the interface of std::min
and std::min_element
, I see a similarity
template< class T, class Compare >
const T& std::min( const T& a, const T& b, Compare comp );
template< class ForwardIt >
ForwardIt min_element( ForwardIt first, ForwardIt last );
They both receive 2 arguments… That’s my “root cause” of this bug.
📌solution 1
Use std::ranges::min_element
in C++20 . In this way, you will not accidently hit into the binary operation.
const auto min_element = std::ranges::min_element(numbers);
📌solution 2
Explicitly fill the template parameter T
:
//std::min<int>(numbers.begin(), numbers.end())❌ failed to compile
And we are aware we made some mistake from this compiler error message.