在类std :: result_of中没有名为“ type”的类型

时间:2018-11-17 15:57:33

标签: c++ asynchronous future stdbind

以下代码无法编译:

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>

2 个答案:

答案 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时通过引用传递参数 您需要使用包装器asyncstd::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。