std::launch::deferred means "don't run it until there is .wait() or .get() ."
Like you never .get() or .wait() ed, it never started.
void has nothing to do with it.
For std::launch::async , the standard states that the returned future destructor ( ~future ) will be blocked until the task completes (i.e. it has an implicit .wait() ). This violates the MSVC specifically because they disagree with this design decision and they are fighting for a change in the standard: in practice, this means that you cannot generally rely on any behavior from std::launch::async returned by future , if you want for future code.
Without the implicit wait in ~future it would be undefined if it would actually call the function when main exits. It would happen or not. Perhaps you could call UB while still having active threads at the end of main .
You may wonder what deferred uses: you can use it to compute a queue for lazy evaluation.
source share