Основанный на SFINAE ifdef - PullRequest
       10

Основанный на SFINAE ifdef

0 голосов
/ 02 октября 2019

Общая информация

Безопасно использовать #ifdef на тот случай, если мы хотим, чтобы компилятор оптимизировал некоторую часть кода, как показано ниже.

#ifdef LOG
mtmd();
#endif

Следовательно, если LOG не определено во время компиляции, во время выполнения не будет никаких накладных расходов.

Вопрос

Мне интересно реализовать тот же механизм с использованием SFINAE. Упрощенная версия кода показана ниже.

template <bool cond, typename std::enable_if<cond>::type* = nullptr>
inline void log(void (*func)(int, int), int in, int out) {
 (*func)(in, out);
}

template <bool cond, typename std::enable_if<!cond>::type* = nullptr>
inline void log(void (*func)(int, int), int in, int out) {}

Я могу использовать его в следующей форме.

void mtmd(int x, int y) { /* Do something */}

int main() {
  constexpr cond = true; // or flase
  int x, y;
  log<cond>(&mtmd, x, y);
}

Вопрос в том, когда cond равно false будут ли какие-либо издержки, или компилятор все оптимизирует, так как функция log равна inline?

1 Ответ

1 голос
/ 03 октября 2019

В общем, с inline никогда нельзя быть уверенным, будет ли он работать, поскольку это скорее подсказка для компилятора, чем реальное требование (в случае, конечно, в отношении связывания и переменных этодовольно строго). Конечно, весьма вероятно, что компилятор оптимизирует удаление ненужных вызовов на log, но это не требуется стандартом. Как сказано в cpp reference

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

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

...