Обновление 2
Этот вопрос был объединен с точной копией, если взглянуть на это, фактический ответ намного проще, чем кто-либо изначально думал. Текущая версия std_lib_facilities.h включает следующую строку:
inline double sqrt(int x) { return sqrt(double(x)); } // to match C++0x
который создает специальную перегрузку для случая int, чтобы соответствовать тому, что должны делать современные компиляторы, а именно приводить целочисленные аргументы к типу double, хотя эта версия не охватывает все случаи.
Если std_lib_facilities.h не использовался, исходная логика по-прежнему применяется, хотя gcc-4.2
довольно старая по сравнению с Visual Studio 2012 из исходного вопроса, но 4.1.2
версия использует __builtin_sqrt
специально для целочисленного случая.
Исходный
Поскольку примерно в 2005 проект стандарта требовал, чтобы аргумент integer был преобразован в double, это описано в проект стандарта C++. Если мы посмотрим в раздел 26
Библиотека числовых значений, а затем перейдем к разделу 26.8
Библиотека C, который охватывает заголовок <cmath>
, он определяет перегрузки математических функций для float, double и long double, которые описаны в параграфе 8:
В дополнение к двойным версиям математических функций в C++ добавлены версии этих функций с плавающей точкой и длинной двойной перегрузкой с той же семантикой.
что было бы ambiguous
для случая int
, но стандарт требует, чтобы была предоставлена достаточная перегрузка, чтобы целочисленные аргументы преобразовывались в двойные. Это описано в параграфе 11, в котором говорится (выделено мной):
При этом должны быть предусмотрены дополнительные перегрузки, достаточные для обеспечения:
- Если какой-либо арифметический аргумент, соответствующий параметру double, имеет тип long double, то все арифметические аргументы, соответствующие параметрам double, фактически преобразуются в тип long double.
- В противном случае, если какой-либо арифметический аргумент, соответствующий параметру double, имеет тип double или целочисленный тип, то все арифметические аргументы, соответствующие параметрам double, эффективно преобразуются в тип double.
- В противном случае все арифметические аргументы, соответствующие параметрам типа double, имеют тип float.
Обновить
Как указывает @nos, возможно, что вызываемая версия sqrt
взята из заголовка math.h
, а не из перегрузок из cmath
, если это так, и, вероятно, здесь есть определенная реализация, то мы может возвращаться к старому поведению в стиле C, если доступна только версия sqrt(double)
, что означает, что int будет неявно преобразован в double эм>.
Один из способов проверить это на gcc
и clang
— это использовать тип long для a
, который вместе с флагом -Wconversion
вызывает предупреждение о конверсии, потенциально изменяющей значение, на моей платформе, если у нас есть только sqrt(double)
. Действительно, если я включу math.h
вместо cmath
, мы сможем выдать это предупреждение. Хотя я не могу вызвать это поведение в clang, что, по-видимому, указывает на то, что это зависит от реализации.
person
Shafik Yaghmour
schedule
30.10.2013
int
неявно преобразуется вdouble
. Я думаю, что он рекомендует явно использоватьdouble
, чтобы избежать путаницы такого рода. - person BoBTFish   schedule 30.10.2013double
, передайте ей именноdouble
и ничего больше. - person Daniel Daranas   schedule 30.10.2013C++
поддержки - мы здесь в застойном состоянииC++03
:( - person BoBTFish   schedule 30.10.2013int
должны каким-то образом разрешаться вdouble
перегрузки, не вызывая ошибки неоднозначности перегрузки. - person AnT   schedule 30.10.2013