Functor basics
Understanding functors (aka: function objects) is pretty straightforward. Perhaps you’ve heard it mentioned that they’re “callable objects”. Turns out, it’s that simple! A functor is a C++ object for which the function call operator is defined.
\Basic functor which doubles a number
class FunctorDoubler {
public:
int operator()(int x) { return x * 2; }
};
void main() {
auto f = FunctorDoubler{ };
std::cout << f(2) << "\n"; // 4
}
Equivalent lambda expression
What makes functors interesting is that they enable lambda functions in the C++ language. When you define a local, anonymous lambda function in C++, the compiler generates a functor in its place, giving it an anonymous name under the hood.
\An equivalent lambda to the FunctorDoubler
void main() {
auto f = [](int x){ return x * 2; };
std::cout << f(2) << "\n"; // 4
}
Functors have state (lambda capture)
Something which functors have over ordinary functions is that like any C++ object, they can have data members. This feature lets them do things like carry the context (state) of a specific object instance along with them when they are used as lambdas. This state can be persisted between calls of the lambda. In fact, this is exactly what happens when you “capture” in a lambda expression. The captured data becomes a data member of the resultant functor.
\Stateful functor
class FunctorAccumulator {
public:
int operator()(int x) {
acc += x;
return acc;
}
private:
int acc{ };
};
void main() {
auto accumulator = FunctorAccumulator{ };
// the accumulated value persists between calls
std::cout << accumulator(3) << "\n"; // 3
std::cout << accumulator(3) << "\n"; // 6
std::cout << accumulator(3) << "\n"; // 9
}
\Equivalent lambda expression
void main() {
int acc{ }; // <- becomes a data member of the lambda once captured
auto lambdaAccumulator = [&acc](int x) {
acc += x;
return acc;
};
std::cout << lambdaAccumulator(3) << "\n"; // 3
std::cout << lambdaAccumulator(3) << "\n"; // 6
std::cout << lambdaAccumulator(3) << "\n"; // 9
}
Compiler does the heavy lifting
There’s more to it of course. The compiler does a lot of the heavy lifting, handling the finer details and edge cases for us, but, this gives us the general idea of how lambdas correlate directly to functors in C++.