C++ Tutorial
- Functors(Function Objects) II - 2020
We can convert a function to a functor.
#include <iostream> #include <vector> #include <set> #include <algorithm> #include <functional> // std:: bind #include <cmath> #include <iterator> // back_inserter double power(double a, double b) { return pow(a,b); } int main() { std::set<int> s = { 1, 2, 3, 4, 5 }; std::vector<int> v; auto fnc = std::function <double (double,double)>(power); // C++11 std::transform(s.begin(), s.end(), std::back_inserter(v), std::bind(fnc, std::placeholders::_1, 3)); // C++11 // {1, 8, 27, 64, 125} }
The transform() takes set elements, raise each of them to the power of 3, and put it into a vector container using back_inserter(). The function template class converts our power function int fnc. This is only available in C++11. In C++03, we should use ptr_fun.
Sometimes, programming logic written using functor is not easily readable. In that case, we need to seek other options. For example:
#include <iostream> #include <vector> #include <algorithm> #include <functional> // std:: bind #include <cmath> #include <iterator> // back_inserter int main() { std::vector<int> v1 = { 101, 2, 38, 64, 55 }; std::vector<int> v2; std::transform(v1.begin(), v1.end(), // source std::back_inserter(v2), // destination std::bind(std::logical_or<bool>(), std::bind(std::greater<int>(), std::placeholders::_1, 100), std::bind(std::less<int>(), std::placeholders::_1, 10)) ); // C++11 (bind) // element > 100 or element < 10 }
It checks if(i > 100 || i < 10) where i is an element from v1. Then, it puts either 1 or 0 into v2 depending on the result of the check. In this case, it looks like this:
v2 = {1, 1, 0, 0, 0}
If we want to see the output, we can replae the back_inserter() line with this:
std::ostream_iterator<int>(std::cout, " "), // destination
Anyway, the code is a little bit verbose and not easily read. So, we can modify it like this:
bool isTrue(int i) { return (i > 100 || i < 10); } int main() { std::vector<int> v1 = { 101, 2, 38, 64, 55 }; std::vector<int> v2; std::transform(v1.begin(), v1.end(), // source std::back_inserter(v2), // destination isTrue ); // element > 100 or element < 10 }
Or we can use C++11's lambda function:
std::transform(v1.begin(), v1.end(), // source std::back_inserter(v2), // destination [](int e){return ( e > 100 || e < 10); } );
Note that with the lambda function, we do not have to define a separate function and just use anonymous function which makes code more compace, at least in this case.
- Functors (Function Objects) I - Introduction
- Functors (Function Objects) II - Converting function to functor
- Functors (Function Objects) - General
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization