As with std::shared_mutex, the standard library's own version of std::future is only half-baked. A much more complete and useful version of future is coming, perhaps in C++20, and there are very many third-party libraries that incorporate the best features of the upcoming version. The best of these libraries include boost::future and Facebook's folly::Future.
The major problem with std::future is that it requires "touching down" in a thread after each step of a potentially multi-step computation. Consider this pathological usage of std::future:
template<class T>
auto pf() {
std::promise<T> p;
std::future<T> f = p.get_future();
return std::make_pair(std::move(p), std::move(f));
}
void test() {
auto [p1, f1] = pf<Connection>();
auto [p2, f2] = pf<Data>();
auto [p3,...