Подтвердить что ты не робот

С++ используют шаблоны, чтобы избежать компилятора от проверки логического

Скажем, у меня есть функция:

template <bool stuff>
inline void doSomething() {
    if(stuff) {
        cout << "Hello" << endl;
    }
    else {
        cout << "Goodbye" << endl;
    }
}

И я называю это следующим образом:

doSomething<true>();
doSomething<false>();

Он выкинул бы:

Hello
Goodbye

Что мне действительно интересно, так ли компилятор полностью оптимизирует это? Когда я вызываю функцию templated с true, создаст ли она функцию, которая просто выведет "Hello" и избежит оператора if и кода "Goodbye"?

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

4b9b3361

Ответ 1

Отказ от ответственности: никто не может ничего гарантировать.

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

Поскольку ваши "истинные" и "ложные" являются CONSTANTS, вы однозначно создаете явно очевидную мертвую ветвь в каждом классе, и компилятор должен ее оптимизировать.

Другими словами, если ваш компилятор не может его оптимизировать, это обсуждение является наименьшей из ваших проблем.

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

Короче, используйте его. Любой современный оптимизирующий компилятор оптимизирует его, потому что он слишком вопиющий из мертвой ветки, чтобы игнорировать. Если он не оптимизирован, я бы сменил компиляторы прямо сейчас.

Если вы пишете какой-либо критически важный для вас код, вы ДОЛЖНЫ полагаться, по крайней мере, до некоторой степени, на оптимизацию компилятора, и это один из самых простых.

Ответ 2

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

template <bool stuff>
inline void doSomething();

template<>
inline void doSomething<true>() {
    cout << "Hello" << endl;
}

template<>
inline void doSomething<false>() {
    cout << "Goodbye" << endl;
}

Но "оптимизация" на самом деле не правильное слово для использования, поскольку это может фактически ухудшить производительность. Это только оптимизация, если она действительно приносит пользу вашей производительности кода.

Ответ 3

Действительно, он действительно создает две функции, но

преждевременная оптимизация - это корень всех злых

особенно если вы меняете структуру кода из-за простой инструкции if. Я сомневаюсь, что это повлияет на производительность. Кроме того, логическое значение должно быть статическим, это означает, что вы не можете выполнить проверку времени выполнения и передать ее функции. Как должен линкер знать, какую функцию вызывать? В этом случае вам придется вручную оценить его и вызвать соответствующую функцию самостоятельно.

Ответ 4

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

Тем не менее, стоит отметить, что компилятор должен проверить правильность обоих ветвей, даже если он использует только одну ветвь. Это часто проявляется, например, при использовании немного разных алгоритмов для итераторов произвольного доступа и других итераторов. Условие будет зависеть от типа-признака, и одна из ветвей может не скомпилироваться в зависимости от операций, проверенных по признакам. Комитет обсудил вопрос об отключении этой проверки под термином static, хотя, хотя консенсуса пока нет, о том, как функции будут выглядеть точно (если они будут добавлены).

Ответ 5

Если вы правильно поняли, что хотите (по существу), вы получаете "две" функции, оптимизированные для истинного или ложного ввода, чтобы они не нуждались в проверке этого флага?

Помимо любой тривиальной оптимизации, которая может дать (я против преждевременной отимизации - я верю в ремонтопригодность перед измерением перед оптимизацией), я бы сказал, почему бы не реорганизовать вашу функцию на фактически две функции? Если у них есть общий код, тогда этот код также может быть реорганизован. Однако, если требование таково, что рефакторинг не является оптимальным, я заменил бы это на #define рефакторинг.