2010-09-20 8 views
7

Próbuję zrozumieć poniższy przykład, który jest podobny (ale nie identyczne) do jednego zaksięgowane wcześniej na tak Help understanding boost::bind placeholder arguments:Boost.Bind - zrozumienie zastępcze

#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); 
} 

Jak to możliwe, że najbardziej zewnętrzna funkcja wiązania wie, że musi przekazać pierwszy argument drugiemu wiązaniu (które oczekuje _1), a drugi argument trzeciemu wiązaniu (które oczekuje _2)? Sposób, w jaki to widzę, polega na tym, że wewnętrzne środki wiążące są najpierw oceniane, więc stają się dwoma jednojajowymi obiektami funkcjonalnymi, które następnie przekazuje się do obiektu wiążącego obiektu less<int>. A gdy nowo utworzony obiekt funkcjonalny jest wywoływany dwoma obiektami, a przechodzi do pierwszego wewnętrznego wiązania, a b przechodzi do drugiego. Gdybym miał rację, dwukrotnie skorzystalibyśmy z _1. Muszę się mylić. Powtórzę raz jeszcze moje pytanie, aby wyjaśnić mój problem: w jaki sposób zewnętrzny segregator wie, który symbol zastępczy został użyty w którym wewnętrznym segregatorze?

Odpowiedz

7

argumenty są pakowane w krotkę (a, b) i przekazywane do funktorów. następnie wewnętrzny funktor decyduje, który element krotki potrzebuje, np. spróbuj:

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

Bardziej ogólnie, każda wartość, niezależnie od tego czy jest to stały/reference/zastępczy jest reprezentowany jako funktora który odbywa krotny argumentu i zwraca wartość.

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

Teraz nie jestem w stu procentach pewny, jak to działa. W ten sposób phoenix implementuje swoją funkcjonalność. jeśli próbujesz zrozumieć mechanizm implementacji bind/lambda, spójrz na phoenix, jest bardzo rozszerzalny i ma doskonałą dokumentację.

+0

ok, rozumiem. Ale co się stanie, jeśli jeden z powiązanych argumentów nie jest segregatorem, np. wartość kosztu? Mam na myśli: boost :: bind (std :: less (), boost :: bind (& X :: value, _1), 10) (a); Skąd wiadomo, do którego argumentu powinna przypisać wygenerowaną krotkę? –

+1

@Mar Zaktualizowałem moją odpowiedź, nie krępuj się – Anycorn