std :: expf и std :: logf не распознаются gcc 7.2.0 - PullRequest
4 голосов
/ 01 апреля 2019

Кажется, что gcc (пробовал 7.2.0 и 5.4.0) не имеет std :: expf и std :: logf - см. Coliru sample .Поскольку cppreference говорит, что они были добавлены в C ++ 11, есть ли какой-то специфичный для gcc макрос, которого мне не хватает, или они вообще отсутствуют в gcc?

Ответы [ 4 ]

2 голосов
/ 03 июня 2019

Это ошибка в libstdc ++, который поставляется с GCC.Он не полностью соответствует C ++ 17 ( по состоянию на 9.1.0 в июне 2019 ).В уведомлении об авторских правах на версию <cmath>, которую Ubuntu использует по умолчанию, говорится, что она последний раз обновлялась в 2016 году. В версии 9.1.0 есть раздел #if __cplusplus > 201402L, но в нем не указаны идентификаторы, требуемые C ++ 17. Существует открытый отчет об ошибке.

Он никогда не объявляет expf или logf (ни cosf, sinf и т. Д.) В пространстве имен std::, дажехотя C ++ 17 говорит, что должен. Стандарт C ++ 11 гласит: «Имена, которые определены как функции в C, должны быть определены как функции в стандартной библиотеке C ++».и «Каждое имя из библиотеки Standard C, объявленной с внешней связью, зарезервировано для реализации для использования в качестве имени со связью extern "C", как в namespace std, так и в глобальном пространстве имен». Однако std::expf et al.отсутствуют в таблице функций, предоставленных <cmath> до P0175r1 в июне 2016 года. Это, очевидно, было упущением, но GCC всегда делал их доступными только в глобальном пространстве имен.

Библиотека libc ++ объявляет их, поэтому компиляция с clang++ -std=c++17 -stdlib=libc++ должна работать.Вы также можете #include <math.h> использовать их в глобальном пространстве имен или использовать перегруженные exp(), log() и т. Д. Для аргументов с плавающей точкой.

1 голос
/ 01 апреля 2019

Если вы

#include <cmath>

вы получите

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 );

И, следовательно, вы можете вызвать только std::exp / std::log и позволить компилятору выяснить перегрузку для вас. Если вы хотите вызвать несоответствующую перегрузку (например, перегрузку float для переменной double), я нахожу гораздо более явным и понятным добавление static_cast в таких случаях:

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

Это странная конструкция для любого способа ее написания (например, почему bla не является float для начала?), И сокрытие ее в суффиксе имени функции из одной буквы никому не помогает.

0 голосов
/ 01 апреля 2019

GCC <cmath> объявляет функции expf и logf и их род библиотеки C в глобальном пространстве имен, а не std::std:: он объявляет перегрузки exp и log с тем же эффектом.

0 голосов
/ 01 апреля 2019

Чтобы g ++ мог использовать C ++ 11, нужно добавить

-std=c++11

в командную строку компилятора.

например:.

g++ -o test -std=c++11 test.cc
...