g ++错误:没有匹配函数来调用'fpclassify(float&)'

时间:2018-05-31 21:38:04

标签: c++ gcc boost

我在Fedora 26系统上使用GCC 5.4.0和Boost 1.67.0(这不是系统的默认编译器)。如果我编译以下a.cpp

#include <boost/any.hpp>

使用命令行:

g++ a.cpp -c -o a.o  --std=c++11 -D__CORRECT_ISO_CPP11_MATH_H_PROTO -I/path/to/boost/include

我收到以下错误:

... blah blah blah ...
/path/to/boost/include/boost/container_hash/detail/hash_float.hpp:212:36: error: no matching function for call to ‘fpclassify(float&)’
         switch (std::fpclassify(v))
... blah blah blah ...

如果我没有定义_CORRECT_ISO_CPP11_MATH_H_PROTO编译结束且没有错误。

以前的Boost版本不会发生这种情况。例如1.62.0。为什么现在发生?

注意:在某些GCC 6.x版本中会出现这种情况:GCC 6.1(Godbolt)和6.2,但6.3和更高版本没有。谢谢@Justin。此外,clang v3.5及更高版本(未经过广泛测试)也不会发生这种情况。

2 个答案:

答案 0 :(得分:3)

问题可以通过以下方式重现:

#define __CORRECT_ISO_CPP11_MATH_H_PROTO 1
#include <cmath>

int main()
{ 
    float v;
    std::fpclassify(v);
}

C ++ 11标准(N3337)为3个浮点类型指定了std::fpclassify的3个重载(没有constexpr)。

代码无法编译,因为cmath标题in these versions of gcc包含(伪代码):

#include <math.h>
#undef fpclassify

#if __cplusplus >= 201103L
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO
constexpr int fpclassify(float __x) {.....}    
constexpr int fpclassify(double __x) {.....}    
constexpr int fpclassify(long double __x) {.....}
#endif

template<typename _Tp>
constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, int>::__type
fpclassify(_Tp __x)
{

这意味着std::fpclassify只能通过整数参数找到。 (我相信这个整数重载是为了满足浮点函数的整数参数应该调用double重载的一般数学要求。)

我找到了the relevant commit to libstdc++。评论建议只有在math.h已经为三个浮点类型提供了fpclassify的三个重载时才应定义此宏。

libstdc ++的autoconf代码检查现有系统math.h并发出此宏,如果它已经定义了fpclassify的三个重载。

如果您处于math.h未提供重载的实现中,则不应使用此宏,否则您将使实现不符合。

答案 1 :(得分:3)

定义__CORRECT_ISO_CPP11_MATH_H_PROTO意味着&#34;此libstdc ++配置和构建的libc具有提供C ++ 11函数的math.h,因此<cmath>不应该&#39;试着提供自己的&#34;。

为什么你自己定义那个宏呢?