以下代码无法编译:
template< typename Fn >
bool templateFunctionOne( Fn&& fn )
{
int v = 5;
return fn( v );
}
template < typename Fn >
bool templateFunctionTwo( Fn&& fn )
{
std::future< bool > tk( std::async( std::launch::async,
&templateFunctionOne< Fn >,
std::forward<Fn>(fn ) ) );
return tk.get();
}
bool printThis( int value )
{
cout << value << endl;
return true;
}
int main()
{
auto func = std::bind( &printThis, std::placeholders::_1 );
return templateFunctionTwo( func );
}
编译时出现以下错误:
我简化了上面的内容,但仍然无法使用相同的错误消息进行编译:
template< typename Fn >
bool templateFunctionOne( Fn&& fn )
{
return fn();
}
template < typename Fn >
bool templateFunctionTwo( Fn&& fn )
{
std::future< bool > tk( std::async( std::launch::async,
&templateFunctionOne< Fn >,
std::forward<Fn>(fn ) ) );
return tk.get();
}
bool printThis()
{
return true;
}
int main()
{
auto func = std::bind( &printThis );
return templateFunctionTwo( func );
}
由于现在函数
printThis
不需要传递任何参数,因此不需要绑定(bind)调用。并且当按如下方式更改主调用时,它可以正常编译: int main()
{
return templateFunctionTwo( &printThis );
}
有人可以帮忙解释一下吗?在传递函数指针而不需要引用时不使用
std::ref
来包装参数时,我已经看到了相同类型的错误,但这似乎是其他事情(或没有),我在这里遗漏了什么? 最佳答案
auto func = std::bind( &printThis );
return templateFunctionTwo( func );
func
是Lvalue,因此当Lvalue传递到templateFunctionTwo
时,Fn
被推导为Fn&
(由于转发引用)。线下
&templateFunctionOne< Fn >,
手段
&templateFunctionOne< Fn& >,
这意味着
templateFunctionOne
通过引用接受其参数,如果要在调用
async
时通过引用传递参数您需要使用包装器
std::ref
或std::cref
: std::future< bool > tk = std::async(
templateFunctionOne< Fn >,
std::ref( std::forward<Fn>(fn) ) ); // <--- ref added
现在,您的代码开始编译。
另一种方法是使用
remove_reference_t<Fn>
或typename std::remove_reference<Fn>::type
从Fn
删除左值引用: std::future< bool > tk = std::async(
templateFunctionOne< std::remove_reference_t<Fn> >, // <--- remove_reference_t added
std::forward<Fn>(fn) );
return tk.get();
然后按值传递
fn
对象。这个版本比第一个版本好,因为 templateFunctionTwo( std::bind( &printThis, std::placeholders::_1 ) )
使用
ref
时失败,因为ref
仅需要采用Lvalues。