简体   繁体   中英

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

The following code just wouldn't compile:

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

when compiling it gives the following error:

functional::1665:61: error: no type named 'type' in 'class std::result_of< bool ((std::_Bind(std::_Placeholder<1>))(int)>))(std::_Bind))(int)>&)>'

I simplified the above, still it won't compile with the same error message:

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

Since now the function printThis doesn't require passing in any parameters, binding the call isn't necessary. And when changing the call in the main as follows, it compiles fine:

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

Could someone help to explain? I've seen the same kind of errors when passing a function pointer without using std::ref to wrap a parameter when its reference is required, but this seems to be something else (or not), what am I missing here?

There is no need to bind to anything.

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

Compiles, and when executed returns the expected value of 5.

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

func is Lvalue, so when Lvalue is passed into templateFunctionTwo , Fn is deduced to be Fn& (due to forwarding reference).

Below line

&templateFunctionOne< Fn >,

means

&templateFunctionOne< Fn& >,

it implies that templateFunctionOne takes its argument by reference, if you want to pass argument by reference when calling async you need to use wrapper std::ref or std::cref :

   std::future< bool > tk =  std::async( 
               templateFunctionOne< Fn >,
               std::ref( std::forward<Fn>(fn) ) ); // <--- ref added

Now your code compiles.

Another way is to use remove_reference_t<Fn> or typename std::remove_reference<Fn>::type to remove Lvalue reference from Fn :

  std::future< bool > tk =  std::async( 
     templateFunctionOne< std::remove_reference_t<Fn> >, // <--- remove_reference_t added 
     std::forward<Fn>(fn)  );
     return tk.get();

then fn object is passed by value. This version is better than first, because the call

 templateFunctionTwo( std::bind( &printThis, std::placeholders::_1 ) )

fails when ref is used, because ref needs to take only Lvalues.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM