Ошибка g ++: нет подходящей функции для вызова 'fpclassify (float &)' - PullRequest
0 голосов
/ 01 июня 2018

Я использую GCC 5.4.0 и Boost 1.67.0 в системе Fedora 26 (это не системный компилятор по умолчанию).Если я скомпилирую следующее 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 и более поздними версиями.Спасибо @ Джастин.Кроме того, этого не происходит с clang v3.5 и более поздними версиями (не всесторонне протестированными).

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Определение __CORRECT_ISO_CPP11_MATH_H_PROTO означает "libc, для которого был настроен и собран этот libstdc ++, имеет math.h, который предоставляет функции C ++ 11, поэтому <cmath> не должен пытаться предоставлять свои собственные".

С какой стати вы сами определяете этот макрос?

0 голосов
/ 01 июня 2018

Проблема может быть воспроизведена с помощью:

#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 в этих версиях 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).


Я нашел соответствующую фиксацию для libstdc ++ .В комментарии предлагается, чтобы этот макрос определялся только в том случае, если math.h уже предоставил три перегрузки fpclassify для трех типов с плавающей запятой.

Код autoconf для libstdc ++ проверяет существующую систему math.h и выдает этот макрос, если он уже определил три перегрузки fpclassify.

Если вы находитесь в реализации, где math.hне предоставляет перегрузок, поэтому вы не должны использовать этот макрос, иначе вы сделаете вашу реализацию не соответствующей.

...