我最近一直在尝试使用现代C ++,这让我想知道是否可以使用仿函数将异步操作包装在类似函数的对象中。
我首先发现std :: async可以很容易地放在包装函数中,如下所示:
#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;
}
这给了我一个想法,将它包装在一个类中,如下所示:
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... );
}
};
我以为我可以使用此代码创建始终运行异步的全局函数。我的想法是它看起来像这样:
auto SubtractAsync = AsyncFunction( []( int a, int b ) { // does not work
return a - b;
} );
相反,我必须在模板括号中指定函数签名:
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;
}
我想这不是什么大不了的事,但它一直困扰着我。如果LaunchAsync()函数不要求我指定函数签名,那么为什么AsyncFunction类需要它呢?
对此有什么解决方法吗?
更新 解决了!正如T.C.所建议的那样,我能够用辅助函数来解决这个问题。完整代码如下:
#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;
}