Question
C++ Functors Explained: What They Are and When to Use Them
Question
I often hear about functors in C++. Can someone provide a clear overview of what they are and explain the situations where they are useful?
Short Answer
By the end of this page, you will understand what a functor in C++ is, how it relates to operator(), and why developers use functors in algorithms, sorting, customization, and stateful behavior. You will also see how functors compare with regular functions and lambdas.
Concept
In C++, a functor usually means an object that can be called like a function. This is also called a function object.
A class becomes a functor when it overloads the function call operator:
operator()()
That means instances of the class can be used with function-call syntax.
MyFunctor f;
f();
Even though f is an object, it behaves like a function.
Why this matters
Functors are useful because they combine two powerful ideas:
- behavior: they can be called like functions
- state: they can store data inside the object
A normal function can perform work, but it cannot easily carry per-instance state without using globals, static variables, or extra parameters. A functor can hold configuration inside the object itself.
Basic idea
class Greeter {
public:
void operator()() const {
std::cout << "Hello\n";
}
};
Now this works:
Greeter g;
g();
Why C++ uses them a lot
Functors are common in the C++ Standard Library, especially with:
std::sortstd::find_ifstd::for_eachstd::transform- associative containers with custom ordering
For example, sorting can accept a comparison object:
std::sort(v.begin(), v.end(), MyComparator());
That comparator is often a functor.
Key benefit: stateful behavior
A functor can store values and use them later.
class Add {
int amount;
public:
Add(int a) : amount(a) {}
int operator()(int x) const {
return x + amount;
}
};
Usage:
Add add5(5);
std::cout << add5(10); // 15
This is harder to express with a plain function unless you pass extra arguments every time.
Modern note
In modern C++, lambdas are often used instead of custom functor classes for short tasks. But lambdas themselves are implemented as callable objects, so understanding functors helps you understand lambdas too.
Mental Model
Think of a functor as a machine with a button.
- A regular function is like a button on the wall: press it, and it runs.
- A functor is like a small machine you own: it has a button and it can store settings inside.
For example:
- a function is "add something"
- a functor is "add 5" because the object remembers
5
So a functor is not just an action. It is an action plus stored data.
Syntax and Examples
Core syntax
A class becomes a functor by overloading operator().
class Printer {
public:
void operator()(const std::string& text) const {
std::cout << text << "\n";
}
};
Usage:
Printer print;
print("Hello");
Example 1: Simple functor
#include <iostream>
class Square {
public:
int operator()(int x) const {
return x * x;
}
};
int main() {
Square square;
std::cout << square(4) << "\n"; // 16
}
Step by Step Execution
Consider this example:
#include <iostream>
class Add {
int amount;
public:
Add(int a) : amount(a) {}
int operator()(int x) const {
return x + amount;
}
};
int main() {
Add add5(5);
int result = add5(10);
std::cout << result << "\n";
}
Step-by-step
1. The class is defined
class Add {
This creates a blueprint for objects that can store an amount.
2. The object stores state
int amount;
Real World Use Cases
1. Custom sorting
You often need to sort data in a special way.
Examples:
- sort users by age
- sort files by size
- sort products by price descending
A functor can define the comparison logic.
2. Filtering and matching
Standard algorithms such as std::find_if and std::count_if accept callable objects.
Examples:
- find the first inactive user
- count numbers greater than a threshold
- filter records matching a condition
A stateful functor can store that threshold.
3. Data transformation
With algorithms like std::transform, functors can modify values.
Examples:
- convert temperatures
- scale numbers
- normalize data
4. Configuration-based behavior
A functor can hold settings.
Examples:
- a formatter storing precision
- a validator storing allowed ranges
- a pricing rule storing a discount percentage
5. Associative containers with custom ordering
std::set and std::map can use custom comparison functors.
Real Codebase Usage
In real C++ projects, functors appear both directly and indirectly.
Common patterns
Guarded behavior
A functor may check conditions before doing work.
class PositiveOnly {
public:
bool operator()(int x) const {
return x > 0;
}
};
This can be passed to algorithms like std::count_if.
Reusable comparison objects
Instead of repeating sorting logic inline, teams sometimes create named functors for clarity.
class SortByScore {
public:
bool operator()(const Player& a, const Player& b) const {
return a.score > b.score;
}
};
This makes intent explicit.
Validation rules
A functor can encapsulate validation settings.
Common Mistakes
1. Forgetting to overload operator()
Broken code:
class MyFunctor {
public:
void run() const {
std::cout << "Hello\n";
}
};
MyFunctor f;
f(); // error
Why it fails:
f()only works ifoperator()exists
Fix:
class MyFunctor {
public:
void operator()() const {
std::cout << "Hello\n";
}
};
2. Confusing a functor with a regular function
A functor is an object, not just a function.
That means:
- it can have member variables
- it can have constructors
- each instance can behave differently
3. Forgetting const when appropriate
Comparisons
| Concept | What it is | Can store state? | Best use case |
|---|---|---|---|
| Regular function | Named callable code | No | Simple reusable logic |
| Functor | Object with operator() | Yes | Reusable callable with state |
| Lambda | Anonymous callable object | Yes, via captures | Short inline behavior |
| Function pointer | Pointer to a function | No | Interfacing with older APIs |
Functor vs regular function
- A regular function is simpler
- A functor can store data and configuration
- A functor can also participate in templates as a type
Functor vs lambda
- Lambdas are often shorter and easier for local use
- Functors are useful when you want a
Cheat Sheet
Quick definition
A functor in C++ is an object that can be called like a function because it overloads operator().
Basic syntax
class MyFunctor {
public:
ReturnType operator()(ParameterType value) const {
// work
}
};
Usage
MyFunctor f;
f(argument);
Equivalent to:
f.operator()(argument);
Why use functors
- callable like functions
- can store state
- useful with STL algorithms
- reusable named behavior
Common STL uses
std::sort(begin, end, comparator);
std::find_if(begin, end, predicate);
std::transform(begin, end, out, operation);
Example comparator
{
:
{
a > b;
}
};
FAQ
What is a functor in C++?
A functor is an object that acts like a function because its class overloads operator().
Why use a functor instead of a normal function?
Use a functor when you want callable behavior that also stores state, such as configuration or parameters.
Are lambdas the same as functors?
Lambdas are not written the same way, but they are implemented as callable objects, so they are closely related to functors.
Are functors still used in modern C++?
Yes. Lambdas are more common for short local tasks, but functors are still useful for reusable named callables and stateful logic.
Where are functors used in the STL?
They are commonly used in algorithms like std::sort, std::find_if, std::transform, and in containers with custom comparators.
Can a functor keep internal data?
Yes. That is one of its main advantages over regular functions.
Is operator() required for a functor?
Yes. In common C++ usage, an object is considered a functor or function object when it defines operator().
Can functors return values?
Yes. operator() can return any valid type, just like a normal function.
Mini Project
Description
Build a small C++ program that uses functors to process numbers in different ways. This project demonstrates the main reason functors are useful: they can behave like functions while storing their own configuration.
Goal
Create a program that sorts numbers in descending order and transforms numbers by adding a configurable value using functors.
Requirements
- Create a functor that compares two integers in descending order.
- Create a functor that adds a stored value to an integer.
- Use
std::sortwith the comparison functor. - Use
std::transformwith the stateful add functor. - Print the results before and after transformation.
Keep learning
Related questions
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Base Class Constructor Rules Explained
Learn how C++ base class constructors are called from derived classes, including order, syntax, defaults, and common mistakes.
C++ Casts Explained: C-Style Cast vs static_cast vs dynamic_cast
Learn the difference between C-style casts, static_cast, and dynamic_cast in C++ with clear examples, safety rules, and real usage tips.