Dedicare la firma della chiamata di una lambda o di un arbitrario chiamabile per “make_function”

In alcune situazioni è preferibile essere in grado di cancellare un callable (es. Funzione, puntatore di funzione, istanza di object con operator() , lambda, mem_fn ), ad esempio mem_fn adattatori Boost con C ++ 11 lambda in cui è ansible assegnare una copia e il tipo costruttibile di default è richiesto.

std::function sarebbe l’ideale, ma non sembra esserci alcun modo per determinare automaticamente quale firma istanziare il modello di class std::function con. C’è un modo semplice per ottenere la firma della funzione di un arbitrario callable e / o avvolgerlo in un’istanza istanza di std::function appropriata (cioè un modello di funzione make_function )?

In particolare, sto cercando l’uno o l’altro di

 template using get_signature = ...; template std::function<get_signature> make_function(F &&f) { ... } 

tale che make_function([](int i) { return 0; }) restituisce una std::function . Ovviamente questo non dovrebbe funzionare se un’istanza è richiamabile con più di una firma (ad es. Oggetti con più di uno, template o default-parameter operator() s).

Boost va bene, anche se le soluzioni non Boost che non sono eccessivamente complesse sono preferite.


Modifica: rispondendo alla mia domanda.

Ho trovato una soluzione non-libreria abbastanza sgradevole, usando il fatto che lambdas ha operator() :

 template struct remove_class { }; template struct remove_class { using type = R(A...); }; template struct remove_class { using type = R(A...); }; template struct remove_class { using type = R(A...); }; template struct remove_class { using type = R(A...); }; template struct get_signature_impl { using type = typename remove_class< decltype(&std::remove_reference::type::operator())>::type; }; template struct get_signature_impl { using type = R(A...); }; template struct get_signature_impl { using type = R(A...); }; template struct get_signature_impl { using type = R(A...); }; template using get_signature = typename get_signature_impl::type; template using make_function_type = std::function>; template make_function_type make_function(F &&f) { return make_function_type(std::forward(f)); } 

Qualche idea in cui ciò può essere semplificato o migliorato? Qualche bug ovvio?

Imansible. Potresti essere in grado di prendere l’indirizzo di operator() per alcuni tipi, ma non per un arbitrario chiamabile, perché potrebbe avere sovraccarichi o parametri di template. Indipendentemente dal fatto che possa funzionare o meno per un lambda, sicuramente non è ben definito, AFAIK.

Per le funzioni lambda non generiche non-variabili e non-generiche e per le semplici funzioni libere, è ansible utilizzare il seguente approccio:

 #include  #include  template< typename L, typename R, typename ...A > constexpr auto // std::function< R (A...) > to_function_pointer(L l, R (L::*)(A...) const) { return static_cast< R (*)(A...) >(l); } template< typename L, typename R, typename ...A > constexpr auto // std::function< R (A...) > to_function_pointer(L l, R (L::*)(A...)) // for mutable lambda { return static_cast< R (*)(A...) >(l); } template< typename L > constexpr auto to_function_pointer(L l) { return to_function_pointer(l, &L::operator ()); } template< typename R, typename ...A > constexpr auto // std::function< R (A...) > to_function_pointer(R (* fp)(A...)) { return fp; } namespace { void f() { std::cout << __PRETTY_FUNCTION__ << std::endl; } } int main() { to_function_pointer([] () { std::cout << __PRETTY_FUNCTION__ << std::endl; })(); //to_function_pointer([&] () { std::cout << __PRETTY_FUNCTION__ << std::endl; })(); // can't cast from non-captureless lambda to function pointer to_function_pointer([] () mutable { std::cout << __PRETTY_FUNCTION__ << std::endl; })(); to_function_pointer(f)(); to_function_pointer(&f)(); return EXIT_SUCCESS; }