MSalters nota che "le lambda non di cattura possono essere convertite in un puntatore a funzione". Cosa significa questo? L'oggetto lambda corrisponderà a un puntatore al tipo di parametro della funzione.
È difficile tradurre il tipo di lambda in un puntatore-a-funzione. Ecco il mio tentativo di implementazione conforme. È leggermente hackerato.
#include <type_traits>
template< typename fn >
struct ptmf_to_pf;
template< typename r, typename c, typename ... a >
struct ptmf_to_pf< r (c::*) (a ...) const >
{ typedef r (* type)(a ...); };
// Use SFINAE to hide function if lambda is not convertible to function ptr.
// Only check that the conversion is legal, it never actually occurs.
template< typename lambda >
typename std::enable_if< std::is_constructible<
typename ptmf_to_pf< decltype(&lambda::operator()) >::type,
lambda >::value >::type
f(lambda arg) {
arg("hello ");
arg("world\n");
}
#include <iostream>
int main() {
int x = 3;
f([](char const *s){ std::cout << s; }); // OK
f([=](char const *s){ std::cout << s; }); // OK
f([=](char const *s){ std::cout << s << x; }); // error
}
Questo non accetterà i puntatori di funzione come argomenti diretti, poiché il parametro modello deve essere risolto in un funtore. Puoi farlo facendo una specializzazione per ptmf_to_pf
che accetta il puntatore ai tipi di funzione.
Inoltre, come dimostra la demo, non accetterà lambda che catturano nulla in base al valore, oltre che per riferimento. Non c'è modo in C++ di rendere la restrizione così specifica.
Quando l'oggetto di chiusura raggiunge la tua funzione, è già stato creato e non hai idea di cosa ci sia dentro, come se fossero private. Ma nel caso ve lo stiate chiedendo, il lambda certamente non può catturare nulla * dopo il fatto *, e in particolare niente dall'interno della * vostra * funzione 'f'. –
Questo sarebbe inutile, poiché catturare un puntatore per valore è pericoloso quanto catturare un riferimento. –
@ BenVoigt Questo è giusto. – log0