Functor In C++ - C++ Programming Tutorial
C++ Course / Miscellaneous / Functor In C++

Functor In C++

BLUF: Mastering Functor In C++ is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Functor In C++

C++ is renowned for its efficiency. Learn how Functor In C++ enables low-level control and high-performance computing in the tutorial below.

In the C++ programming language, a functor represents a function object, which is essentially an object of a class that overrides the function call operator . Functors offer a more object-oriented approach to interacting with functions or objects that behave like functions.

Functors are applicable in various scenarios requiring a function, such as algorithms like std::transform and std::sort, as well as in custom data structures such as maps and sets.

Here is a sample functor that multiplies its input by a constant factor:

Example

class Multiplier {
public:
  Multiplier(int factor) : factor_(factor) {}

  int operator()(int x) const {
    return x * factor_;
  }

private:
  int factor_;
};

In this instance, Multiplier represents a class containing a sole member variable named factor, which is initialized within the constructor. The operator method is redefined to accept an integer parameter x and produce the result of x multiplied by factor.

We can use this functor like this:

Example

Multiplier multiply_by_5(5);
int result = multiply_by_5(10); // result = 50

In this instance, we instantiate a Multiplier object with a factor_ set to 5. Subsequently, we invoke the functor using a parameter of 10, resulting in a product of 10 * 5 = 50.

Note that we have the capability to invoke multiplyby5 just like a standard function, even though it represents an instance of Multiplier. This is made possible by overloading the operator function, enabling us to treat the object as callable like a function.

Functors are frequently employed alongside templates to develop adaptable, reusable code capable of operating with various data types.

Need of Functors over Normal Functions

Functors have a number of advantages over normal functions in C++. Here are a few reasons why you might choose to use a functor instead of a normal function:

  • Flexibility: Functors can be customized by using member variables or constructor parameters, allowing them to behave differently in different situations. This flexibility is not possible with normal functions.
  • Encapsulation: Functors can encapsulate behavior that is related to a specific object or class. This can make the code more organized and easier to read.
  • Polymorphism: Functors can be used in situations where a function pointer or a function object is needed, allowing for polymorphism. This is not possible with normal functions.
  • Stateful behavior: Functors can maintain the state between calls to the function, allowing them to remember information about previous calls. This is not possible with normal functions, which have no memory between calls.
  • Efficiency: Functors can sometimes be more efficient than normal functions because they can avoid the overhead of calling a separate function. In some cases, the functor can be inlined by the compiler, further improving performance.

In essence, functors offer a versatile and potent approach to handling functions or function-like entities in C++. They are adaptable, encapsulated, polymorphic, maintain state, and are effective. Consequently, they are a well-received and extensively utilized aspect of the programming language.

Types of C++ Functors

There are three categories of functors accessible in C++.

1. Generator Functor:

In C++, a generator functor refers to a specific type of functor that produces a series of values each time it is invoked. Essentially, a functor is an object designed to mimic a function by accepting arguments and outputting a result.

A generator functor is commonly structured as a class that redefines the function call operator and retains the state across different calls to produce a series of values. Here is a demonstration:

Example:

Example

#include <iostream>
 
class FibonacciGenerator {
public:
   
FibonacciGenerator() : a_(0), b_(1) {}
    int operator()() {
        int result = a_;
        int next = a_ + b_;
        a_ = b_;
        b_ = next;
       
return result;
    }
private:
    int a_;
    int b_;
};
 
int main() {
   
FibonacciGenerator fib;
    for (int i = 0; i < 20; ++i) {
        int value = fib();
       
std::cout << value << " ";
    }
   
std::cout << std::endl;
    return 0;
}

Output:

Explanation:

This code initializes a FibonacciGenerator instance named fib and proceeds to iterate through a for loop to produce the initial 20 Fibonacci numbers by invoking the operator method of the generator functor multiple times. The generated sequence of numbers is then displayed on the console.

2. Unary Functor:

In C++, a unary functor refers to a type of functor that accepts a single argument of a specific type and produces a result of a different type. A functor is essentially an object that mimics a function by being callable with arguments and capable of yielding a result.

A unary functor is commonly structured as a class that overrides the function call operator and accepts a singular argument of a defined type.

Unary function objects are valuable across a range of scenarios, like converting data or executing functions on series of values. They enable the packaging of a particular operation or conversion into a reusable entity, enhancing code modularity and simplifying maintenance efforts.

Here is a comprehensive code example showcasing the implementation of the Square unary functor to calculate the squares of a series of integer values:

Example:

Example

#include <iostream>
 
class Square {
public:
    int operator()(int x) const {
       
return x * x;
    }
};
 
int main() {
    Square square;
    for (int i = 0; i < 5; ++i) {
        int value = square(i);
       
std::cout << value << std::endl;
    }
    return 0;
}

Output:

Explanation:

This code instantiates a unary functor object named square to generate square values. It employs a for loop to invoke the operator method of the functor using a series of integers. The output, which consists of the sequence of squared values, is then displayed on the console.

In this code snippet, we have designated the operator method of the Square functor as const to signify that it does not alter the functor's state. This is considered a best practice when implementing functors, as it clearly communicates that the functor is immutable and has no side effects.

3. Binary Functor:

In C++, a binary functor is a type of function object that accepts two arguments with defined types and produces a result of a different type. A functor is an object that mimics the behavior of a function by being callable with arguments and returning a value.

A binary functor is commonly structured as a class that overrides the function call operator and accepts two arguments with defined types.

This binary functor accepts a pair of integer arguments, x and y, and computes their total. The operator method is designated as const, signaling that it does not alter the functor's internal state.

Here is a comprehensive code example showcasing the application of the Add binary functor to calculate the total of two integers:

Example:

Example

#include <iostream>
 
class Add {
public:
    int operator()(int x, int y) const {
       
return x + y;
    }
};
 
int main() {
    Add add;
    int result = add(2, 3);
   
std::cout << result << std::endl;
    return 0;
}

Output:

Explanation:

This script generates an instance of the Add binary functor as the 'add' object and invokes the operator method of the functor using two integer parameters. The sum obtained is then stored in the 'result' variable and displayed on the console.

In this program, it's important to highlight that the operator function in the Add functor is designated as const. This signifies that the function does not alter the functor's state. This practice is beneficial when creating functors because it explicitly states that the functor is devoid of state and does not induce any side effects.

How to Create a C++ Functor?

We can effortlessly generate functors in C++; to do so, we need to begin by defining a class, then proceed to override the function call operator , and finally instantiate or create an object of that particular class to invoke it as a function.

Let's understand this with the help of an example

Example:

Example

#include <iostream>
using namespace std;
 
 
class FunctorCreation
{
public:
    
    void operator()()
    {
        cout << "Operation Successful";
    }
};
 
int main()
{
    
    FunctorCreation functor;
 
 
    functor();
 
    return 0;
}

Output:

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience