views:

133

answers:

6

What is the problem with this code ? this code is giving me lots of syntax errors. Also I would like to know why functors are used in C++.

class f
{
public:
    int operator(int a) {return a;}
} obj;

int main()
{
    cout << obj(0) << endl;
}
A: 

Try this:

class f
{

  public:

   int operator(int a) {return a;}

};

int main()
{
  f obj;
  cout<<obj(0)<<endl;

}
Alexander Rafferty
the problem is with operator()(int a)
mousey
+7  A: 

You're missing an extra pair of parenthesis when declaring operator(). The name of the function is operator(), and it still needs the list of parameters after it. Thus it should look like:

int operator()(int a) {return a;}

Function objects (a.k.a. functors) like this are typically used where you'd use a pointer to a function. However, they have the advantage that they can use inheritance and they encapsulate state as well. Often, well designed class or function templates will be able to use them almost interchangeably with function pointers. However, a good optimizer can typically produce better code when a template object is used.

For a fairly sophisticated example of how you might use function objects, have a look at expression templates.

Here's a small, somewhat contrived example of how they can use inheritance:

struct unary_int_func {
    virtual int operator()(int i) = 0;
};
struct negate : public unary_int_func {
    int operator()(int i) {return -i;}
};
struct one_plus : public unary_int_func {
    int operator()(int i) {return i+1;}
};

void show_it(unary_int_func &op, int v) {
    cout << op(v) << endl;
}

In this case, we create a base class with the operator as a pure virtual function. Then we derive to concrete classes that implement it. Code such as show_it() can then use any instance of a class derived from this base. While we could just have used a pointer to a function that takes an int and returns an int, this is more typesafe. Code that uses the function pointer would accept any such function pointer, whereas this way we can define a whole new hierarchy that maps an int to an int:

struct a_different_base_class {
    virtual int operator()(int i) = 0;
};

but instances of this would not be interchangeable with instances of unary_int_func.

As for state, consider a running sum function:

struct running_sum : public unary_int_func {
    int total;
    running_sum() : total(0) {}
    int operator()(int i) {return total += i;}
};

int main()
{
    running_sum s;
    cout << s(1) << endl;
    cout << s(2) << endl;
    cout << s(3) << endl;
    cout << s(4) << endl;
}

Here, the instance of running_sum keeps track of the total. It will print out 1, 3, 6 and 10. Pointers to functions have no such way of keeping state between distinct invocations. SGI's STL page on function objects has a similar example to my running sum one, but shows how you can easily apply it to a range of elements in a container.

Boojum
can you please tell what is the use of inheritance here ? (compared to functions). Also I dint get the encapsulate state too.
brett
@brett, functor are objects, and object can have attributes (used to store values/states).
YeenFei
imagine you have a caller requesting for a printer object, where it would invoke by passing known parameter (usually string). how would you implement different printers (device / pdf) while maintaining OOD and loose coupling ?
YeenFei
@Boojum and @YeenFei thank you very much
brett
A: 

because int operator(int) is effectively equal to int int #something_missing_here#(int)

operator is a reserved keyword and not qualifier as valid function identifier/name when used alone.
I would say it is used to make compiler understand that given expression are function declaration despite the invalid identifiers used (c++ only allow alphabet and underscore as first character in naming)

YeenFei
A: 

Functors are basically functions with states. Their biggest usage is in STL and Boost libraries. For example std::sort takes a type of functor called Comparator. In this context, perhaps a function object could have been passed instead but functor offers more flexibility by means of the data members you can have and manipulate with subsequent calls to the same functor. Functors are also used to implement C++ callbacks.

Goutham
A: 

As you already have figured out the issue in your operator overloading code, I would rather try to address your doubt regarding functors.

Functor is a short for 'function pointer'. These are widely used to provide a handle to customize the behavior of an algorithm, for example the sorting algorithms in STL use functor as parameter and the user (programmer) can implement the function to tell the algorithm the result of comparison for 2 elements.

Hemant
A: 

A functor is an object (instance of class or struct) that typically overloads the operator(). The difference between a functor and a normal function is that because a functor is an object, it can maintain state between calls.

Because a functor is an object, rules of inheritance apply as well and you can use this to your advantage.

A functor is also useful when you use the STL. std::sort, std::for_each, etc allow you to process the contents of an entire container (arrays included). Here's an example from cplusplus.com:

// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

void myfunction (int i) {
  cout << " " << i;
}

struct myclass {
  void operator() (int i) {cout << " " << i;}
} myobject;

int main () {
  vector<int> myvector;
  myvector.push_back(10);
  myvector.push_back(20);
  myvector.push_back(30);

  cout << "myvector contains:";
  for_each (myvector.begin(), myvector.end(), myfunction);

  // or:
  cout << "\nmyvector contains:";
  for_each (myvector.begin(), myvector.end(), myobject);

  cout << endl;

  return 0;
}
carleeto