In the Boost Signals library, they are overloading the () operator.
Is this a convention in C++? For callbacks, etc.?
I have seen this in code of a co-worker (who happens to be a big Boost fan). Of all the Boost goodness out there, this has only led to confusion for me.
Any insight as to the reason for this overload?
Introduction to Operator Overloading Operator overloading is one of the best features of C++. By overloading the operators, we can give additional meaning to the operators like +-*/=.,= etc., which by default are supposed to work only on standard data types like int, float, char, void etc.
It allows you to provide an intuitive interface to users of your class, plus makes it possible for templates to work equally well with classes and built-in/intrinsic types. Operator overloading allows C/C++ operators to have user-defined meanings on user-defined types (classes).
Operator overloading facilitates the specification of user-defined implementation for operations wherein one or both operands are of user-defined class or structure type. This helps user-defined types to behave much like the fundamental primitive data types.
Operator Overloading means giving extended meaning beyond their predefined operational meaning. For example operator + is used to add two integers as well as join two strings and merge two lists. It is achievable because '+' operator is overloaded by int class and str class.
One of the primary goal when overloading operator() is to create a functor. A functor acts just like a function, but it has the advantages that it is stateful, meaning it can keep data reflecting its state between calls.
Here is a simple functor example :
struct Accumulator { int counter = 0; int operator()(int i) { return counter += i; } } ... Accumulator acc; cout << acc(10) << endl; //prints "10" cout << acc(20) << endl; //prints "30"
Functors are heavily used with generic programming. Many STL algorithms are written in a very general way, so that you can plug-in your own function/functor into the algorithm. For example, the algorithm std::for_each allows you to apply an operation on each element of a range. It could be implemented something like that :
template <typename InputIterator, typename Functor> void for_each(InputIterator first, InputIterator last, Functor f) { while (first != last) f(*first++); }
You see that this algorithm is very generic since it is parametrized by a function. By using the operator(), this function lets you use either a functor or a function pointer. Here's an example showing both possibilities :
void print(int i) { std::cout << i << std::endl; } ... std::vector<int> vec; // Fill vec // Using a functor Accumulator acc; std::for_each(vec.begin(), vec.end(), acc); // acc.counter contains the sum of all elements of the vector // Using a function pointer std::for_each(vec.begin(), vec.end(), print); // prints all elements
Concerning your question about operator() overloading, well yes it is possible. You can perfectly write a functor that has several parentheses operator, as long as you respect the basic rules of method overloading (e.g. overloading only on the return type is not possible).
It allows a class to act like a function. I have used it in a logging class where the call should be a function but i wanted the extra benefit of the class.
so something like this:
logger.log("Log this message");
turns into this:
logger("Log this message");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With