Почему не отменено одно правило определения для 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 по-прежнему должен иметь отдельные переводческие единицы.

Другие вопросы по тегам