1. ホーム
  2. c++

[解決済み] 一発勝負の'if'を書くための最もエレガントな方法

2022-06-01 10:49:30

質問

C++ 17以降では if ブロックを書くことができます。

#include <iostream>
int main() {
    for (unsigned i = 0; i < 10; ++i) {

        if (static bool do_once = true; do_once) { // Enter only once
            std::cout << "hello one-shot" << std::endl;
            // Possibly much more code
            do_once = false;
        }

    }
}

考えすぎかもしれませんし、他に解決する方法があることも承知していますが、それでも、このように何とか書くことは可能でしょうか。 do_once = false は必要ないでしょうか?

if (DO_ONCE) {
    // Do stuff
}

ヘルパー関数を do_once() を含む static bool do_once を含んでいますが、その同じ関数を別の場所で使いたいとしたらどうでしょうか?このような場合には #define ? そうでないことを祈ります。

どのように解決するのですか?

使用方法 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;
    }
};