In the weird, wild world of IEEE 754 floating point, NaN != NaN. In other words, two not-a-number values do not compare as equal to each other. So, you cannot simply let std::remove
do an equality test.
You need to supply your own predicate that calls a function to determine whether or not a floating-point value is NaN. If you're targeting C++11 or later, the standard library provides such a function: std::isnan
. (If not, the situation is a bit more complicated.)
Putting it all together, then, the correct code would look like this:
#include <cmath>
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<double> x = {
1,
2,
std::numeric_limits<double>::quiet_NaN(),
3,
std::numeric_limits<double>::quiet_NaN(),
4
};
std::cout << "Before removing: ";
for (auto i : x)
{
std::cout << i << " ";
}
std::cout << "\n";
x.erase(std::remove_if(std::begin(x),
std::end(x),
[](const auto& value) { return std::isnan(value); }),
std::end(x));
std::cout << "After removing: ";
for (auto i : x)
{
std::cout << i << " ";
}
return 0;
}
In case it got lost in all the demo code, the relevant part is just:
x.erase(std::remove_if(std::begin(x),
std::end(x),
[](const auto& value) { return std::isnan(value); }),
std::end(x));
where I am passing a lambda to std::remove_if
as a unary predicate. It calls std::isnan
, passing in the value to check, and it returns the result, which is a Boolean indicating whether or not the value is not-a-number. If the predicate returns true, std::remove_if
does the removal; otherwise, it doesn't.
Note that the logic in floating-point world is typically that NaN values are infectious. In other words, any operation involving a NaN will return NaN as a result. So, it strikes me as a bit odd that you're trying to remove all NaN values. Be careful not to just shove them under the rug as if they weren't there.