Wrapping std :: async in a functor

I've been experimenting with modern C ++ lately, and it made me wonder if I could use a functor to wrap an asynchronous operation in a functionally similar object.

I first found that std :: async can be easily wrapped in a wrapper function like:

#include <iostream>
#include <functional>
#include <future>

template< typename Fn, typename... Args >
std::future< typename std::result_of< Fn( Args... ) >::type >
LaunchAsync( Fn&& fn, Args&&... args )
{
    return std::async( std::launch::async, fn, args... );
} 

using namespace std;

int main()
{
    auto addResult = LaunchAsync( []( int a, int b ) { return a + b; }, 1, 2 );   
    cout << addResult.get() << endl;
    return 0;
}

      

This gave me the idea to wrap it in a class instead, like this:

template< typename Fn >
class AsyncFunction
{
    Fn _fn;
public:
    AsyncFunction( Fn fn ) : _fn( fn ) { }
    template< typename... Args >
    std::future< typename std::result_of< Fn( Args... ) >::type >
    operator()( Args&&... args )
    {
        return std::async( std::launch::async, _fn, args... );
    }
};

      

I thought I could use this code to create global functions that always run async. I thought it would look like this:

auto SubtractAsync = AsyncFunction( []( int a, int b ) { // does not work
    return a - b;
} );

      

Instead, I have to specify the function signature within the template brackets:

auto SubtractAsync = AsyncFunction< std::function< int( int, int ) > >( []( int a, int b ) {
    return a - b;
} );

int main()
{
    auto subtractResult = SubtractAsync( 7, 3 ); // works
    cout << subtractResult.get() << endl;
    return 0;
}

      

I guess this is not very much, but it worries me. If the LaunchAsync () function does not require a function signature, then why does the AsyncFunction require one?

Is there any work around for this?

UPDATE: Solved! As TC suggested, I was able to solve this with a helper function. Full code below:

#include <functional>
#include <future>
#include <iostream>

template< typename Fn >
class AsyncFunctor
{
    Fn _fn;
public:
    AsyncFunctor( Fn&& fn ) : _fn( fn ) { }

    template< typename... Args >
    std::future< typename std::result_of< Fn( Args... ) >::type >
    operator()( Args&&... args ) const
    {
        return std::async( std::launch::async, _fn, args... );
    }
};

template< typename Fn > // helper function to handle template parameters
AsyncFunctor< Fn > AsyncFunction( Fn&& fn )
{
    return AsyncFunctor< Fn >( std::move( fn ) );
}

auto AddAsync = AsyncFunction( []( auto a, auto b) { // it works!
    return a + b;
} );

using namespace std;

int main()
{
    auto result = AddAsync( 3, 4 );
    cout << result.get() << endl;
    return 0;
}

      

+3


source to share





All Articles