В самом конце выступления Скотта Шурра «Представляем constexpr
» на CppCon он спрашивает: «Есть ли способ отравить функцию»? Затем он объясняет, что это можно сделать (хотя и нестандартным способом):
- Ввод
throw
вconstexpr
функцию - Объявление неразрешенной
extern const char*
- Ссылаясь на нерешенные
extern
вthrow
Я чувствую, что здесь я немного не в себе, но мне любопытно:
- Что значит «отравить функцию»?
- В чем важность / полезность описываемой им техники?
constexpr
функции оценивался во время компиляции.constexpr
функцию можно использовать либо во время компиляции, либо во время выполнения. Так это способ заставить его использовать во время выполнения? Когда это полезно?constexpr
функция часто не является наиболее эффективной реализацией из-за ограничений, поэтому может не потребоваться ее оценка во время выполнения; или, может быть, это ошибка (как в его примере).Ответы:
В общем, это относится к тому, чтобы сделать функцию непригодной для использования, например, если вы хотите запретить использование динамического выделения в программе, вы можете «отравить»
malloc
функцию, чтобы ее нельзя было использовать.В видео он использует это более определенным образом, что становится ясно, если вы прочитаете слайд, который отображается, когда он говорит об отравлении функции, где говорится: «Способ принудительно использовать только время компиляции?»
Итак, он говорит об «отравлении» функции, чтобы сделать ее не вызываемой во время выполнения, поэтому ее можно вызывать только в постоянных выражениях. Метод состоит в том, чтобы иметь ветвь в функции, которая никогда не выполняется при вызове в контексте времени компиляции, и чтобы эта ветвь содержала что-то, что вызовет ошибку.
throw
Выражение допускается в функции constexpr, до тех пор , как она никогда не будет достигнуто во время компиляции вызовов функции (потому что вы не можете бросить исключение во время компиляции, это по сути своей динамической операции, как выделение памяти). Таким образом, выражение throw, которое ссылается на неопределенный символ, не будет использоваться во время вызовов во время компиляции (потому что это не может быть скомпилировано) и не может использоваться во время выполнения, потому что неопределенный символ вызывает ошибку компоновщика.Поскольку неопределенный символ не используется "odr" при вызовах функции во время компиляции, на практике компилятор не будет создавать ссылку на символ, поэтому нормально, что он не определен.
Это полезно? Он демонстрирует, как это сделать, не обязательно говоря, что это хорошая идея или широко полезная идея. Если по какой-то причине вам нужно это сделать, его методика может решить вашу проблему. Если вам это не нужно, вам не о чем беспокоиться.
Одна из причин, по которой это может быть полезно, - это когда версия некоторой операции во время компиляции не так эффективна, как могла бы быть. Существуют ограничения на типы выражений, разрешенные в функции constexpr (особенно в C ++ 11, некоторые ограничения были сняты в C ++ 14). Таким образом, у вас может быть две версии функции для выполнения вычислений: одна оптимальная, но использует выражения, которые недопустимы в функции constexpr, и одна, которая является допустимой функцией constexpr, но будет плохо работать, если будет вызвана во время выполнения. время. Вы можете отравить субоптимальный вариант, чтобы гарантировать, что он никогда не будет использоваться для вызовов времени выполнения, гарантируя, что более эффективная версия (не constexpr) будет использоваться для вызовов времени выполнения.
NB. Производительность функции constexpr, используемой во время компиляции, на самом деле не важна, потому что в любом случае у нее нет накладных расходов во время выполнения. Это может замедлить вашу компиляцию, заставив компилятор выполнять дополнительную работу, но не будет иметь никаких затрат на производительность во время выполнения.
источник
«Отравление» идентификатора означает, что любая ссылка на идентификатор после «отравления» является серьезной ошибкой компилятора. Этот метод может использоваться, например, для отмены поддержки (функция устарела, никогда не используйте ее!).
В GCC традиционно был Прагма для этого:
#pragma GCC poison
.источник