Почему это не «неопределенная внешняя переменная»? привести к ошибке компоновщика в C ++ 17?

Я скомпилировал и запустил следующую программу в компиляторе C ++ 17 (Coliru). В программе я объявленный extern переменная, но не определил Это. Тем не менее, компилятор не дает ошибка компоновщика.

#include <iostream>

extern int i; // Only declaration

int func()
{
if constexpr (true)
return 0;
else if (i)
return i;
else
return -1;
}

int main()
{
int ret = func();
std::cout<<"Ret : "<<ret<<std::endl;
}

Почему компилятор не выдает ошибку компоновщика?

38

Решение

Потому что переменная не используется odr. У тебя есть constexpr if там, который всегда отбрасывает ветку, которая могла бы его использовать.

Одна из точек constexpr if в том, что отброшенная ветвь не должна даже компилироваться, только должна быть правильно сформирована. Вот как мы можем размещать вызовы несуществующих функций-членов в отброшенной ветви.

58

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

В вашем случае переменная используется только в отброшенных выражениях. Тем не менее, даже если мы игнорируем этот факт, спецификация языка C ++ по-прежнему прямо заявляет, что Диагностика не требуется за отсутствующие определения

3.2 Правило одного определения

4 Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе с помощью odr, за исключением исключенного оператора (6.4.1); Диагностика не требуется.

Спецификация языка понимает, что оптимизирующий компилятор может быть достаточно умен, чтобы исключить любое использование переменной odr. В этом случае было бы чрезмерным и ненужным требовать, чтобы реализация выявляла и сообщала о потенциальных нарушениях ODR.

41

Поскольку компилятор выдает ошибки компилятора, линкер приведет к ошибкам компоновщика …

Нет, серьезно:

if constexpr (true)

всегда имеет значение true, поэтому компилятор игнорирует остальную часть предложения if, потому что оно никогда не достигается. Так i никогда не используется на самом деле.

9

На это уже ответили, но если вам интересно, cppreference.com имеет именно этот пример для constexpr если:

Constexpr If

Утверждение, которое начинается с if constexpr известен как constexpr if заявление.

В выражении constexpr if значение состояние должен быть контекстно преобразован постоянное выражение типа bool. Если значение истинно, то Заявление-ложь отбрасывается (если имеется), в противном случае, заявление-правда отбрасывается
[…] Отклоненное утверждение может УСО использование переменная, которая не определена:

extern int x; // no definition of x required
int f() {
if constexpr (true)
return 0;
else if (x)
return x;
else
return -x;
}
1
По вопросам рекламы [email protected]