Composizione funzionale con boost::bind

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

Parte sull'uso di bind, nel capitolo nove, all'interno della terza parte, dedicata ai functor e alla programmazione di più alto ordine.

Il problema sembra semplice: vogliamo selezionare elementi che siano all'interno di un certo intervallo, tipo (5, 10].
Normalmente risolviamo questa richiesta con codice tipo questo:

if(i>5 && i<=10) {
// ...
}

Più complicato risulta l'applicazione di questa condizione nel processare un container. L'uso di boost::bind, in connessione con le operazioni della libreria standard C++, ci aiuta ad ottenere una soluzione relativamente semplice.

Dobbiamo in pratica fare un and logico su due confronti, ottenendo questo codice:

boost::bind(std::logical_and(),
boost::bind(std::greater(), _1, 5),
boost::bind(std::less_equal(), _1, 10));

Vediamo un esempio che verifica questo costrutto. Mettiamo in un vettore alcuni valori, poi usiamo count_if per contare quanti elementi del vettore rispettano la nostra condizione e find_if per trovare il primo elemento che le rispetta:

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>

#include "boost/bind.hpp"

using namespace std;

void bind04() {
vector<int> v;

v.push_back(7);
v.push_back(4);
v.push_back(12);
v.push_back(10);

int count = count_if(v.begin(), v.end(),
boost::bind(logical_and<bool>(),
boost::bind(greater<int>(), _1, 5),
boost::bind(less_equal<int>(), _1, 10)));
cout << "Found " << count << " items" << endl;

vector<int>::iterator it = find_if(v.begin(), v.end(),
boost::bind(logical_and<bool>(),
boost::bind(greater<int>(),_1,5),
boost::bind(less_equal<int>(),_1,10)));

if (it != v.end()) {
cout << "First item: " << *it << endl;
}
}

Un altro possibile uso é quello di applicare diverse operazioni su ogni singolo elemento di un container.

Nell'esempio che segue vogliamo aggiungere 10 a tutti gli elementi e quindi togliere il 5% dal valore risultante. Abbiamo quindi un binding composto che, notiamo, parte dall'operazione più interna.

#include <iostream>
#include <list>
#include <functional>
#include <algorithm>

#include "boost/bind.hpp"

using namespace std;

void bind05() {
list<double> values;
values.push_back(10.0);
values.push_back(100.0);
values.push_back(1000.0);

transform(values.begin(), values.end(), values.begin(),
boost::bind(multiplies<double>(), 0.95,
boost::bind(plus<double>(), _1, 10)));

copy(values.begin(), values.end(), ostream_iterator<double>(cout," "));
cout << endl;
}

Nessun commento:

Posta un commento