A function adapter is a function object that enables the composition of function objects with each other, with certain values, or with special functions.
Function adaptors provided by C++11.
1) The bind() Adapter - binds parameters for callable objects
using std;
using std::placeholder
// Normal binding
auto plus10 = bind(plus<int>(), _1, 10);
// internally calls plus<> (i.e., operator +), with a placeholder _1
// as first parameter/operand and 10 as second parameter/operand
cout << "+10: " << plus10(7) << endl;
auto plus10times2 = bind(multiplies<int>(), bind(plus<int>(), _1, 10), 2);
cout << "+10 *2: " << plus10times2(7) << endl;
auto pow3 = bind(multiplies<int>(), bind(multiplies<int>(), _1, _1), _1);
cout << "x*x*x: " << pow3(7) << endl;
auto inversDivide = bind(divides<double>(), _2, _1);
cout << "invdiv: " << inversDivide(49,7) << endl;
// Call global function
char myToupper (char c)
{
std::locale loc;
return std::use_facet<std::ctype<char> >(loc).toupper(c);
}
bind(equal_to<char>(), bind(myToupper,_1), bind(myToupper,_2)));
// Create func object: myToupper(param1)==myToupper(param2)
// Note that bind() internally copies passed arguments. To let the function object use a reference
// to a passed argument, use ref() or cref()
void incr (int& i)
{
++i;
}
int i=0;
bind(incr,i)(); // increments a copy of i, no effect for i
bind(incr,ref(i))(); // increments i
// Calling Member Functions
class Person {
private:
string name;
public:
Person (const string& n) : name(n) {
}
void print () const {
cout << name << endl;
}
void print2 (const string& prefix) const {
cout << prefix << name << endl;
}
};
vector<Person> coll = { Person("Tick"), Person("Trick"), Person("Track") };
for_each (coll.begin(), coll.end(), bind(&Person::print,_1));
for_each (coll.begin(), coll.end(), bind(&Person::print2,_1,"Person: "));
bind(&Person::print,_1)
// defines a function object that calls param1.print() for a passed Person.
// That is, because the first argument is a member function, the next argument
// defines the object for which this member function gets called
bind(&Person::print2,_1,"Person: ")
// defines a function object that calls param1.print2("Person: ") for any passed Person
// bind pointers
vector<Person*> cp;
...
for_each (cp.begin(), cp.end(), bind(&Person::print, _1));
vector<shared_ptr<Person>> sp;
...
for_each (sp.begin(), sp.end(), bind(&Person::print, _1));
2) The mem_fn() Adapter
simply calls an initialized member function for a passed argument while additional
arguments are passed as parameters to the member function:
for_each (coll.begin(), coll.end(), mem_fn(&Person::print));
mem_fn(&Person::print)(n); // calls n.print()
mem_fn(&Person::print2)(n,"Person: "); // calls n.print2("Person: ")
// Binding to Data Members
map<string,int> coll;
int sum = accumulate (coll.begin(), coll.end(),
0,
bind(plus<int>(), _1, bind(&map<string,int>::value_type::second, _2)));
auto f1 = bind(&map<string,int>::value_type::second, _2);
auto f2 = bind(plus<int>(), _1, f1);
f2(value, *iter) => plus<int>(value, f1(*iter))
f1(*iter) => f1(pair<const string, int> p) => p.second
(second is the data member of pair class, in order to access this data member, we need bind a pair instance)
WHY SO COMPLICATED ?
We have more powerful weapon, lambdas!!!
// accumulate implementation reference
template<class InputIt, class T, class BinaryOperation>
T accumulate(InputIt first, InputIt last, T value, BinaryOperation op)
{
for (; first != last; ++first) {
value = op(value, *first);
}
return value;
}
3) not1() and not2 are almost deprecated since C++11, and so others.