come boost :: function e boost :: bind work

Non mi piace avere scatole magiche sparse per tutto il mio codice … come funzionano esattamente queste due classi per consentire praticamente a qualsiasi funzione di essere mappata su un object funzione anche se la funzione ha un parametro completamente diverso impostato su quello che sta passando a boost::bind

Funziona anche con diverse convenzioni di chiamata (ad esempio, i metodi membri sono __thiscall sotto VC, ma le funzioni “normali” sono generalmente __cdecl o __stdcall per quelli che devono essere compatibili con C.

boost::function consente qualsiasi cosa con un operator() con la firma giusta da associare come parametro, e il risultato del bind può essere chiamato con un parametro int , quindi può essere associato alla function .

Funziona così (questa descrizione si applica allo stesso modo per std::function ):

boost::bind(&klass::member, instance, 0, _1) restituisce un object come questo

 struct unspecified_type { ... some members ... return_type operator()(int i) const { return instance->*&klass::member(0, i); } 

dove return_type e int sono dedotti dalla firma di klass::member , e il puntatore della funzione e il parametro associato sono in effetti memorizzati nell’object, ma ciò non è importante

Ora, boost::function non esegue alcun tipo di controllo: prenderà qualsiasi object e qualsiasi firma fornita nel parametro del modello e creerà un object richiamabile in base alla firma e che chiamerà l’object. Se è imansible, è un errore di compilazione.

boost::function è in realtà un object come questo:

 template  class function { function_impl* f; public: return_type operator()(argument_type arg0) const { return (*f)(arg0); } }; 

dove return_type e argument_type sono estratti da Sig , e f è allocata dynamicmente sull’heap. Questo è necessario per consentire agli oggetti completamente indipendenti con diverse dimensioni di legarsi alla boost::function .

function_impl è solo una class astratta

 template  class function_impl { public: virtual return_type operator()(argument_type arg0) const=0; }; 

La class che fa tutto il lavoro, è una class concreta derivata da boost::function . Ce n’è uno per ogni tipo di object che assegni a boost::function

 template  class function_impl_concrete : public function_impl { Object o public: virtual return_type operator()(argument_type arg0) const=0 { return o(arg0); } }; 

Ciò significa, nel tuo caso, il compito di potenziare la funzione:

  1. istanzia un tipo function_impl_concrete (che è tempo di compilazione, ovviamente)
  2. crea un nuovo object di quel tipo sull’heap
  3. assegna questo object al membro f di boost :: function

Quando chiami l’object funzione, chiama la funzione virtuale del suo object di implementazione, che indirizzerà la chiamata alla tua funzione originale.

NOTA BENE: Si noti che i nomi in questa spiegazione sono deliberatamente costituiti. Qualsiasi somiglianza con persone o personaggi reali … lo sai. Lo scopo era quello di illustrare i principi.