std::function
ha una firma fissa. Questa era una scelta di design, non un requisito difficile. Scrivi pseudo std::function
che supporta più firme non è difficile:
template<class...Sigs>
struct functions;
template<>
struct functions<> {
functions()=default;
functions(functions const&)=default;
functions(functions&&)=default;
functions& operator=(functions const&)=default;
functions& operator=(functions&&)=default;
private:
struct never_t {private:never_t(){};};
public:
void operator()(never_t)const =delete;
template<class F,
std::enable_if_t<!std::is_same<std::decay_t<F>, functions>{}, int>* =nullptr
>
functions(F&&) {}
};
template<class S0, class...Sigs>
struct functions<S0, Sigs...>:
std::function<S0>,
functions<Sigs...>
{
functions()=default;
functions(functions const&)=default;
functions(functions&&)=default;
functions& operator=(functions const&)=default;
functions& operator=(functions&&)=default;
using std::function<S0>::operator();
using functions<Sigs...>::operator();
template<class F,
std::enable_if_t<!std::is_same<std::decay_t<F>, functions>{}, int>* =nullptr
>
functions(F&& f):
std::function<S0>(f),
functions<Sigs...>(std::forward<F>(f))
{}
};
uso:
auto f = [](int a = 3) {std::cout << a << std::endl; };
functions<void(int), void()> fs = f;
fs();
fs(3);
Live example.
Ciò creerà una copia separata della lambda per sovraccarico. È persino possibile avere diversi lambda per sovraccarichi diversi con getto attento.
È possibile scriverne uno che non lo fa, ma in pratica richiederebbe reimplementare std::function
con uno stato interno più elaborato.
Una versione più avanzata di quanto sopra eviterebbe l'utilizzo dell'ereditarietà lineare, poiché ciò comporta il numero O (n^2) e la profondità del modello ricorsiva O (n) sul numero di firme. Un'ereditarietà di alberi binari bilanciati scende a O (n lg n) codice generato e O (lg n) profondità.
La versione forza industriale sarebbe conservare il passato in lambda volta, utilizzare l'ottimizzazione oggetto piccolo, avere una pseudo-vtable manuale che utilizza una strategia di successione binaria di inviare la chiamata di funzione, e conservare inviato a funzionare puntatori in detta pseudo vtable. Ci vorrebbe spazio O (# firme) * sizeof (puntatore di funzione) in una base per classe (non per istanza), e utilizzare circa il sovraccarico di ogni istanza come farebbe std::function
.
Ma questo è un po 'troppo per un post SO, no?
start of it
'auto h = f;'? – MikeCAT
Non penso che 'std :: function' abbia un supporto di parametri predefinito. – chris
@MikeCAT So che :) Qual è il modo corretto se voglio specificare completamente il tipo, se ce n'è? –