STL Functors in C++
Introduction
In C++, functors (or function objects) are objects that can be treated as though they are a function or function pointer. They're a key component of the Standard Template Library (STL) and are used extensively for scenarios where a function needs to be passed as an argument. Functors provide greater flexibility compared to function pointers because they can hold state.
What is a Functor?
A functor is any object that can be used with the function-call syntax. This is achieved by overloading the operator()
in the class. Here's a basic example of a functor:
#include <iostream>
class MultiplyBy {
public:
MultiplyBy(int factor) : factor_(factor) {}
int operator()(int value) const {
return value * factor_;
}
private:
int factor_;
};
int main() {
MultiplyBy multiplyBy2(2);
std::cout << "5 multiplied by 2 is " << multiplyBy2(5) << std::endl;
return 0;
}
In this example, MultiplyBy
is a functor that multiplies a given number by a factor. The operator()
is overloaded to perform the multiplication.
Advantages of Functors
Functors have several advantages over regular functions:
- Stateful: Functors can maintain state across calls, unlike simple function pointers.
- Flexibility: Functors can be used where function pointers are expected.
- Type Safety: Functors are type-safe and can leverage C++'s type system.
Using Functors with STL Algorithms
One of the most common uses of functors is with STL algorithms. Many algorithms in the STL, such as std::sort
, accept function objects as parameters. Here's an example:
#include <iostream>
#include <vector>
#include <algorithm>
class Compare {
public:
bool operator()(int a, int b) const {
return a > b;
}
};
int main() {
std::vector vec = {1, 4, 3, 2, 5};
std::sort(vec.begin(), vec.end(), Compare());
for (int num : vec) {
std::cout << num << " ";
}
return 0;
}
In this example, the Compare
functor is used to sort the vector in descending order.
Built-in STL Functors
The STL provides several built-in functors for common operations. These are found in the <functional>
header. Some of the common ones include:
std::plus
: Adds two values.std::minus
: Subtracts the second value from the first.std::multiplies
: Multiplies two values.std::divides
: Divides the first value by the second.std::greater
: Returns true if the first value is greater than the second.std::less
: Returns true if the first value is less than the second.
Here's an example using std::greater
:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main() {
std::vector vec = {1, 4, 3, 2, 5};
std::sort(vec.begin(), vec.end(), std::greater());
for (int num : vec) {
std::cout << num << " ";
}
return 0;
}
In this example, the vector is sorted in descending order using the std::greater
functor.
Custom Functors
You can create custom functors to suit your specific needs. Custom functors are particularly useful when you need to pass a parameterized operation to an STL algorithm. Here's an example of a custom functor:
#include <iostream>
#include <vector>
#include <algorithm>
class IsMultipleOf {
public:
IsMultipleOf(int divisor) : divisor_(divisor) {}
bool operator()(int value) const {
return value % divisor_ == 0;
}
private:
int divisor_;
};
int main() {
std::vector vec = {1, 4, 3, 2, 5, 10, 15};
auto it = std::remove_if(vec.begin(), vec.end(), IsMultipleOf(2));
vec.erase(it, vec.end());
for (int num : vec) {
std::cout << num << " ";
}
return 0;
}
In this example, the custom functor IsMultipleOf
is used to remove all elements from the vector that are multiples of 2.
Conclusion
Functors are a powerful feature in C++ that allow for more flexible and reusable code. They can maintain state, be used with STL algorithms, and provide type safety. Whether using built-in STL functors or creating your own custom functors, they are an essential tool for any C++ programmer.