Как использовать вероятный / маловероятный атрибут C++20 в операторе if-else
Этот вопрос о C++20 [[likely]]
/[[unlikely]]
особенность, а не определяемые компилятором макросы.
В этих документах ( cppreference) приведен только пример их применения к оператору switch-case. Этот пример случая переключения прекрасно компилируется с моим компилятором (g++-7.2), поэтому я предполагаю, что компилятор реализовал эту функцию, хотя она еще официально не представлена в текущих стандартах C++.
Но когда я использую их так: if (condition) [[likely]] { ... } else { ... }
Я получил предупреждение:
msgstr "предупреждение: атрибуты в начале оператора игнорируются [-Wattributes]".
Так как же мне использовать эти атрибуты в операторе if-else?
2 ответа
Основываясь на примере из отчета Jacksonville'18 ISO C++, синтаксис правильный, но кажется, что он еще не реализован:
if (a>b) [[likely]] {
На сегодняшний день cppreference утверждает, что, например,likely
(курсив мой):
Применяется к оператору, чтобы позволить компилятору оптимизировать для случая, когда пути выполнения, включающие этот оператор, более вероятны, чем любой альтернативный путь выполнения, который не включает такой оператор.
Это говорит о том, что место для размещения атрибута находится в наиболее вероятном утверждении, то есть:
if (condition) { [[likely]] ... } else { ... }
Этот синтаксис принят, например, Visual Studio 2019 16.7.0 при компиляции с /std:c++latest
.
Так как же мне использовать эти атрибуты в операторе if-else?
Точно так же, как вы делаете, ваш синтаксис правильный в соответствии с примером, приведенным в проекте стандарта (упрощенно, чтобы показывать только соответствующие биты):
int f(int n) {
if (n > 5) [[unlikely]] {
g(0);
return n * 2 + 1;
}
return 3;
}
Но вы должны понимать, что эта функция является относительно новой, поэтому в реализациях могут быть только заполнители, позволяющие вам устанавливать атрибуты. Это видно из вашего предупреждающего сообщения.
Вы также должны понимать, что, если определенные формулировки между последним проектом и конечным продуктом не изменятся, даже совместимые реализации могут игнорировать эти атрибуты. Это очень много предложений для компилятора, как inline
в C. Из этого последнего проекта n4762
(во время этого ответа и с моим акцентом):
Примечание. Использование вероятного атрибута предназначено для того, чтобы позволить реализациям оптимизировать ситуацию, когда пути выполнения, включая его, произвольно более вероятны, чем любой альтернативный путь выполнения, который не включает такой атрибут в операторе или метке.
Обратите внимание на слово "разрешить", а не "принудительно", "требовать" или "мандат".