Что значит "отравить функцию" на С++?

В самом конце Скотта Шурра говорят "Представляя constexpr" в CppCon, он спрашивает: "Есть ли способ отравить функцию"? Затем он объясняет, что это можно сделать (хотя и нестандартным образом):

  • Ввод throw в функцию constexpr
  • Объявление неразрешенного extern const char*
  • Ссылка на неразрешенный extern в throw

Я чувствую, что я немного из глубины здесь, но мне любопытно:

  • Что значит "отравить функцию"?
  • Какова важность/полезность метода, который он излагает?

Ответ 1

В целом это относится к тому, чтобы сделать функцию непригодной для использования, например. если вы хотите запретить использование динамического выделения в программе, вы можете "отравить" функцию malloc, чтобы ее нельзя было использовать.

В видеоролике он использует его более определенным образом, что ясно, если вы читаете слайд, который отображается, когда он говорит об отравлении функции, в которой говорится: "Только способ принудительного компиляции"?

Таким образом, он говорит о "отравлении" функции, чтобы сделать ее невоспроизводимой во время выполнения, поэтому она может быть выведена только в постоянных выражениях. Метод состоит в том, чтобы иметь ветвь в функции, которая никогда не принимается при вызове в контексте времени компиляции, и чтобы эта ветвь содержала что-то, что вызовет ошибку.

A throw выражение допускается в функции constexpr, если оно никогда не достигается во время вызова функции времени компиляции (поскольку вы не можете генерировать исключение во время компиляции, это динамически динамическая операция, как выделение памяти). Таким образом, выражение throw, которое ссылается на символ undefined, не будет использоваться во время вызовов времени компиляции (поскольку это не скомпилировалось) и не может использоваться во время выполнения, потому что символ undefined вызывает ошибку компоновщика.

Поскольку символ undefined не используется "odr-used" во время вызова функции компиляции, на практике компилятор не будет создавать ссылку на символ, поэтому он хорошо, что он undefined.

Это полезно? Он демонстрирует, как это сделать, не обязательно говоря это хорошая идея или широко полезный. Если у вас есть необходимость сделать это по какой-то причине, его техника может решить вашу проблему. Если вам это не нужно, вам не нужно беспокоиться об этом.

Одна из причин, по которой это может быть полезно, - это то, что версия какой-либо операции с компиляцией не так эффективна, как могла бы быть. Существуют ограничения на типы выражений, разрешенных в функции constexpr (особенно в С++ 11, некоторые ограничения были удалены в С++ 14). Таким образом, у вас может быть две версии функции для выполнения вычисления, которая является оптимальной, но использует выражения, которые не разрешены в функции constexpr, и та, которая является допустимой функцией constexpr, но будет работать плохо, если вызывается при запуске, время. Вы можете отравить субоптимальный, чтобы гарантировать, что он никогда не используется для вызовов во время выполнения, гарантируя, что для вызовов во время выполнения используется более эффективная версия (неконференция).

N.B. Производительность функции constexpr, используемой во время компиляции, на самом деле не очень важна, поскольку в любом случае она не имеет лишних расходов во время выполнения. Это может замедлить вашу компиляцию, заставив компилятор выполнять дополнительную работу, но у нее не будет затрат на производительность во время выполнения.

Ответ 2

"Отравление" идентификатор означает, что любая ссылка на идентификатор после "отравления" представляет собой ошибку жесткого компилятора. Этот метод может использоваться, например, для жесткой устаревания (функция IS устарела, никогда не используйте ее!).

В GCC традиционно для этого была прагма: #pragma GCC poison.