28

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?

Fred Nurk
  • 13,952
  • 4
  • 37
  • 63
lurks
  • 2,576
  • 4
  • 30
  • 39

7 Answers7

36

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.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 3
    And the main reason you'd want functors is to have higher-order functions in C++. – Harold L Feb 28 '10 at 03:01
  • 2
    You 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. – Tyler Feb 28 '10 at 03:05
  • 4
    Well 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) – Michael Anderson Feb 28 '10 at 03:11
21

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) );
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
6

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.

paul
  • 61
  • 1
1

If you're making a class that encapsulates a function pointer, this might make the usage more obvious.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
1

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.

fintux
  • 11
  • 2
1

For example for implementing generators:

// generator
struct Generator {
    int c = 0;

    virtual int operator()() {
        return c++;
    }
};

int sum(int n) {
    Generator g;

    int res = 0;
    for( int i = 0; i < n; i++ ) {
        res += g();
    }

    return res;
}
Quonux
  • 2,975
  • 1
  • 24
  • 32
0

I see potential to yet one exotic use:

Suppose you have object of unknown type and have to declare another variable of same type, like this:

 auto c=decltype(a*b)(123);

When such pattern used extensively, decltype become very annoying. This case can occur when using some smart type system that automatically invent type of result of functions and operators based on types of arguments.

Now, if each specialization of each type of that type system equipped with magic definition of operator() like this:

template<????> class Num<???>{
    //specific implementation here
    constexpr auto operator()(auto...p){return Num(p...);}
}

decltype() no more needed, you can write simply:

auto c=(a*b)(123);

Because operator() of object redirects to constructor of its own type.

Lexey
  • 1