如何将isnan用作std::find_if(c++11)的谓词函数

How to use isnan as a predicate function to std::find_if (c++11)

本文关键字:c++11 函数 谓词 if find isnan 用作 std      更新时间:2023-10-16

我有一段代码在std::vector<double> cats上运行,它正在做这样的事情:

std::find_if(cats.begin(), cats.end(), std::isnan<double>);

这是在gcc 4.3之前编译的,但不再使用gcc 4.7.2编译。我得到这样一个错误:

error: no matching function for call to 'find_if(std::vector<double>::iterator, std::vector<double::iterator, <unresolved overloaded function type>)'

如何在较新的gcc下进行编译?最好也是在旧的gcc下?当然,不需要去掉stl和手动编写循环。如果不能同时做到这两个,那么新的gcc就足够了,我会将两个实现都保留为#define

您实际想要的重载不是GCC 4.7中的模板,它只是一个具有以下签名的正常函数:

bool isnan(double);

(有一个模板,但SFINAE意味着它只适用于积分类型。)

但在以前的版本中,它是一个模板,所以没有一种简单的可移植的方法来获取它的地址。

既然您已经说过C++11,那么您可以使用lambda,并让lambda的主体进行重载解析,以找到正确的重载(或模板专用化):

std::find_if( cats.begin(), cats.end(), [](double d) { return std::isnan(d); } );

否则,对于C++03,您可以提供自己的转发包装:

struct IsNan {
  double operator()(double d) const { return std::isnan(d); }
};
std::find_if( cats.begin(), cats.end(), IsNan() );

在C++11中,isnan是针对不同浮点类型floatdoublelong double的三个重载的集合。您可以使用强制转换语法来解决所需的过载:

std::find_if(cats.begin(), cats.end(),
             static_cast<bool (*)(double)>(std::isnan));

当然,如果您的目标平台都支持lambda,那么对于维护人员来说,Jonathan建议的lambda的使用可能会更清楚。