C++ Functor

Learn via video course
FREE
View all courses
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
Topics Covered

Introduction

Functors, a short name for Function objects, is an instance of a certain class but can be called and executed like normal functions.

This can be achieved by overloading the function call operator (), and once overloaded, this allows us to call the objects of that specific class as if they were simply a function, meaning functors are objects in reality, but due to the overloading of the function call operator () we can make them behave like ordinary functions, and can directly call them using the normal function call syntax, by passing an argument and later can receive the returned value after the successful execution of the call as well.

Need of Functors Over Normal Functions

There are various reasons justifying why Functors should be preferred over normal Functions in their respective scenarios. For example

  • Separation of Logic - While solving a problem using the functor-based approach, the appropriate logic can be separated from the other logical computations happening in the code, allowing us to use the functors in multiple situations as well.
  • Parameterisation - Parameterising a functor is easier and more convenient than traditional functions.
  • Statefulness - This is probably the most important part of why we should prefer functors over normal functions. Normal functions are like free functions, and they cannot retain states between function calls, but talking about functors, they can have the states, meaning the data we are working with will be remembered and will be carried between subsequent calls to a function or class methods there.
  • Performance - Functors are most commonly used in STL implementations, and the concept of templates usually allows better optimization because more details are defined at compile time. As a result, passing functors or function objects in the program instead of ordinary functions often result in better performance.

Types of C++ Functors

There are generally three types of functors

  • Generator Functors - Functors can be called without arguments.
  • Unary Functors - Functors can be called with one argument.
  • Binary Functors - Functors that can be called with two arguments.

How to Create a C++ Functor?

We can easily create functors in C++. For this purpose, we have to create a class first. Then we have to overload the function call operator (), and after that, we can create an instance or an object of that specific class and call that a function.

Let's understand this with the help of an example

Output:

Examples of C++ Functors

In the above example, we have seen how we can work with C++ functors, but one thing should be remembered that functors are not limited to printing string messages onto the console. We can do much more with C++ functors.

Let's see some more examples to understand it better

1. C++ Functor Example

In the example below, we will calculate the square of a number using C++ functors.

Output:

2. Example to Demonstrate State Retention of C++ Functors

In the below example, we will be having a demonstration of how functors in C++ preserve their states between subsequent function calls.

Output:

3. C++ Functor with Return Type and Parameter

Output:

4. C++ Functor with a Member and a Variable

Output:

5. C++ Predefined Functors with STL

The C++ language has a wide collection of predefined useful function objects or simply functors, defined inside the functional header file. We will be properly covering the C++ pre-defined functors in the ahead sections of the article.

Let's see an example of using a pre-defined Function in our program.

Output:

What are Pre-Defined Functors in C++?

The C++ language provides some predefined useful functors defined inside the functional header file. We can include the above header and use the functionalities of those functors immediately.

Let's now look at some predefined functors inside the functional header file.

Arithmetic Functors

FunctorsDescription
plustakes two parameters and returns their sum
minustakes two parameters and returns their difference
multipliestakes two parameters and returns their product
dividestakes two parameters and returns their division
modulustakes two parameters and returns the remainder after division
negatetakes a single parameter and returns the negated value

Relational Functors

FunctorsDescription
equal_totakes two parameters and returns true if both are equal
not_equal_totakes two parameters and returns true if they are unequal
greatertakes two parameters and returns true if the first parameter is greater than the second parameter
greater_equaltakes two parameters and returns true if the first parameter is either greater than or equal to the second one
lesstakes two parameters and returns true if the first parameter is less than the second parameter
less_equaltakes two parameters and returns true if the first parameter is either less than or is equal to the second one

Logical Functors

FunctorsDescription
logical_andreturns the result of the Logical AND operation of two booleans
logical_orreturns the result of the Logical OR operation of two booleans
logical_notreturns the result of the Logical NOT operation of a boolean

Bitwise Functors

FunctorsDescription
bit_andperforms the Bitwise AND operation on two parameters and returns the result
bit_orperforms the Bitwise OR operation on two parameters and returns the result
bit_xorperforms the Bitwise XOR operation on two parameters and returns the result

Functors vs. Function Pointers vs. Virtual Functions

Each of the above three, i.e., functors, function pointers, and virtual functions, have their respective usages, advantages, and disadvantages. Firstly, let's see the difference between functions and function pointers.

Functors and Function Pointers

Functors can preserve their internal state, valid only for "this invocation" of the function object. In contrast, if we try to mimic the same behavior in normal functions or function pointers, we would need to initialize static variables in our program. Still, those static variables will still be valid for any specific function invocation.

Compilers can also inline the calls for the function objects, meaning the compiler can copy the code of the functor directly from its definition instead of creating a separate set of instructions in the memory, but this can not happen in the case of function pointers.

Functors and Virtual Functions

Functors and Virtual Functions are very closely related. Suppose there is a case in which we have to write a program to solve a maths question. The program is needed to take three parameters, two being both operands and the third parameter explaining what type of mathematical operation to perform. This scenario can easily be written using both functors and virtual functions, i.e., to choose what type of mathematical algorithm will be executed dynamically.

But the point where functor overpass the virtual functions here is that, when we use virtual functions, they do not give us the ability to write a templated function that can also accept function pointers, unlike functors. At the same time, this functionality may not be necessary while writing small programs, but it plays an important role while working with complex workflows, etc.

FAQs

Q: What are Functors in Simple Words?

A: Functors are simply objects of a certain class that can be made to behave like normal functions. We can call them using the function call syntax, pass parameters, receive the return value from them, etc.

Q: How are Functors made to behave like normal Functions?

A: It is due to the manual overloading of the function call operator (). The function call operator () can take any number of arguments of any datatype and return anything.

Conclusion

  • Functors or Function objects are an instance of a certain class but can be called and executed like normal functions.
  • We can achieve this by overloading the function call operator ().
  • Parameterization, statefulness, Improved performance, etc., are some reasons why functors can be preferred over normal functions.
  • We can easily create a functor. For that, first, we need to create a class, then overload the function call operator (), create an instance of the class, and now we can call that object a normal function.
  • C++ provides us with a wide range of useful pre-defined functors defined inside the functional header file, like arithmetic, relational, logical, bitwise, etc.
  • Functors can generally be preferred over Function Pointers as they can preserve the internal state. Compilers can also inline the calls for function objects, resulting in improved program performance.
  • Functors and Virtual Functions are very closely related. Both allow us to dynamically select between what type of arguments we want to pass in the function call.
  • Using functors, we can write a templated function that can accept function pointers as well as the argument, unlike virtual functions.