I've successfully used std::async in the past, but lately in checking the fidelity of some new code, I've run into an oddity that has me stumped. I'm sure there should be a simple explanation and a proper solution, but I can't find a discussion of it anywhere.

The following bit of minimal code illustrates the matter:

```
#include <functional>
#include <thread>
#include <future>
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>

int main(int argc, char **argv) {

    for (size_t delay = 0; delay < 2; delay++) {
        std::vector<std::future<std::string>> futures;
        for (size_t i = 0; i < 10; i++) {

            auto fut = std::async(std::launch::async, 
                [&i] () -> std::string
                {
                    std::stringstream ss;
                    ss << "work on number " << i << " " << std::this_thread::get_id();
                    return ss.str();
                }
            );
            if (delay == 1) {
                std::this_thread::sleep_for (std::chrono::milliseconds(10));
            }
            futures.push_back(std::move(fut));
        }

        // do not proceed until all threads are done
        std::for_each(futures.begin(), futures.end(), [](std::future<std::string>& fut) 
            {
                auto codeconf = fut.get();
                std::cout << codeconf << std::endl;
            }
        );
        std::cout << std::endl;
    }
}

```

Without the delay (i.e. first time through the outer loop), some loop-elements (integers) get missed and don't get assigned to a thread/task, while other loop elements get assigned to more than one thread. The loop also runs beyond it's limits:  

work on number 4 139770383861504  

work on number 4 139770375468800  

work on number 4 139770367076096  

work on number 6 139770358683392  

work on number 5 139770350290688  

work on number 6 139770341897984  

work on number 7 139770333505280  

work on number 8 139770325112576  

work on number 10 139770248296192  

work on number 10 139770239903488  

Including a minor delay (10 ms) allows loop increments and threads to correspond as expected and intended -- i.e. a one-to-one correspondence between loop increment and task/thread (the order of completion doesn't matter, of course, even though they are in order here):  

work on number 0 139770239903488  

work on number 1 139770248296192  

work on number 2 139770325112576  

work on number 3 139770333505280  

work on number 4 139770383861504  

work on number 5 139770375468800  

work on number 6 139770367076096  

work on number 7 139770358683392  

work on number 8 139770350290688  

work on number 9 139770341897984  

My understanding is that the async launch policy should just pick up the integer that corresponds to the loop iteration, feed it into the lambda function, and execute it on an independent task/thread; when it starts (which is essentially immediate) and when it ends doesn't really matter to the functioning and logic of the loop. But here, without a delay, "async" seems to quite literally to describe the relationship between loop iterations and tasks.

Is the tiny delay workaround legitimate? What am I failing to understand?