Whenever we want some code to be executed in the background, we can simply start a new thread that executes this code. While this happens, we can do something else and then wait for the result. It's simple:
std::thread t {my_function, arg1, arg2, ...};
// do something else
t.join(); // wait for thread to finish
But then the inconvenience starts: t.join() does not give us the return value of my_function. In order to get at that, we need to write a function that calls my_function and stores its return value in some variable that is also accessible for the first thread in which we started the new thread. If such situations occur repeatedly, then this represents quite a bunch of boilerplate code we have to write again and again.
Since C++11, we have std::async which can do exactly this job for us and not only...