class std::result_of 中没有名为 'type' 的类型

no type named 'type' in class std::result_of

以下代码无法编译:

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: error: no type named 'type' in 'class std::result_of< bool ((std::_Bind(std::_Placeholder<1>))(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不需要传入任何参数,所以绑定调用是不必要的。当按如下方式更改 main 中的调用时,它编译得很好:

 int main()
 {
    return templateFunctionTwo( &printThis );  
 }  

谁能帮忙解释一下?在传递函数指针而不使用 std::ref 来包装需要引用的参数时,我看到了同样的错误,但这似乎是别的(或不是),我在这里错过了什么?

不需要绑定任何东西。

 #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 );  
  }  

编译,执行时returns期望值5。

auto func = std::bind( &printThis );
return templateFunctionTwo( func );  

func 是左值,所以当左值传入 templateFunctionTwo 时, Fn 被推断为 Fn& (由于转发引用)。

下一行

&templateFunctionOne< Fn >,

表示

&templateFunctionOne< Fn& >,

这意味着 templateFunctionOne 通过引用获取其参数, 如果你想在调用 async 时通过引用传递参数 您需要使用包装器 std::refstd::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>::typeFn:

中删除左值引用
  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只需要取左值。