Стандарт С++ определяет некоторые перегруженные функции в заголовке <cmath>
, которые не являются частью заголовка <math.h>
в C (потому что C не имеет перегрузки).
Среди них float abs(float)
, double abs(double)
, long double abs(long double)
и double abs(Integral)
.
С другой стороны, abs
вообще не определяется в C <math.h>
(он вместо этого находится в <stdlib.h>
), а единственная сигнатура - int abs(int)
.
Теперь в моих системах при использовании компилятора С++ с программой на С++ #include <math.h>
не предоставляет перегрузки С++ abs
, либо в глобальном пространстве имен, либо в std
.
С другой стороны, #include <cmath>
определяет std::abs
.
Это то, что я ожидаю, - включить версию C для получения C-функций и включить версию С++ для получения функций С++. Этот ответ от @visitor упоминает одно и то же.
Однако пользователь @Cheers-and-hth-Alf утверждает, что это является нарушением стандарта, потому что он говорит: "Каждый заголовок C, каждый из которых имеет имя формы name.h
, ведет себя так, как будто каждое имя помещенный в стандартное пространство имен библиотек соответствующим заголовком cname, помещается в область глобального пространства имен." (Этот раздел, D.5.2, похоже, не сильно изменился между С++ 03, С++ 11 и С++ 14.)
Достаточно легко проверить, что делает ваша платформа: посмотреть, что происходит с
#include <math.h>
int main() {
abs(1.2);
return 0;
}
Если abs
не объявлено, то <math.h>
не включает функции С++.
Если он компилируется, попробуйте включить <stdio.h>
и добавьте printf("%g\n", abs(1.2));
Если это жалуется на несоответствующий формат или печатает 1, тогда <math.h>
включает функцию C int abs(int)
(обычно в <stdlib.h>
).
(Лучше избегать <iostream>
и других заголовков С++, так как они склонны тянуть <cstdlib>
и путать проблему.)
Вот что я нашел:
GNU libstdС++
$ g++ -Wall -Wextra abs2.cc -o abs2
abs2.cc: In function 'int main()':
abs2.cc:5:22: error: 'abs' was not declared in this scope
std::cout << abs(1.2) << '\n';
libstdС++ docs по теме
рекомендуется включать заголовки типа С++ <c*>
, а не заголовки C-стиля <*.h>
именно потому, что
Заголовки в стиле С++ используют перегрузку функций, а заголовки в стиле C - нет.
Apple libС++
$ clang++ -Wall -Wextra abs2.cc -o abs2
abs2.cc:4:5: error: use of undeclared identifier 'abs'; did you mean 'fabs'?
Кроме того, если вы также включаете <stdlib.h>
, чтобы получить определение abs
, clang++ дает
более полезное сообщение об ошибке
abs2.cc:5:5: warning: using integer absolute value function 'abs' when argument is of floating point type [-Wabsolute-value]
abs(1.2);
^
abs2.cc:5:5: note: use function 'std::abs' instead
abs(1.2);
^~~
std::abs
abs2.cc:5:5: note: include the header <cmath> or explicitly provide a declaration for 'std::abs'
abs2.cc:5:9: warning: implicit conversion from 'double' to 'int' changes value from 1.2 to 1 [-Wliteral-conversion]
abs(1.2);
~~~ ^~~
abs2.cc:5:5: warning: ignoring return value of function declared with const attribute [-Wunused-value]
abs(1.2);
^~~ ~~~
Это явно говорит о том, что перегрузки поплавка доступны только из <cmath>
, а не из
C традиционными заголовками.
Apache libstdcxx
Я не установил его, но рассмотрев заголовок math.h, он возвращает те функции из <cmath>
, которые также определены в C <math.h>
в глобальное пространство имен, но не включает abs
.
OpenWatcom С++
Опять же, рассмотрев cmath/math.h header,
при использовании в качестве math.h
он вносит те же функции в глобальное пространство имен, что и Apache libstdcxx, не включая abs
.
STLPort
Изучая заголовок math.h, он включает в себя заголовок системы C <math.h>
, который не является частью библиотеки С++ и поэтому не включает abs
. (Это то же, что и g++ и clang++).
Microsoft Visual Studio (Dinkumware)
У меня нет доступа к этому самому, но этот сайт претендует на компиляцию с использованием Visual С++, и он говорит
error C4578: 'abs': conversion from 'double' to 'int', possible loss of data
(Did you mean to call 'fabs' or to #include <cmath>?)
Итак, буквально каждая основная реализация стандартной библиотеки С++ в нарушение стандарта по этому вопросу?
Или нам не хватает чего-то, что стандарт говорит о <math.h>
и других традиционных заголовках C?