In a previous unnamed programming post I've mentioned about how the comma operator can be of use to evade naming temporaries.

I've come to realize that can also be used for joining async tasks:

#include <mutex>
#include <future>
#include <iostream>

int main() {
    using namespace std;

    mutex m;

    async(launch::async, [&m] { lock_guard{m}, cout << "hello"; }),
    async(launch::async, [&m] { lock_guard{m}, cout << "world"; });

If .get() is not called on the future returned by std::async, it's well known that the future's destructor will block until the task is finished. In the above example two temporary futures are created and they're "joined" with a comma operator. Both are executed in parallel and nothing afterwards will execute until both temporaries cease to exist, which means until both tasks are finished.

Notice how there's just one named variable in this code, there was no need to name lock_guards nor futures. 😂