Почему не отменено одно правило определения для C++17?
Ссылаясь на проект C++ N4713:
Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе с помощью odr, за исключением исключенного оператора (9.4.1); Диагностика не требуется. Определение может явным образом появиться в программе, оно может быть найдено в стандартной или определяемой пользователем библиотеке или (при необходимости) неявно определено (см. 15.1, 15.4 и 15.8). Встроенная функция или переменная должны быть определены в каждой единице перевода, в которой она используется odr, за пределами отброшенного оператора.
В версиях C++ до C++ 17 я могу обойти это ограничение, просто объявив свои функции inline
, C++ 17 добавляет ту же функцию для переменных.
Кроме того, мне кажется, что inline
- Ключевое слово не служит другой цели, кроме возможности игнорировать ODR.
Итак, почему все это правило не отменено для C++17? Я не вижу цели правила, которое можно отключить.
4 ответа
"Отключение" ODR с помощью inline
не является бесплатным: определение inline
Сущность должна присутствовать в каждой единице перевода. Обратите внимание, что это подразумевает, что любое изменение в его определении вызывает перекомпиляцию каждого модуля компиляции, который его использует. Это было бы особенно неприятно, когда функция является частью некоторой библиотеки, от которой зависят многие / большие проекты.
не-inline
функции, с другой стороны, живут только в одном модуле компиляции и на них ссылаются через какой-то символ компоновщиком, когда это необходимо в другом месте. Соблюдение ODR гарантирует, что символ не является двусмысленным.
inline
это опасно и дорого.
Это дорого, потому что каждая единица компиляции, которая использует что-то, теперь зависит от определения вещи. Так поменять тело? Перекомпилируйте каждого пользователя.
Это опасно, потому что если два inline
определения не согласны, ваша программа IF-NDR (плохо сформирована, диагностика не требуется).
Без inline
два определения вызывают плохо сформированную программу, но компилятор должен предоставить диагностику; обычно серьезная ошибка.
inline
отключает это чрезвычайно полезное предупреждение.
Если бы каждый компилятор был способен преобразовывать IF-NDR разных inline
определения в диагностическое сообщение об ошибке у вас будет больше случаев. Пока это оказывается трудным и / или не реализованным, inline
это "активировать небезопасный режим!" вариант. Установка по умолчанию будет контрпродуктивной.
Компромисс в том, что вам нужно определение inline
функция везде, где он используется. Если вы хотите этого, просто поместите всю программу в один файл.cpp.
ODR - это то, что вам нужно для отдельной компиляции, и это все еще полезно.
Из контекста:
Одно и только одно определение каждой не встроенной функции или переменной, которая используется в odr (см. Ниже), должно присутствовать во всей программе (включая любые стандартные и пользовательские библиотеки). Компилятор не обязан диагностировать это нарушение, но поведение программы, которая его нарушает, не определено.
Объявление функции как inline
не "игнорирует" ODR, но заставляет каждый внешний вид функции быть своей собственной сущностью, которая нуждается в определении в каждой единице перевода, где она используется. Небольшая, но значительная разница. ODR по-прежнему должен иметь отдельные переводческие единицы.