When to Prefer Functors Instead of Function?
1. Stateful Computations
If we need to maintain state information between calls, functors are a good choice. Unlike regular functions, functors can store state information in member variables and use it across multiple calls.
Example:
C++
// C++ program to use functors for Stateful Computations #include <iostream> using namespace std; // Struct representing a counter with a count variable struct Counter { int count = 0; // Initial count is 0 // Overloaded function call operator to increment count // and print it void operator()() { cout << "Count: " << count++ << endl; } }; int main() { Counter counter; // Creating an instance of Counter // Invoking the counter twice counter(); // Count: 0 counter(); // Count: 1 return 0; } |
Count: 0 Count: 1
2. Parameterized Behavior
Functors can be parameterized when they are constructed. This allows you to create a functor with specific behavior that can be used later.
Example:
C++
// C++ program to use parametrized functors #include <iostream> using namespace std; // Struct representing a multiplier with a factor variable struct Multiplier { int factor; // Factor to multiply by // Constructor to initialize the factor Multiplier( int factor) : factor(factor) { } // Overloaded function call operator to perform // multiplication int operator()( int input) { return input * factor; } }; int main() { Multiplier multiplyByThree( 3); // Creating an instance of Multiplier with // factor 3 // Using the multiplier to multiply 5 by 3 cout << "3 * 5 = " << multiplyByThree(5) << endl; return 0; } |
3 * 5 = 15
3. Overloading Function Call Operator
Functors allow overloading of the function call operator that means we can have different versions of the operator() function that take different numbers or types of parameters, providing more flexibility.
Example:
C++
// C++ program to use Functors to overload the function call // operator #include <iostream> #include <string> using namespace std; // Struct representing an overloaded functor struct OverloadedFunctor { // Overloaded function call operator for integers void operator()( int x) { cout << "Integer: " << x << endl; } // Overloaded function call operator for strings void operator()( const string& x) { cout << "String: " << x << endl; } }; int main() { // Creating an instance of the overloaded functor OverloadedFunctor functor; // Using the functor to print an integer and a string functor(42); functor( "Hello, Functor!" ); return 0; } |
Integer: 42 String: Hello, Functor!
4. Use with STL Algorithms
Many STL algorithms like std::sort
, std::transform
, etc., accept functors as arguments so, functors can be used to customize the behavior of these algorithms.
Example:
C++
// C++ program to use functor with STL algorithm #include <algorithm> #include <iostream> #include <vector> using namespace std; // Functor for multiplication by 2 struct Multiply { int operator()( int x) const { return x * 2; } }; int main() { vector< int > vec = { 1, 2, 3, 4, 5 }; vector< int > result(vec.size()); // Using std::transform with Multiply functor to // multiply each element by 2 transform(vec.begin(), vec.end(), result.begin(), Multiply()); // Printing the result for ( int i : result) { cout << i << " " ; // Output: 2 4 6 8 10 } cout << endl; return 0; } |
2 4 6 8 10
When to Use a Functor Instead of a Function in C++?
In C++, both functors and functions can be used to encapsulate behavior and provide callable objects. Still, there are specific scenarios where using a functor is more advantageous than a regular function. In this article, we will learn when to use a functor instead of a function in C++.