How can it be useful to overload the "function call" operator?
Solution 1
This can be used to create "functors", objects that act like functions:
class Multiplier {
public:
Multiplier(int m): multiplier(m) {}
int operator()(int x) { return multiplier * x; }
private:
int multiplier;
};
Multiplier m(5);
cout << m(4) << endl;
The above prints 20
. The Wikipedia article linked above gives more substantial examples.
Solution 2
There's little more than a syntactic gain in using operator() until you start using templates. But when using templates you can treat real functions and functors (classes acting as functions) the same way.
class scaled_sine
{
explicit scaled_sine( float _m ) : m(_m) {}
float operator()(float x) const { return sin(m*x); }
float m;
};
template<typename T>
float evaluate_at( float x, const T& fn )
{
return fn(x);
}
evaluate_at( 1.0, cos );
evaluate_at( 1.0, scaled_sine(3.0) );
Solution 3
A algorithm implemented using a template doesn't care whether the thing being called is a function or a functor, it cares about the syntax. Either standard ones (e.g. for_each()) or your own. And functors can have state, and do all kinds of things when they are called. Functions can only have state with a static local variable, or global variables.
Solution 4
If you're making a class that encapsulates a function pointer, this might make the usage more obvious.
Solution 5
The compiler can also inline the functor and the function call. It cannot inline a function pointer, however. This way, using the function call operator can significantly improve performance when it is used for example with the standard C++ libary algorithms.
Related videos on Youtube
lurks
Software developer. Geek. Hipster? I live in Argentina. Programming languages I find interesting: C++, Python, Lisp, Javascript, Clojure, and anything that runs on top of the JVM (but not the Java language itself though). I feel more comfortable under Unix environments.
Updated on July 09, 2022Comments
-
lurks almost 2 years
I recently discovered that in C++ you can overload the "function call" operator, in a strange way in which you have to write two pair of parenthesis to do so:
class A { int n; public: void operator ()() const; };
And then use it this way:
A a; a();
When is this useful?
-
AnT stands with Russia about 14 yearsRead about function objects. en.wikipedia.org/wiki/Function_object
-
-
Harold L about 14 yearsAnd the main reason you'd want functors is to have higher-order functions in C++.
-
Tyler about 14 yearsYou could expand this to, for example, multiply by m the first time you call it, multiply by m+1 the second time, etc. Normal functions can't save any state information in between calls, but functors can.
-
Michael Anderson about 14 yearsWell you can always use static variables in a function to give it state (or globals - shudder). But both are very ugly and error prone. (I'd use a functor instead .. but it is possible)
-
Adrian Ratnapala over 11 yearsYep; function-like objects really are most useful when you have sufficiently weak typing. C++ hasn't got that, but templates do.