packaged_task

packaged_task creates a callable object out of a work function, which a thread then evaluates.

packaged_task differs from ::std::async because the work function is not called until packaged_task is passed to a thread.

Note that some or all of the arguments of the work function can be bound using ::std::bind:

#include <iostream>
#include <cmath>
#include <functional>

#include <future>
#include <thread>

unsigned do_work(unsigned x, unsigned y)
{
   return std::pow(x, y);
}

int main(int argc, char ** argv)
{
   {
   
   ::std::packaged_task < unsigned( unsigned, unsigned ) >
      task( do_work );
   
   auto
      future = task.get_future();
   
   ::std::jthread
      thread( ::std::move( task ), 2, 3 );
   
   future.wait();
   
   ::std::cout << future.get()         // 2 ** 3 = 8
               << ::std::endl
                  ;
   
   }
   
   {
   
   //
   // Note that arguments can also be bound using
   // ::std::bind:
   //
   
   ::std::packaged_task < unsigned(void) >
      task
         (
         ::std::bind( do_work, 2, 3 )
         )
         ;
   
   auto
      future = task.get_future();
   
   ::std::jthread
      thread( ::std::move( task ) );   // No arguments
   
   future.wait();
   
   ::std::cout << future.get()         // 2 ** 3 = 8
               << ::std::endl
                  ;
   
   }
   
   return 0;
}
Output:
8 8