以下代码无法编译:
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 );
}
编译时出现以下错误:
functional :: 1665:61:错误:“类”中没有名为“ type”的类型 std :: result_of
))(int)>))(std :: _ Bind))(int)>&)>'
我简化了上面的内容,但仍然无法使用相同的错误消息进行编译:
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
不需要传递任何参数,因此不需要绑定调用。并且当按如下方式更改主调用时,它可以正常编译:
int main()
{
return templateFunctionTwo( &printThis );
}
有人可以帮忙解释一下吗?在传递函数指针而无需使用std::ref
来包装需要引用的参数时,我看到了相同类型的错误,但这似乎是其他事情(或没有),我在这里遗漏了什么? / p>
答案 0 :(得分:0)
没有必要绑定任何东西。
#include<thread>
#include<functional>
#include<utility>
#include<future>
#include<memory>
#include<iostream>
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 )
{
std::cout << value << std::endl;
return true;
}
int main()
{
//auto func = std::bind( &printThis, std::placeholders::_1 );
return templateFunctionTwo( &printThis );
}
编译,执行后返回期望值5。
答案 1 :(得分:0)
public virtual T FindByID<T>(T typeInstance, long id, string typeName) where T : TypeBase
{
Assembly asm = Assembly.GetCallingAssembly();
var item = asm.CreateInstance(typeName);
using (IDbConnection cn = Connection)
{
MethodInfo getInfo = typeof(SqlMapperExtensions).GetMethod("Get");
MethodInfo getGeneric = getInfo.MakeGenericMethod(item.GetType());
item = getGeneric.Invoke(cn, new object[] { cn,id,null,null });
}
return (T)item;
}
auto func = std::bind( &printThis );
return templateFunctionTwo( func );
是Lvalue,所以当Lvalue传递到func
时,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
只需要取Lvalues。