Why is this overload operator ()?

I am currently studying the standard template library (STL).

In this program, I save some long values ​​in an associative container, and then sort them according to the placement (according to the number in the unit of space).

The code:

#include <iostream> #include <set> #include <functional> using namespace std; class UnitLess { public: bool operator()(long first, long second) { long fu = first % 10; long su = second % 10; return fu < su; } }; typedef set<long, UnitLess> Ctnr; int main(void) { Ctnr store; store.insert(3124); store.insert(5236); store.insert(2347); store.insert(6415); store.insert(4548); store.insert(6415); for(Ctnr::iterator i = store.begin(); i != store.end(); ++i) { cout << *i << endl; } } 

But I don’t understand why our professor overloaded () the operator?

Thanks.

+4
source share
3 answers

The purpose of the class is to implement a function that sorts the elements in a set in a specific way. This is called a predicate.

It is implemented as a functor, i.e. allows you to use a function operator for an object (this is what std :: set does under the hood). This is the usual way for STL and similar code to call custom objects. (A function pointer is more restrictive than a function object (aka functor)

Therefore, it is used as follows:

 Unitless functor; functor(123, 124); // returns true or false 

std :: set is a sorted binary tree, so it calls the Unitless () operator several times for each insert to determine where each long value should go.

Try compiling and putting the printf / std :: cout file into it and see what happens.

Also, keep in mind that callbacks like this (i.e. when you cannot see the call to your code) are frightened and confused at the beginning of your learning curve.

  • Then you get used to it and use them everywhere because they are neat.
  • Then your code again becomes intimidating and confusing, and you avoid them like the plague.
  • Then you become a cable tape programmer and use them only where necessary, but never in other places.

;)

+7
source

UnitLess is a binary predicate that is required for a call with two parameters in the STL.

UnitLess call function operator in UnitLess , instances of this type can be used as a function that takes two longs and returns a bool .

 UnitLess f; f(5, 10); 

equivalently

 bool f(long first, long second) { long fu = first % 10; long su = second % 10; return fu < su; } f(5, 10); 
+7
source

He performed the selective comparison used for std :: set, which compares only units, that is, the modulo 10. Since std :: set is a template, it just tries to call what looks like a function, regardless of whether it is one or no. By overloading operator (), you force it to act as a function.

Doing this can in some cases be extremely powerful, because a struct / class can save state as well as additional parameters. The whole boost :: function / boost :: bind function is based on this (and you don't need to create a class every time).

There is perhaps a slight flaw in the encoded actual example, since the exercise was just to sort them by units, but it could very well eliminate numbers that have the same units but are not actually duplicated. There are no such examples in your code example (you have a duplicate, but this is a duplicate of the whole value). If you had 3478 in addition to 4548, the comparator would consider them the same and would not allow duplication.

By the way, I'm not sure that set is what I would call a "associative" container, which refers to key-value pairs. There are no related values ​​in the set, just keys.

Another point: operator () must be const.

+2
source

All Articles