2015-08-05 22 views
10

Come mostrato nella 'possibile implementazione' di std::apply, vediamo che la funzione di libreria standard std::invoke viene utilizzata per richiamare l'oggetto richiamabile F.perché usare invocare helper anziché chiamare semplicemente functor?

È necessario in questa situazione? se sì, per quale motivo?

Quali sono i vantaggi della scrittura:

template<typename F, typename ... Args> 
decltype(auto) func(F &&f, Args &&... args){ 
    return std::invoke(std::forward<F>(f), std::forward<Args>(args)...); 
} 

oltre:

template<typename F, typename ... Args> 
decltype(auto) func(F &&f, Args &&... args){ 
    return std::forward<F>(f)(std::forward<Args>(args)...); 
} 

?

risposta

7

Un puntatore a membro è Callable, e invoke (o INVOKE, come quella soon-to-be-seven-bullet-point construct è noto nella Standard) maniglie magico 's questo caso (beh, quattro e che presto saranno sei casi in realtà), mentre la sintassi della funzione di chiamata non lo fa.

1

voglio completare T.C.'s answer con un esempio sintattico:

struct X { 
    int x; 
    int foo(int a) const { return a + x; } 
}; 

e si dispone di un oggetto X e un puntatore a una funzione di membro, ad es .:

X obj = X{1000}; 
auto fn = &X::foo; 

e bisogno di chiamare func.

  • Con la sintassi di chiamata, questo non funzionerà:

    func_call(fn, obj, 24); // compiler error 
    

    error: must use '.' or '->' to call pointer-to-member function in [...]

    Invece si deve lavorare intorno ad esso:

    func_call([obj, fn](int a) { return (obj.*fn)(a); }, 24); 
    
  • Se tu avessi il metodo invoke , potresti aver appena scritto:

    func_invoke(fn, obj, 24); 
    
Problemi correlati