Встроенная (встроенная?) Функция перегрузки

Рассмотрим следующий код:

#include <iostream>
#include <math.h>

double log(double) { return 42; }

int main() {
std::cout << log(1) << std::endl;
}

При сборке отладочной версии печатает все используемые компиляторы (msvc, gcc, clang) 42,

Но когда я пытаюсь собрать (и запустить) в режиме релиза, я получил:

  • ошибка компиляции в msvc: error C2169: 'log' : intrinsic function, cannot be defined;
  • печать 42 для gcc;
  • печать 0 для лязга.

Почему результаты выпуска / отладки отличаются для одного и того же компилятора?

Почему были получены разные результаты для разных компиляторов в режиме релиза?

4

Решение

Вы определяете функцию, которая уже объявлена ​​в <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 поведение не определено; Таким образом, реализация может делать то, что она хочет, включая выдачу бессмысленных сообщений об ошибках.

5

Другие решения

Итак, согласно стандарту (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, но это лучшее предположение).

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector