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
c ++ 11 g ++ mingw


source to share


No one has answered this question yet

Check out similar questions:

514
Are the days of going const std :: string & as a parameter passing by?
366
Pretty printable STL STL containers
220
to_string is not a member of std, says g ++ (mingw)
8
std :: async member function call
6
using std :: async with template functions
five
std :: atomic_is_lock_free (shared_ptr <T> *) does not compile
4
Why can't std :: bind resolve function overloads with multiple arguments?
2
cout is not a member of std, and other C ++ related questions
0
Error trying to use pthread on Ubuntu
-1
How to return a static const int std :: array from a method?



All Articles
Loading...
X
Show
Funny
Dev
Pics