2010-09-20 27 views
7

Sto cercando di capire il seguente esempio, che è simile (ma non uguale) a quello registrato in precedenza sul SO Help understanding boost::bind placeholder arguments:Boost.Bind - comprendere segnaposti

#include <boost/bind.hpp> 
#include <functional> 

struct X { 
    int value; 
}; 

int main() {  
    X a = { 1 }; 
    X b = { 2 }; 

    boost::bind(std::less<int>(), 
     boost::bind(&X::value, _1), 
     boost::bind(&X::value, _2)) 
    (a, b); 
} 

Come è possibile, che la la funzione di binding più esterno sa che deve passare il primo argomento al secondo binding (che si aspetta _1) e il secondo argomento al terzo binding (che si aspetta _2)? Il modo in cui vedo questo è che i raccoglitori interni vengono valutati per primi, quindi diventano due oggetti funzionali unari, che vengono poi passati al raccoglitore dell'oggetto less<int>. E quando l'oggetto funzionale appena creato viene richiamato con due oggetti, a passa al primo inner-bind e b passa al secondo. Se avessi ragione, useremmo lo _1 due volte. Devo essere sbagliato. Ripeterò ancora una volta la mia domanda per chiarire il mio problema: in che modo il raccoglitore esterno sa quale segnaposto è stato utilizzato in quale legante interno?

risposta

7

gli argomenti sono raggruppati in tupla (a, b) e passati ai funtori. allora il funtore interno decide quale elemento tuple ha bisogno, per es. Prova:

boost::bind(&X::value, _1)(a,b) 
boost::bind(&X::value, _2)(a,b) 

Più in generale, ogni valore, a prescindere se è costante/riferimento/segnaposto è rappresentato come functor che prende argomento tupla e restituisce il valore.

bind(f, 10)(a) // still functor which discards arguments 

Ora, io non sono al cento per cento sicuro che questo è il modo legano lo fa. tuttavia, questo è il modo in cui phoenix implementa la sua funzionalità. se stai cercando di capire il meccanismo dell'implementazione di bind/lambda, guarda phoenix, è molto estensibile e ha una documentazione eccellente.

+0

ok, ho capito. Ma cosa succede se uno degli argomenti associati non è un raccoglitore, ad es. valore costante? Intendo: boost :: bind (std :: less (), boost :: bind (& X :: value, _1), 10) (a); Come fa a sapere a quale argomento dovrebbe assegnare la tupla generata? –

+1

@ Mar Ho aggiornato la mia risposta, sentitevi liberi di guardare – Anycorn