What are C++ functors and their uses?
Solution 1
A functor is pretty much just a class which defines the operator(). That lets you create objects which "look like" a function:
// this is a functor
struct add_x {
add_x(int val) : x(val) {} // Constructor
int operator()(int y) const { return x + y; }
private:
int x;
};
// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument
std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
assert(out[i] == in[i] + 1); // for all i
There are a couple of nice things about functors. One is that unlike regular functions, they can contain state. The above example creates a function which adds 42 to whatever you give it. But that value 42 is not hardcoded, it was specified as a constructor argument when we created our functor instance. I could create another adder, which added 27, just by calling the constructor with a different value. This makes them nicely customizable.
As the last lines show, you often pass functors as arguments to other functions such as std::transform or the other standard library algorithms. You could do the same with a regular function pointer except, as I said above, functors can be "customized" because they contain state, making them more flexible (If I wanted to use a function pointer, I'd have to write a function which added exactly 1 to its argument. The functor is general, and adds whatever you initialized it with), and they are also potentially more efficient. In the above example, the compiler knows exactly which function std::transform
should call. It should call add_x::operator()
. That means it can inline that function call. And that makes it just as efficient as if I had manually called the function on each value of the vector.
If I had passed a function pointer instead, the compiler couldn't immediately see which function it points to, so unless it performs some fairly complex global optimizations, it'd have to dereference the pointer at runtime, and then make the call.
Solution 2
Little addition. You can use boost::function
, to create functors from functions and methods, like this:
class Foo
{
public:
void operator () (int i) { printf("Foo %d", i); }
};
void Bar(int i) { printf("Bar %d", i); }
Foo foo;
boost::function<void (int)> f(foo);//wrap functor
f(1);//prints "Foo 1"
boost::function<void (int)> b(&Bar);//wrap normal function
b(1);//prints "Bar 1"
and you can use boost::bind to add state to this functor
boost::function<void ()> f1 = boost::bind(foo, 2);
f1();//no more argument, function argument stored in f1
//and this print "Foo 2" (:
//and normal function
boost::function<void ()> b1 = boost::bind(&Bar, 2);
b1();// print "Bar 2"
and most useful, with boost::bind and boost::function you can create functor from class method, actually this is a delegate:
class SomeClass
{
std::string state_;
public:
SomeClass(const char* s) : state_(s) {}
void method( std::string param )
{
std::cout << state_ << param << std::endl;
}
};
SomeClass *inst = new SomeClass("Hi, i am ");
boost::function< void (std::string) > callback;
callback = boost::bind(&SomeClass::method, inst, _1);//create delegate
//_1 is a placeholder it holds plase for parameter
callback("useless");//prints "Hi, i am useless"
You can create list or vector of functors
std::list< boost::function<void (EventArg e)> > events;
//add some events
....
//call them
std::for_each(
events.begin(), events.end(),
boost::bind( boost::apply<void>(), _1, e));
There is one problem with all this stuff, compiler error messages is not human readable :)
Solution 3
A Functor is a object which acts like a function.
Basically, a class which defines operator()
.
class MyFunctor
{
public:
int operator()(int x) { return x * 2;}
}
MyFunctor doubler;
int x = doubler(5);
The real advantage is that a functor can hold state.
class Matcher
{
int target;
public:
Matcher(int m) : target(m) {}
bool operator()(int x) { return x == target;}
}
Matcher Is5(5);
if (Is5(n)) // same as if (n == 5)
{ ....}
Solution 4
Name "functor" has been traditionaly used in category theory long before C++ appeared on the scene. This has nothing to do with C++ concept of functor. It's better to use name function object instead of what we call "functor" in C++. This is how other programming languages call similar constructs.
Used instead of plain function:
Features:
- Function object may have state
- Function object fits into OOP (it behaves like every other object).
Cons:
- Brings more complexity to the program.
Used instead of function pointer:
Features:
- Function object often may be inlined
Cons:
- Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)
Used instead of virtual function:
Features:
- Function object (non-virtual) doesn't require vtable and runtime dispatching, thus it is more efficient in most cases
Cons:
- Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)
Solution 5
Like others have mentioned, a functor is an object that acts like a function, i.e. it overloads the function call operator.
Functors are commonly used in STL algorithms. They are useful because they can hold state before and between function calls, like a closure in functional languages. For example, you could define a MultiplyBy
functor that multiplies its argument by a specified amount:
class MultiplyBy {
private:
int factor;
public:
MultiplyBy(int x) : factor(x) {
}
int operator () (int other) const {
return factor * other;
}
};
Then you could pass a MultiplyBy
object to an algorithm like std::transform:
int array[5] = {1, 2, 3, 4, 5};
std::transform(array, array + 5, array, MultiplyBy(3));
// Now, array is {3, 6, 9, 12, 15}
Another advantage of a functor over a pointer to a function is that the call can be inlined in more cases. If you passed a function pointer to transform
, unless that call got inlined and the compiler knows that you always pass the same function to it, it can't inline the call through the pointer.
Comments
-
uss over 3 years
I keep hearing a lot about functors in C++. Can someone give me an overview as to what they are and in what cases they would be useful?
-
Martin York over 15 yearsJust need to add that they can be used just like a function pointer.
-
Alecs over 12 yearsCan you explain this line, please std::transform(in.begin(), in.end(), out.begin(), add_x(1)); why you write there add_x, not the add42?
-
josesuero over 12 years@Alecs Both would have worked (but the effect would have been different). If I'd used
add42
, I would have used the functor I created earlier, and added 42 to each value. Withadd_x(1)
I create a new instance of the functor, one which only adds 1 to each value. It is simply to show that often, you instantiate the functor "on the fly", when you need it, rather than creating it first, and keeping it around before you actually use it for anything. -
Milad Khajavi about 11 yearsCan you explain these use case in real example? how can we use functors as polymorphism adn funtion pointer?
-
erogol about 11 yearsWhat actually does mean that a functor holds state?
-
Gautam over 10 yearsThe () operator is called the function-call operator. I guess you could also call it the parentheses operator.
-
zar over 10 yearsCan the functors have other member functions as well?
-
josesuero over 10 years@zadane of course. They just have to have the
operator()
, because that is what the caller uses to invoke it. What else the functor has of member functions, constructors, operators and member variables is completely up to you. -
caub over 10 years
std::transform(in.begin(), in.end(), out.begin(), [](int &i){ i+=1;});
-
johnbakers about 10 yearsIf your functor called different specific functions, and these other functions varied in the number of parameters they accept, does this mean your functor accepted a variable number of arguments for dispatching to these other functions?
-
MasonWinsauer about 10 years@LokiAstari - For those that are new to the concept, that could be a bit misleading. Functors can be "used like", but not always "in place of" function pointers. For example, a function that takes a function pointer cannot take a functor in its place even if the functor has the same arguments and return value as the function pointer. But by and large when designing, functors are the preferred and theoretically "more modern" way to go.
-
463035818_is_not_a_number over 9 yearsthanks for pointing out that one needs a base class to have some kind of polymorphism. I just have the problem that I have to use a functor in the same place as a simple function pointer and the only way I found was to write a functor base class (as I cannot use C++11 stuff). Wasnt sure if this overhead makes sense until i read your answer.
-
NathanOliver almost 9 yearsShouldn't
operator ()
be public in your first example since classes default to private? -
Mateen Ulhaq over 8 years@crl Shouldn't that be
std::transform(in.begin(), in.end(), out.begin(), [](int i) { return i + 1; });
? -
Lightness Races in Orbit over 8 years"This parameter is actually the argument "parameterVar" passed by the constructor we just wrote" Huh?
-
einpoklum over 8 years"unlike regular functions, they can contain state" <- umm, regular functions can have static variables, so - they can contain state, albeit the semantics are a bit dodgy.
-
rikimaru2013 about 8 years@jalf
class which defines the operator()
function isn't class but it still functor. -
srm about 8 years@rikimaru2013 In the parlance of functional programming, you're correct, a function is also a functor, but in the parlance of C++, the functor is specifically a class used as a function. The terminology was a bit abused early on, but the division is useful distinction and so persists today. If you start referring to functions as "functors" in a C++ context then you'll just confuse the conversation.
-
Nic about 8 yearsWhy does the second one return
int
when it should returnbool
? This is C++, not C. When this answer was written, didbool
not exist? -
Nic about 8 years@Erogol A functor is an object which happens to support the syntax
foo(arguments)
. Therefore, it can contain variables; for example, if you had anupdate_password(string)
function, you might want to keep track of how often that had happened; with a functor, that can be aprivate long time
representing the timestamp it last happened. With a function pointer or plain function, you'd need to use a variable outside of its namespace, which is only directly related by documentation and usage, rather than by definition.l -
James Curran about 8 years@QPaysTaxes A typo I guess. I probably copy'n'pasted the code from the first example and forgot to change it. I've fixed it now.
-
Nic about 8 yearsOh, that makes sense. Thanks for bearing with my pedantry :)
-
Sergei Tachenov almost 8 yearsIs it a class or an instance of the class? In most sources,
add42
would be called a functor, notadd_x
(which is the class of the functor or just the functor class). I find that terminology consistent because functors are also called function objects, not function classes. Can you clarify this point? -
Omu over 7 yearsso this is like in javascript when you have
function makeadd(bynumber){ return function(x){ return x + bynumber; }}
-
Euri Pinhollow over 7 yearsIt puzzled me for quite a while that you named
std::transform
a function. It isn't, it's a template which looks like a function in your code thanks to template parameter deduction. -
armb over 7 yearsArticle arguing that functor should correctly be used for this meaning (see also en.wikipedia.org/wiki/Functor), and that using it for function objects is just sloppy: jackieokay.com/2017/01/26/functors.html It may be too late for that though, given the number of answers here that only consider the function object meaning.
-
JoeManiaci about 7 yearsI love when people not only explain something but also give the motivation for using it. Thank you.
-
sanjeev over 6 yearscan you please explain the above scenario by quoting some part of code , i am new to c++ want to understand this concept..
-
StarDust over 6 yearsWhat's the advantage using over bool Is5(int n) {return 5==n;}
-
James Curran over 6 years@Riasat If Matcher is in a library, defining Is5() is quite simple. ANd you can create Is7(), Is32() etc. Further, that's just an example. THe functor could be much more complicate.
-
Hi-Angel over 6 years⁺¹ for mentioning that the name have been made up for no reason. I've just been searching for what's the relation between mathematical (or functional if you want) functor and the one from C++.
-
Euri Pinhollow over 6 years@einpoklum functions can contain only one state unless you also pass the state (state itself or some value identifying state) as argument somehow.
-
Euri Pinhollow over 6 yearsThe answer is good but it lacks some important data which is obvious to experienced programmers but not so much to newbies: 1) only function templates have advantage of making it obvious for compiler what function was used. 2) If function accepts
std::function<whatever(whatever)>
then the advantage of inlining is lost. --------- When I first read this answer years ago it left me in buggy state because of argument deduction which hidden the fact that you cannot pass any object to non-template function. -
mschmidt over 6 yearsThis answer should be the one with >700 Upvotes. As someone how knows Haskell better than C++, the C++ lingua puzzled me all the times.
-
Caleth about 6 years@EuriPinhollow when you pass arguments, e.g.
std::transform(in.begin(), in.end(), out.begin(), add_x(1))
, you have a function call. You are right thatstd::transform
on it's own is not a function. -
Euri Pinhollow about 6 yearsOne more comment: it is still possible to inline function even if it is passed as
function
object value. BUT: compilers are able to inline calls even if function is passed by pointer, you do not need to have a template for that. It's just that with function template you cannot pass function defined at run time. -
Mateen Ulhaq almost 6 yearsCategory theory and C++? Is this Bartosz Milewski's secret SO account?
-
Mateen Ulhaq almost 6 yearsIt might be helpful to summarize the functor laws in standard notation:
fmap(id, x) = id(x)
andfmap(f ◦ g, x) = fmap(f, fmap(g, x))
. -
463035818_is_not_a_number over 5 yearsmaybe at some point this answer deserves an update, since now lambdas are the easiest way to get a functor from whatever
-
copper.hat over 5 yearsThanks for elaborating the misleading use of the word functor.
-
Sisir over 5 yearsThis is true. But with the new C++ 11
lambdas
functors are pretty much dead. Now you may not need to create a whole class to have the function, instead have the function inlined in the method call. Lambdas are equally powerful in terms of both usage and performance. -
Caleth almost 5 years@Sisir when you only have one
operator()
, sure. If you have a bunch of differentoperator()
s sharing state then multiple lambdas are harder to get right than an explicit closure class -
Caleth almost 5 years@mschmidt whilst functor also means this, C++ overloads the name to mean the same as "function object"
-
Paul Fultz II almost 5 yearsThere is no mention of functor in the C++ standard. cppreference.com provides no definition of functor while it does provide a definition of FunctionObject with no mention of functor at all.
-
renardesque almost 5 yearsThis (the matrix example) is plain use of
operator()
but not making use of function object properties. -
rnpl over 4 yearsC++ and math terminology diverge in a lot of areas. This is neither undesirable nor wrong. E.g. "vector". Math concepts like "array", "sequence", "matrix" or "vector" have no equivalent in programming, because programming requires a concrete data type, which math is completely unconcerned with. In math you might talk about a sequence of numbers, but in programming this is meaningless. Are you talking about a list? a vector? a deque? The fact that some of these terms duplicate mathematical ones is fine. Even "function" does not have the mathematical meaning, which is why function object fails.
-
Franky about 4 yearsWhat does
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
do at the first iteration, please? -
Ray Eldath almost 4 yearsI'm specifically curious about the name functor, is this have anything to do with functors in cats theory? I've just heard this word from some friends, and I know nothing of it, nor am I interested in that direction -- just curious.
-
user almost 4 yearsGot an example?
-
phuclv over 3 yearsint C++11 there are
std::function
andstd::bind
-
rturrado over 3 yearsI was looking exactly for this example because I have just seen it in a C++ course and I wasn't understanding it. Usually, we define an object of a class, which implements operator(), and pass it as an argument, a functor, to a function such as
transform
. However, in this case we are just constructing the object in the same call. Is that the only difference? That the functor goes out of scope and is destroyed oncetransform
finishes? Thanks!