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;
}
source to share
No one has answered this question yet
Check out similar questions: