一次性写“ if”的最优雅方式 [英] Most elegant way to write a one-shot 'if'
问题描述
自C ++ 17起,我们就可以编写一个 if
块,该块将完全像这样执行一次:
Since C++ 17 one can write an if
block that will get executed exactly once like this:
#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
结尾?
I know I might be overthinking this, and there are other ways to solve this, but still - is it possible to write this somehow like this, so there is no need of the do_once = false
at the end?
if (DO_ONCE) {
// Do stuff
}
我在考虑一个辅助函数, do_once()
,其中包含静态布尔do_once
,但是如果我想在不同的地方使用相同的功能怎么办?也许这是 #define
的时间和地点吗?
I'm thinking a helper function, do_once()
, containing the static bool do_once
, but what if I wanted to use that same function in different places? Might this be the time and place for a #define
? I hope not.
推荐答案
使用 std :: exchange
:
if (static bool do_once = true; std::exchange(do_once, false))
< hr>
您可以缩短反转真值的时间:
You can make it shorter reversing the truth value:
if (static bool do_once; !std::exchange(do_once, true))
但是如果您使用的是很多,不要看中并创建一个包装器:
But if you are using this a lot, don't be fancy and create a wrapper instead:
struct Once {
bool b = true;
explicit operator bool() { return std::exchange(b, false); }
};
并像这样使用它:
if (static Once once; once)
不应假定变量在条件之外被引用,因此名称并不能给我们带来多少好处。从其他语言中汲取灵感,例如 Python 赋予 _
标识符特殊的含义,我们可以这样写:
The variable is not supposed to be referenced outside the condition, so the name does not buy us much. Taking inspiration from other languages like Python which give a special meaning to the _
identifier, we may write:
if (static Once _; _)
进一步的改进:利用BSS部分(@Deduplicator),避免在我们已经运行时写入内存(@ShadowRanger),并在要进行多次测试时给出分支预测提示(例如,如问题所示):
Further improvements: take advantage of the BSS section (@Deduplicator), avoid the memory write when we have already run (@ShadowRanger), and give a branch prediction hint if you are going to test many times (e.g. like in the question):
// 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;
}
};
这篇关于一次性写“ if”的最优雅方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!