std::expf and std::logf not recognized by gcc 7.2.0

后端 未结 3 1701
感动是毒
感动是毒 2020-12-20 20:44

It seems that gcc (tried 7.2.0 and 5.4.0) does not have std::expf and std::logf - see coliru sample. Since cppreference says they were added in C++11 is there some gcc speci

相关标签:
3条回答
  • 2020-12-20 21:11

    This is a bug in libstdc++, which ships with GCC. It does not fully conform to C++17 (as of v9.1.0 in June 2019). The copyright notice on the version of <cmath> that Ubuntu uses by default says it was last updated in 2016. Version 9.1.0 does have a #if __cplusplus > 201402L section, but it doesn’t declare the identifiers required by C++17. There is an open bug report.

    It never declares expf or logf (nor cosf, sinf, etc.) within the std:: namespace, even though C++17 says it shall. The C++11 standard says, “Names that are defined as functions in C shall be defined as functions in the C++ standard library,” and “Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.” However, std::expf et al. are missing from the table of functions provided by <cmath> until P0175r1 in June 2016. This was apparently an oversight, but GCC has always made them available only in the global namespace.

    The libc++ library does declare them, so compiling with clang++ -std=c++17 -stdlib=libc++ should work. You can also #include <math.h> to use them in the global namespace, or use the overloaded exp(), log(), etc. on float arguments.

    0 讨论(0)
  • 2020-12-20 21:20

    GCC's <cmath> declares the functions expf and logf and their C Library kin in the global namespace, not std::. In std:: it declares overloads of exp and log to the same effect.

    0 讨论(0)
  • 2020-12-20 21:25

    If you

    #include <cmath>
    

    you will get

    float       exp ( float arg );
    double      exp ( double arg );
    long double exp ( long double arg );
    double      exp ( IntegralType arg );
    
    float       log ( float arg );
    double      log ( double arg );
    long double log ( long double arg );
    double      log ( IntegralType arg );
    

    And hence you can call just std::exp/std::log and let the compiler figure out the overload for you. If you want to call a mismatching overload (e.g. the float overload on a double variable), I find it much more explicit and clear to add a static_cast in those cases:

    double bla = ...;
    return std::exp(static_cast<float>(bla));
    

    This is a strange construct any way you write it (e.g. why is bla not a float to begin with?), and hiding it in a single-letter function name suffix isn't helping anyone.

    0 讨论(0)
提交回复
热议问题