Function Objects
In the previous example, we are passing the address of a function (mult()) into the accumulate() function.
We can instead use a Function Object:
//
// main.cpp
// STL Function Objects
//
// Created by Bryan Higgs on 10/23/24.
//
#include <iostream>
#include <vector> // For vector
#include <numeric> // For accumulate()
class Multiply
{
public:
int operator()(int x, int y) const { return x * y; }
};
int main(int argc, const char * argv[])
{
int values[] = {2, 3, 5, 7, 11};
size_t len = sizeof(values)/sizeof(values[0]);
// Initialize vector using pointer iterator
std::vector<int> v(&values[0], &values[len]);
int product = accumulate(v.begin(), v.end(), 1, Multiply());
std::cout << "Result: " << product << std::endl;
return 0;
}… which produces the following:
Result: 2310
Program ended with exit code: 0
A function object, or functor, is any type that implements operator(). This operator is referred to as the call operator or sometimes the application operator. The C++ Standard Library uses function objects primarily as sorting criteria for containers and in algorithms.
Reasons for using a function object instead of an ordinary function include:
- A function object can carry more potentially useful context than can an ordinary function.
- A function object’s operator() can be inlined, whereas passing the address of an ordinary function precludes inlining.
STL provides the following function objects:
| Arithmetic | Relational | Logical |
|---|---|---|
plus<T> | equal_to<T> | logical_and<T> |
| minus<T> | not_equal_to<T> | logical_or<T> |
| multiplies<T> | less<T> | logical_not<T> |
| divides<T> | greater<T> | |
| modulus<T> | less_equal<T> | |
| negate<T> | greater_equal<T> |
So, we can modify our code to make use of the STL-provided function object, multiplies<T>:
//
// main.cpp
// STL Function Objects
//
// Created by Bryan Higgs on 10/23/24.
//
#include <iostream>
#include <vector> // For vector
#include <numeric> // For accumulate()
#include <functional> // For multiplies
int main(int argc, const char * argv[])
{
int values[] = {2, 3, 5, 7, 11};
size_t len = sizeof(values)/sizeof(values[0]);
// Initialize vector using pointer iterator
std::vector<int> v(&values[0], &values[len]);
int product = accumulate(v.begin(), v.end(), 1,
std::multiplies<int>() );
std::cout << "Result: " << product << std::endl;
return 0;
}… which produces the same output as before.