В итоге я немного поковырялся в стандарте, доступных реализациях и вышло у меня следующее:
std::future<std::result_of_t<std::decay_t<Function>( std::decay_t<Args>... )>>
async( std::launch policy, Function&& f, Args&&... args )
{
using result_t = typename std::result_of<Function( Args... )>::type;
using packaged_t = typename std::packaged_task<result_t()>;
auto task = new packaged_t( std::bind( std::forward<Function>( f ), // (1)
std::forward<Args>( args )... ) );
auto res = task->get_future();
dispatch_async_f(
dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), task,
[]( void* task_ptr ) { // (2)
auto smart_task_ptr = std::unique_ptr<packaged_t>( // (3)
static_cast<packaged_t*>( task_ptr ) );
( *smart_task_ptr )();
} );
return res;
}
Довольно долго ломал голову на тему того, можно ли как-то обойтись без создания неуправляемого объекта типа
В итоге, для корректного удаления созданного объекта