boost::async() is now std::async() in C++11, and it returns a (blocking) future. You can compel it to start a new thread but it does not provide its result asynchronously (it can't, because C++11 has no standard event loop nor support for coroutines).
You can sort-of emulate C# async in effect, by having a thread which composes tasks using std::async(), blocks on the futures it obtains, and then when finished posts its result to the program's event loop (in glib, say, using g_idle_add()). With this scheme you cannot eliminate at least one blocking thread (and you may end up with more), but at least the blocking thread will be scheduled out by the OS's scheduler while it is blocking.
A more refined development of this for C/C++ is to run a thread pool set with a maximum number of threads approximating to the number of cores available, where tasks assigned to the pool increment the maximum thread count when about to block so as to keep cores active (decrementing again when coming out of the block) and deliver the composed result to the program's event loop. It avoids "callback hell" (you only have one callback), but this still puts the onus on the programmer to manage the thread count correctly. C# async hides all that.