Boost bind

Da Beyond the C++ Standard Library: An Introduction to Boost, di Björn Karlsson.

bind

La STL mette a disposizione bind1st e bind2nd per permettere il binding a functor già esistenti. Boost estende questo concetto con bind.

Per prima cosa, mi rivedo un uso di bind1st:

#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;

int main () {
int numbers[] = {10,20,30,40,50,10};
int cx = count_if (numbers, numbers+6, bind1st(equal_to<int>(), 10) );
cout << "There are " << cx << " elements that are equal to 10.\n";
}

Chiamo la count_if passando come predicato il functor equal_to che viene adattato dalla bind1st in modo da usare, oltre al parametro passato dalla count_if, ovvero l'elemento corrente nella scansione della sequenza, un valore fisso - 10 nel nostro caso.

Riscrivere questo specifico esempio con boost:bind non porta un gran vantaggio, anzi, a ben vedere, sembra piuttosto una soluzione peggiore, dato che occorre specificare il segnaposto (_1) utilizzato.

Ma boost:bind é più potente di bind1st, e lo vediamo quando vogliamo usare una funzione e non un functor (come é obbligatorio fare per bind1st).

Vero é che spesso é possibile adattare una funzione alle specifiche di bind1st ma questo comporta un appesentimento del codice, e non sempre é possibile farlo.

Altro punto a favore di boost::bind é la possibilità di innestare diverse chiamate, come nell'ultimo esempio d'uso che riporto.

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
#include <boost/bimap.hpp>

using namespace std;

class A {
int value_;
public:

A(int value) : value_(value) {
}

void print() {
cout << "Value is: " << value_ << endl;
}
};

void doSomething(int a, int b) {
if (a == b) {
cout << "done" << endl;
}
}

int main() {
int numbers[] = {10, 20, 30, 40, 50, 10};

int cx = count_if(numbers, numbers + 6, bind1st(equal_to<int>(), 10));
cout << cx << endl;

cx = count_if(numbers, numbers + 6, boost::bind(equal_to<int>(), _1, 10));
cout << cx << endl;

for_each(numbers, numbers + 6, boost::bind(&doSomething, _1, 10));

vector<A> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);

for (vector<A>::iterator it = v.begin(); it != v.end(); ++it) {
it->print();
}

cout << "for_each:" << endl;
for_each(v.begin(), v.end(), mem_fun_ref(&A::print));

cout << "for_each w/ boost::bind:" << endl;
for_each(v.begin(), v.end(), boost::bind(&A::print, _1));

cout << "count w/ nested boost::bind:" << endl;
int count = count_if(numbers, numbers + 6,
boost::bind(logical_and<bool>(),
boost::bind(greater<int>(), _1, 15),
boost::bind(less_equal<int>(), _1, 40)));
cout << count << endl;
}

Nessun commento:

Posta un commento