问题
I have a piece of code that is operating on a std::vector<double> cats
and is doing something like this:
std::find_if(cats.begin(), cats.end(), std::isnan<double>);
this compiles under gcc before 4.3 but no longer compiles with gcc 4.7.2. I get an error like this:
error: no matching function for call to 'find_if(std::vector<double>::iterator, std::vector<double::iterator, <unresolved overloaded function type>)'
How can I get this to compile under newer gcc? And preferably also under the older gcc? Without getting rid of stl and manually writing the loop of course. If it's not possible to do both, the new gcc would suffice and I would leave both implementations in there with a #define
.
回答1:
The overload you actually want is not a template in GCC 4.7, it is just a normal function with this signature:
bool isnan(double);
(There is a template, but SFINAE means it only applies to integral types.)
But in previous versions it was a template, so there isn't an easy portable way to take its address.
Since you've said C++11, you can use a lambda and let the body of the lambda do overload resolution to find the right overload (or template specialization):
std::find_if( cats.begin(), cats.end(), [](double d) { return std::isnan(d); } );
Otherwise for C++03 you could provide your own forwarding wrapper:
struct IsNan {
double operator()(double d) const { return std::isnan(d); }
};
std::find_if( cats.begin(), cats.end(), IsNan() );
回答2:
In C++11, isnan
is a set of three overloads for the different floating point types float
, double
, long double
. You can resolve the overload you want by using the cast syntax:
std::find_if(cats.begin(), cats.end(),
static_cast<bool (*)(double)>(std::isnan));
Of course, the use of a lambda as suggested by Jonathan might be clearer for maintainers, if your target platforms all support lambdas.
来源:https://stackoverflow.com/questions/17574242/how-to-use-isnan-as-a-predicate-function-to-stdfind-if-c11