Рассмотрим следующий код:
#include <iostream>
#include <math.h>
double log(double) { return 42; }
int main() {
std::cout << log(1) << std::endl;
}
При сборке отладочной версии печатает все используемые компиляторы (msvc, gcc, clang) 42
,
Но когда я пытаюсь собрать (и запустить) в режиме релиза, я получил:
error C2169: 'log' : intrinsic function, cannot be defined
;42
для gcc;0
для лязга.Почему результаты выпуска / отладки отличаются для одного и того же компилятора?
Почему были получены разные результаты для разных компиляторов в режиме релиза?
Вы определяете функцию, которая уже объявлена в <math.h>
с внешней связью.
Стандарт С11, § 7.12.6.7:
#include <math.h> double log(double x);
§7.1.2:
[Extern.names] / 3:Любое объявление библиотечной функции должно иметь внешнюю связь.
Каждое имя из библиотеки Standard C объявлено с внешней связью
зарезервирован для реализации для использования в качестве имени с внешней связью «C», оба в пространстве именstd
и в глобальном пространстве имен.
Согласно [reserved.names] / 2 поведение не определено; Таким образом, реализация может делать то, что она хочет, включая выдачу бессмысленных сообщений об ошибках.
Итак, согласно стандарту (17.6.1.2.4):
Однако в стандартной библиотеке C ++ объявления (за исключением имен, которые определены как макросы в C) находятся в пределах пространства имен (3.3.6) пространства имен std. Не определено, будут ли эти имена сначала объявлены в глобальной области пространства имен, а затем введены в пространство имен std с помощью явных объявлений using (7.3.3).
Не указано, является ли log()
в math.h
(действительно cmath
) находится в пространстве имен std
или нет. Если это так (как для libstdc ++ для gcc), то вызов log(1)
довольно просто вызывает вашу функцию, потому что другая названа std::log()
, Но для Clang, по-видимому, это помещает его в глобальное пространство имен. Так как есть
template <typename T> double log(T x);
Это будет предпочтительнее вашего, так как вы передаете int, поэтому в clang он будет вызывать его. (Я не могу проверить это сейчас, так как я не могу получить доступ к coliru и у меня не установлен clang, но это лучшее предположение).