Почему std::необязательный оператор * не имеет утверждения режима отладки для has_value()?

#c #visual-studio #stdoptional

#c #visual-studio #stdoptional

Вопрос:

Я прекрасно понимаю, что из соображений производительности operator* in std::optional не выполняет никаких проверок на предмет фактического существования содержащегося значения. Однако в режиме отладки соображения производительности не должны иметь значения, и для меня было бы очень разумно, чтобы какое-то утверждение было сделано в режиме отладки.

Похоже, в Visual Studio нет такого утверждения (хотя я не уверен в других компиляторах).

Мой вопрос: есть ли какая-либо фундаментальная причина, по которой компилятор НЕ будет делать такое утверждение в режиме отладки или это просто недостающая функция?

Комментарии:

1. Чем больше ваша отладочная сборка отличается от выпуска, тем менее полезной она становится.

Ответ №1:

Есть ли какая-либо фундаментальная причина, по которой компилятор НЕ будет делать такое утверждение в режиме отладки или это просто недостающая функция?

Нарушения ODR. std::optional является шаблоном класса и, следовательно, реализован в заголовке. Различное поведение кода внутри заголовка для разных символов препроцессора настолько опасно, насколько это возможно. Рассмотрим этот пример (не тестировался, вы поймете суть):

 clang   -DNDEBUG usesOptionalOfInt.cpp -shared -c -o myLib.so
clang   alsoUsesOptionalOfInt.cpp main.cpp -lmyLib -o ./ub-please
 

Там вы идете с неопределенным поведением. Обратите внимание, что очень маловероятно, что разница в std::optional::operator* действительно нанесет какой-либо вред в этом примере, но все же — вы хотите избежать этих ситуаций.

Комментарии:

1. Но если вы хотите использовать STL поверх статических библиотек, вы все равно должны создавать их с теми же параметрами компилятора, иначе ничего не будет работать! std::vector уже полон утверждений в Visual Studio (см. _STL_VERIFY() в разделе различные _ITERATOR_DEBUG_LEVELs ). В чем разница между этими утверждениями и тем, которое предлагает @FranciscoMartinez ?

2. Это зарезервированные имена — клиентскому коду не разрешается связываться с ними. Из cppreference : «идентификаторы, которые начинаются с символа подчеркивания, за которым следует заглавная буква, зарезервированы». Это основное отличие, например NDEBUG , от макроса.