Использование std::exchange
:
if (static bool do_once = true; std::exchange(do_once, false))
Вы можете сделать его короче, изменив значение истины:
if (static bool do_once; !std::exchange(do_once, true))
Но если вы часто этим пользуетесь, не думайте, а вместо этого создайте обертку:
struct Once {
bool b = true;
explicit operator bool() { return std::exchange(b, false); }
};
И используйте это как:
if (static Once once; once)
Предполагается, что на переменную нельзя ссылаться за пределами условия, поэтому ее имя не приносит нам большой выгоды. Черпая вдохновение из других языков, таких как Python , которые придают особое значение идентификатору _
, мы можем написать:
if (static Once _; _)
Дальнейшие улучшения: воспользуйтесь разделом BSS (@Deduplicator), избегайте записи в память, когда мы уже запустили (@ShadowRanger), и дайте подсказку по прогнозированию ветвления, если вы собираетесь тестировать много раз (например, как в вопрос):
// GCC, Clang, icc only; use [[likely]] in C++20 instead
#define likely(x) __builtin_expect(!!(x), 1)
struct Once {
bool b = false;
explicit operator bool()
{
if (likely(b))
return false;
b = true;
return true;
}
};