Very interesting article! Your last code example was interesting:
```
if (Guard g(&lock); !--remaining) {
signal(&done);
}
```
I wondered about the lifetime of that temporary guard object; does it
last throughout the body of the if statement, or does it only last
until the if condition is evaluated? Today I learned that it's the
former (as intended)... but only if that temporary is *named*, as it
is above. That is, for example, the following doesn't behave as
desired:
```
if (Guard{&lock}; !--remaining) {
signal(&done);
}
```
In fact it appears that the guard is destructed even before the decrement.
Indeed, forgetting to name std::scoped_lock, and similar, is one of the
most common mistakes — I've done it myself — and may go unnoticed for a
long time, at least without TSan:
https://en.cppreference.com/w/cpp/thread/scoped_lock#Notes
> A common beginner error is to "forget" to give a scoped_lock variable a
> name
Since they couldn't fix this gotcha in the standard library, I knew I
wouldn't be able to fix it in my implementation, either. Along these
lines, before writing this article I didn't know the initialized-if scope
extended into the "else" part as well:
https://en.cppreference.com/w/cpp/language/if#if_statements_with_initializer
I've yet to see an instance of else-side use in the wild, and I only came
across this note while double checking my examples.