[ glorius @ 24.10.2013. 18:52 ] @
Proucavam boost::bind i jedna stvar mi nije jasna:

Code:


std::sort(                                           
            v.begin(),                               
            v.end(),                                 
            boost::bind(std::less<int>(),            
                boost::bind(&personal_info::age, _1),
                boost::bind(&personal_info::age, _2) 
                       )                             
         );                                          



Jasno mi je da ovaj kod 'vezuje' parametre koji su oznaceni placeholderima sa _1 i _2 i kada sort pozove function operator za less<int>() oni se predaju funkciji i dalje se pravi komparacija.
Nije mi jasno to kako kompajler zna kojoj bind funkciji pripadaju _1 i _2 placeholders. Da li pripadaju ovoj spoljnoj koja za prvi parametar uzima std::less<int>() funktor ili u nested bindovima.
Po ovom kodu, oni pripadaju spoljnoj bind funkciji. Sta kao i nested bind zahteva placeholder za kreiranje svog function objekta?

Isto tako postoji primer koji radi istu stvar ali i tu mi nije jasno sta se desava:

Code:


std::sort(v.begin(), v.end(), boost::bind(&personal_info::age, _1) <
              boost::bind(&personal_info::age, _2));



Ono sto me buni je to, zasto placeholders ne idu od _1 za svaki bind vec je za jedan _1 a za drugi _2 "prvi" placeholder za bind funkciju.
[ Rapaic Rajko @ 25.10.2013. 11:09 ] @
Auh, kuda ide ova apstrakcija vise... :)

Nisam strucnjak za C++, i prvi put cujem za boost::bind(), ali neku analogiju u navedenom kodu mogu da uocim. Posmatraj placeholders _1 i _2 kao OUT argumente, u odnosu na bind() koji ih kreira. Sto znaci da imaju smisla samo za spoljnu funkciju sort(), odnosno (u drugom primeru) poredjenje '<' (unutar kojih je pozvan bind() koji generise placeholder).
Pa tako, nagadjam da, kad bi se stavili placeholders _1 i _1 (umesto _1 i _2) bi se i compiler pobunio - traze se 2(dva) argumenta za poredjenje, a umesto toga, dvaput se generise samo prvi argument... drzi li vodu ova prica?

Pozz
[ glorius @ 25.10.2013. 17:23 ] @
Bez koriscenja bind bi morali da obezbedimo funkcijski objekat:

Code:


class SomeClass
{
       int age() const;
};

class SortCriterion
{
public:
      bool operator() (const SomeClass& p1, const SomeClass& p2) const
      {
           return p1.age() < p2.age();        
      }
};

...

std::sort(vecOfSomeClassValues.begin(), vecOfSomeClassValues.end(), SortCriterion());



Sada, ako pogledamo primer:

Code:


std::sort(                                           
            v.begin(),                               
            v.end(),                                 
            boost::bind(std::less<int>(),            
                boost::bind(&personal_info::age, _1),
                boost::bind(&personal_info::age, _2) 
                       )                             
         ); 



boost::bind(std::less<int>(),
boost::bind(&personal_info::age, _1),
boost::bind(&personal_info::age, _2)
)

Ovaj deo koda generise funkcijski objekat koji vraca bool rezultat (to je operator() std::less<int> funkcijskog objekta) i spoljasnji bind vezuje rezultate unutrasna dva binda za operator() std::less<int> funkcijskog objekta:

Code:


class GenerisaniSortKriterijum;

poziva se operator () i predaju se ages:

rezultat_1 = _1.age(); // generisano sa boost::bind(&personal_info::age, _1)
rezultat_2 = _2.age(); // generisano sa boost::bind(&personal_info::age, _2)

GenerisaniSortKriterijum::operator()(rezultat_1, rezultat_2) i vraca se vrednost definisana std::less<int> kriterujmom poredjenja.

( u stvari, ovo je analogno sa: std::less<int>::operator(rezultat_1, rezultat_2)



Objekte koji su predstavljeni sa _1 i _2 su delayed parametri funkcije koje sort predaje ovom nasem GenerisaniSortKriterijum kada poziva generisani predikat.
Mozda nisam objasnio na najbolji nacin ali mislim da je to ono sto se desava kada se izvrsava ovaj slozeni bind kod.
Eto sad sam i ja razumeo dok sam pisao ovo, sta se desava i tvoje objasnjenje mi je dosta pomoglo da skapiram o cemu se radi.

Mene je zanimalo to, sta ako funkcija age uzima parametar neki (mozda u ovom primeru nema smisla ali ajde da vidimo)

Code:


....

int age(bool roundToNextDecade);

....

std::sort(                                           
            v.begin(),                               
            v.end(),                                 
            boost::bind(std::less<int>(),            
                boost::bind(&personal_info::age, _1, ???),
                boost::bind(&personal_info::age, _2, ???) 
                       )                             
         ); 



Moguce da ovo nema nikakvog smisla i da ne moze ovako...
U svakom slucaju, mislim da sam skapirao malo bolje sada sve ovo :)

A da, mozda bi bRoundToNextDecade onda mogli da predamo nekoj hipotetickoj sort funkciji koja prosledjuje i 3. parametar i onda bi ispalo nesto ovako:

Code:


std::sort(                                           
            v.begin(),                               
            v.end(),                                 
            boost::bind(std::less<int>(),            
                boost::bind(&personal_info::age, _1, _3),
                boost::bind(&personal_info::age, _2, _3) 
                       )                             
         ); 




[Ovu poruku je menjao glorius dana 25.10.2013. u 18:42 GMT+1]
[ glorius @ 25.10.2013. 17:59 ] @
Citat:
Pa tako, nagadjam da, kad bi se stavili placeholders _1 i _1 (umesto _1 i _2) bi se i compiler pobunio - traze se 2(dva) argumenta za poredjenje, a umesto toga, dvaput se generise samo prvi argument.


Ne bi bilo greske, onda bi se samo uporedjivali ages jednog te istog objekta koji je predat generisanom funktoru kao prvi parametar (a to, sto se tice sort nema mnogo smisla :) ).
[ glorius @ 25.10.2013. 21:02 ] @
Nasao sam resenje:
Kod Person klase je malo (vise) los ali sam ga modifikovao zbog funkcionalnosti koju sam zeleo da postignem.

Code:


class Person
{
public:
    Person(int age)
        : m_nAge(age)
        , m_bAlreadyRounded(false)
    {}

    int age(bool bRoundToNextDecade = false) const
    {
        if(bRoundToNextDecade && !m_bAlreadyRounded)
        {
            m_nAge = (m_nAge / 10 + 1)*10;
            m_bAlreadyRounded = true;
        }

        return m_nAge;
    }

private:
    mutable int m_nAge;
    mutable bool m_bAlreadyRounded;
};

void mySort(std::vector<Person>& persons, bool bRound)
{
    std::sort(persons.begin(), persons.end(), boost::bind(std::less<int>()
                                                        , boost::bind(&Person::age, _1, bRound)  // aha! 
                                                        , boost::bind(&Person::age, _2, bRound)  // aha! :)
                                                      )
              );
}

std::ostream& operator<<(std::ostream& out, const Person& p)
{
    out << p.age() << std::endl;
    return out;
}

int main()
{
    std::vector<Person> persons;
    persons.push_back(Person(15));
    persons.push_back(Person(8));
    persons.push_back(Person(29));

    mySort(persons, true);

    std::copy(persons.begin(), persons.end(), std::ostream_iterator<Person>(std::cout));
}

[ Rapaic Rajko @ 28.10.2013. 10:01 ] @
Citat:
glorius:
Citat:
Pa tako, nagadjam da, kad bi se stavili placeholders _1 i _1 (umesto _1 i _2) bi se i compiler pobunio - traze se 2(dva) argumenta za poredjenje, a umesto toga, dvaput se generise samo prvi argument.


Ne bi bilo greske, onda bi se samo uporedjivali ages jednog te istog objekta koji je predat generisanom funktoru kao prvi parametar (a to, sto se tice sort nema mnogo smisla :) ).


Hm, pomisljao sam i na to dok sam gledao gornji kod. Ali mi se ipak cini da sam ja u pravu (generisao bi se samo prvi argument). Zamislimo da je taj standardni sort() neki quick, shell ili koji god vec bio sort; svi sort metodi traze nacin/kriterijum poredjenja, i dva item-a za poredjenje. Sad, ti kazes da bi stavljanjem pogresnih placeholder-a (_1 i _1, umesto _1 i _2) na neki nacin poremetio/modifikovao algoritam sort-a, tako da uzme jedan ISTI item umesto 2 razlicita? Sumnjam; i dalje mislim da bi samo izgenerisao dvaput PRVI argument, odnosno da bi se compiler pobunio (seti se, placeholders su OUT parametri). Ali dobro, treba probati, sto ti i mozes :); rado bih cuo rezultat tog eksperimenta.

Jako mi je drago ako sam ti (ikako) pomogao, ali iskreno, jezim se od tolike apstrakcije :D .

Pozz