The safest path is to remove all the NaNs values from the range before applying any min-max standard algorithm.
Consider a possible implementation of std::min_element
1:
template<class ForwardIt>
ForwardIt min_element(ForwardIt first, ForwardIt last)
{
if (first == last) return last;
ForwardIt smallest = first; // <-- If the first is a NaN...
++first;
for (; first != last; ++first) {
if (*first < *smallest) { // <-- This condition will always be FALSE
smallest = first;
}
}
return smallest; // <-- An iterator to a NaN is returned
}
More formally, the C++ Standard2 specifies:
27.8.1 General [alg.sorting.general]
The operations in [alg.sorting] defined directly in namespace std have two versions: one that takes a function object of type Compare
and one that uses an operator<
.
Compare
is a function object type ([function.objects]) that meets the requirements for a template parameter named BinaryPredicate
([algorithms.requirements]). The return value of the function call operation applied to an object of type Compare
, when contextually converted to bool
([conv]), yields true if the first argument of the call is less than the second, and false otherwise. Compare comp
is used throughout for algorithms assuming an ordering relation.
For all algorithms that take Compare
, there is a version that uses operator<
instead. That is, comp(*i, *j) != false
defaults to *i < *j != false
. For algorithms other than those described in [alg.binary.search], comp
shall induce a strict weak ordering on the values.
The term strict refers to the requirement of an irreflexive relation (!comp(x, x)
for all x
), and the term weak to requirements that are not as strong as those for a total ordering, but stronger than those for a partial ordering. If we define equiv(a, b)
as !comp(a, b) && !comp(b, a)
, then the requirements are that comp
and equiv
both be transitive relations:
(4.1) comp(a, b) && comp(b, c)
implies comp(a, c)
(4.2) equiv(a, b) && equiv(b, c)
implies equiv(a, c)
The problem, given any float
value x
, is that the following hold:
x < NaN == false
and NaN < x == false
, but x != NaN
Only considering the subset of the float
values which are not NaNs we can fulfill the requirement.
1) https://en.cppreference.com/w/cpp/algorithm/min_element
2) I'm quoting the draft at https://eel.is/c++draft/alg.sorting.general , emphasis mine.