lundi 29 juin 2015

Wrapping std::async in a functor

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

I first found that std::async can be easily placed in a wrapper function, like so:

#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;
}

That gave me an idea to instead wrap it in a class, 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. My thinking was that 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 in 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 it isn't really a big deal, but it's been bothering me. If the LaunchAsync() function doesn't require me to specify the function signature, then why does the AsyncFunction class require it?

Is there any kind of work-around to this?

Aucun commentaire:

Enregistrer un commentaire