Significance of passing a function as an argument - c++

I just learn about passing a function of as an argument in c++,
however I wonder what is its significance.
Considering this example,
#include <iostream>
using namespace std;
void argumentFunction(int x) {
cout << x << " is the result.";
}
void myFunction(void (*functionparam) (int), char parameter[80]) {
cout << parameter;
(*functionparam)(1);
}
int main() {
myFunction(&argumentFunction, "I am calling a function with a function.");
cin.ignore(80,'\n');
return 0;
}
why would I need to pass argumentFunction as a parameter in myFunction, which in fact I can directly call it without passing it:
like this:
#include <iostream>
using namespace std;
void argumentFunction(int x) {
cout << x << " is the result.";
}
void myFunction(char parameter[80]) {
cout << parameter;
argumentFunction(1);
}
int main() {
myFunction( "I am calling a function with a function.");
cin.ignore(80,'\n');
return 0;
}

One example is in the C standard library function qsort, which has the signature:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
This allows the programmer to pass an arbitrary comparison function to the existing sorting algorithm instead of having to write a whole new sort function for each type of sorting that needs to be done.

If we take a practical example like C's qsort, it doesn't know how to compare your data. After all, it could be string keys you're sorting, integers, floats, pointers, a combo, etc.
It knows how to sort your data, but it doesn't know how to compare one of your keys to another. So passing in a comparator function pointer gives it that missing puzzle piece and allows that code to sort virtually anything (well, except for objects that require C++ semantics since it just shuffles bytes around while ignoring objects).
So a function pointer is a useful mechanism for decoupling. qsort is decoupled from the data types it can potentially sort. That also makes it very generally applicable since you can provide the missing functionality it needs by passing in function pointers.
Another example is, say, you want to build a user interface for a software. Whenever the data in your software changes, some viewport/canvas kind of thingy should be redrawn. If you just called that redraw function directly in every part of your codebase where the data changes, all sorts of parts throughout your system would have to be coupled to the user interface.
Instead, if the system just calls one or more function pointers whenever the data changes, the underlying system doesn't have to be directly coupled to anything in the user interface (also allowing you to swap out the user interface with something newer and more fashionable without breaking that logic). It's sort of like broadcasting a signal out to the world saying, "I have changed!" without caring who is listening, and we can pass in the appropriate function pointers to determine what to do in the case of such events.
With C++ you have more flexible concepts like virtual functions, functionoids using them, function objects that work with templates, ones that can work abstractly using templates to capture specific function object types through static polymorphism to something using dynamic polymorphism that doesn't require templates to then be used, etc. But it's basically the same idea.

Related

Passing pointer to struct, vs. passing void pointer and casting to struct

I'm working on a legacy code base that has this pattern:
struct sometype_t { /* ... */ };
int some_method(void *arg1) { // void pointer
((sometype_t*)arg1)->prop1; // cast
}
Is there any (common) scenario where it would be unsafe to use sometype_t * instead of void *?
int some_method(sometype_t *arg1) {
arg1->prop1;
}
The pointer isn't passed across ABIs or into 3rd-party libraries; it stays entirely within C++ code that we own.
It's usually not a good choice, but the only situation I'm aware of where this really make sense is if you want to have stateful callbacks passed into a function, without using templates:
void takes_callback(void(*f)(void*), void * data);
Basically the gist is that since you aren't using templates, you have to fix the function signature you accept (of course, it can and often does take other arguments and return something as well). If you just call the function with your own parameters though, the function can only hold state between calls via global variables. So instead the contract for takes_callback promises to call f with data as a parameter.
So, if you wanted to use some_method as a callback in such an API, you would have to have it take void*, and do the cast internally. Obviously, you are throwing away type safety here, and if you happen to call takes_callback with &somemethod and a pointer to anything that's not a sometype_t you have UB.
Having a C ABI is one reason to avoid templates, but it's not the only one. Maybe they were worried about code bloat, or wanted to keep the implementation in a .so so that versions could be upgraded without recompiling, etc.
The obvious common scenario that immediately comes to mind is callbacks for some functions from C standard library.
For example, the proper way to write the comparison callback for std::qsort is to declare the function with two const void * arguments and then cast them to proper specific pointer types inside the callback.
Replacing these const void * parameters with specifically-typed pointers will simply prevent the code from compiling.

Implementing message in c++

As you know, objective-c uses message expression to call member function(method), which means you can dynamically call member function in run-time.
I wanted to implement this message expression in c++ as class. So any classes can use message expression by inheriting and registering the their member function.
Here's simple example for what I'm trying to do.
in SomeClass.cpp
// class SomeeClass : public MyMessageExpression
type SomeClass::method_name_of_SomeClass(){
//code..
registerFunc(method_name_of_SomeClass) //registerFunc will add the function pointer into the function table
}
And finally you can use like this,
SomeClass.sendMessge("method_name_of_SomeClass");
The problem I couldn't solve is that how I'm going to cast void pointer into mothod_name_of_SomeClass's function pointer in run-time. How can I set variable function pointer in function table?
In case mothod_name_of_SomeClas uses stdcall calling convention How can I implement this class?
Here is something that works that may be close enough for you:
#include <map>
#include <iostream>
template<typename C>
struct MessageExpression
{
std::map<std::string,void(C::*)(void)> functions;
void registerFunc(std::string name,void(C::*function)(void))
{ functions[name]=function; }
void sendMesg(std::string name)
{ (static_cast<C*>(this)->*functions[name])(); }
};
struct SomeClass : public MessageExpression<SomeClass>
{
void method1() { std::cout << "method1" << std::endl; };
void method2() { std::cout << "method2" << std::endl; };
};
int main()
{
SomeClass s;
s.registerFunc("method1",&SomeClass::method1);
s.registerFunc("method2",&SomeClass::method2);
s.sendMesg("method1");
s.sendMesg("method2");
}
You can store a void pointer in an array of void pointers but at some point you need to convert it back to the correct member function pointer. And since that is done in MessageExpression anyway you may as well store the correct kind of pointer in a proper map.
You need to pass &SomeClass::method1 to registerFunc because the compiler won't know about method1 unless you say what namespace it is in. I am also passing the string - you could use a preprocessor macro to stringify the function name if you want.
The other thing you could do is store std::function in the map. But then you need to bind the this pointer just before calling it. I don't see the advantage here - it may make more sense if you bound the this pointer before storing it in the map..
so basically you have several levels that you can tackle this at...
Ignore it, when in rome do as romans do, use virtual methods and c++ paradigms
Use Objective-C++, this is useful as a shim between Mac OSX gui and a c++ library
Use strings as something like selectors... and sort of mock out NSInvocation, use a variadic method like MyObject::performMethodWithArguments(std::string methodName, ...) ... this would be logic heavy and sort of painful
probably just learn about virtual methods and function pointers.

What are pointers to class members used for?

I have read about pointers to class members, but I have never seen them being used in any practical applications. Can someone explain what are the use cases of such pointers? Is it really necessary to have such pointers?
Eg.
class abc
{
public:
int a;
abc(int val) { a = val; }
};
int main()
{
int abc::*data;
abc obj(5);
data = &abc::a;
cout << "Value of a is " << obj.*data << endl;
return 0;
}
In the above eg. why is the value of 'a' accessed in this manner? What is the advantage of using pointers to class members?
The biggest advantage of a pointer-to-member or pointer-to-member-function is that you
don't have to bind to a specific instance right away
don't need to place any restrictions on the member names, only the type has to match.
This can be used for e.g. call-backs or abstract algorithms:
std::map<int,int> m;
m.insert(std::make_pair(1,2));
m.insert(std::make_pair(3,4));
m.insert(std::make_pair(5,6));
std::ptrdiff_t s =
std::count_if(m.begin(), m.end(),
boost::bind(&std::map<int,int>::value_type::first, _1) > 2);
std::cout << s << std::endl; // 2
Note that Boost.Bind, Boost.Function and their TR1 equivalents already encapsulate that nicely for you. To a certain degree the current standard also includes tools like std::mem_fun in <functional>.
If you have used MFC, you will see pointers to member function concept is heavily used (internally)
DECLARE_MESSAGE_MAP, BEGIN_MESSAGE_MAP, END_MESSAGE_MAP
See Message Maps
The question I suppose is: "what does pointer to member data add over simple pointer to data?" and the only answer I can think of is a level of explicit meaning: we are pointing at data in this class.
Now I can see some value in what is effectively some additional documentation of intent. One example I've seen that might be quite powerful is when our "class" is actually a legacy C struct. Now we have no local methods of that struct, so having some pointers that are explicitly associated with that struct may well make our code clearer.
Pointer-to-member is, like all C++ features, just syntactic sugar for something you could already have done in pure C.
Pointers-to-member-variable are pretty simple. One use case is if you wanted to write a (template) function that could sort an array of structures by any field. By passing in a pointer-to-member, you can retrieve some specified field of any instance of the structure without having to hard-code the field. Of course a functor that accepts a structure pointer and returns the field value could have been used instead.
Pointers-to-member-function are a little more complicated. At first glance, they are just like ordinary function pointers that know how to pass the hidden 'this' pointer. But virtual functions make a simple idea pretty complicated.
And virtual base classes make all pointers-to-member awfully complicated. It's not something you'd want to code yourself using simple C constructs. But the complex cases are rare.

What is the point of function pointers?

I have trouble seeing the utility of function pointers. I guess it may be useful in some cases (they exist, after all), but I can't think of a case where it's better or unavoidable to use a function pointer.
Could you give some example of good use of function pointers (in C or C++)?
Most examples boil down to callbacks: You call a function f() passing the address of another function g(), and f() calls g() for some specific task. If you pass f() the address of h() instead, then f() will call back h() instead.
Basically, this is a way to parametrize a function: Some part of its behavior is not hard-coded into f(), but into the callback function. Callers can make f() behave differently by passing different callback functions. A classic is qsort() from the C standard library that takes its sorting criterion as a pointer to a comparison function.
In C++, this is often done using function objects (also called functors). These are objects that overload the function call operator, so you can call them as if they were a function. Example:
class functor {
public:
void operator()(int i) {std::cout << "the answer is: " << i << '\n';}
};
functor f;
f(42);
The idea behind this is that, unlike a function pointer, a function object can carry not only an algorithm, but also data:
class functor {
public:
functor(const std::string& prompt) : prompt_(prompt) {}
void operator()(int i) {std::cout << prompt_ << i << '\n';}
private:
std::string prompt_;
};
functor f("the answer is: ");
f(42);
Another advantage is that it is sometimes easier to inline calls to function objects than calls through function pointers. This is a reason why sorting in C++ is sometimes faster than sorting in C.
Well, I generally use them (professionally) in jump tables (see also this StackOverflow question).
Jump tables are commonly (but not exclusively) used in finite state machines to make them data driven. Instead of nested switch/case
switch (state)
case A:
switch (event):
case e1: ....
case e2: ....
case B:
switch (event):
case e3: ....
case e1: ....
you can make a 2d array of function pointers and just call handleEvent[state][event]
Examples:
Custom sorting/searches
Different
patterns (like Strategy, Observer)
Callbacks
The "classic" example for the usefulness of function pointers is the C library qsort() function, which implements a Quick Sort. In order to be universal for any and all data structures the user may come up with, it takes a couple of void pointers to sortable data and a pointer to a function that knows how to compare two elements of these data structures. This allows us to create our function of choice for the job, and in fact even allows for choosing the comparison function at run time, e.g. for sorting ascending or descending.
Agree with all of the above, plus....
When you load a dll dynamically at runtime you'll need function pointers to call the functions.
In C, the classic use is the qsort function, where the fourth parameter is pointer to a function to use to perform the ordering within the sort. In C++, one would tend to use functors (objects that look like functions) for this kind of thing.
I am going to go against the current here.
In C, function pointers are the only way to implement customization, because there is no OO.
In C++, you can use either function pointers or functors (function objects) for the same result.
The functors have a number of advantages over raw function pointers, due to their object nature, notably:
They may present several overloads of the operator()
They can have state / reference to existing variables
They can be built on the spot (lambda and bind)
I personally prefer functors to function pointers (despite the boilerplate code), mostly because the syntax for function pointers can easily get hairy (from the Function Pointer Tutorial):
typedef float(*pt2Func)(float, float);
// defines a symbol pt2Func, pointer to a (float, float) -> float function
typedef int (TMyClass::*pt2Member)(float, char, char);
// defines a symbol pt2Member, pointer to a (float, char, char) -> int function
// belonging to the class TMyClass
The only time I have ever seen function pointers used where functors could not was in Boost.Spirit. They have utterly abused the syntax to pass an arbitrary number of parameters as a single template parameter.
typedef SpecialClass<float(float,float)> class_type;
But since variadic templates and lambdas are around the corner, I am not sure we will use function pointers in pure C++ code for long now.
I used function pointers recently to create an abstraction layer.
I have a program written in pure C that runs on embedded systems. It supports multiple hardware variants. Depending on the hardware I am running on, it needs to call different versions of some functions.
At initialization time, the program figures out what hardware it is running on and populates the function pointers. All of the higher-level routines in the program just call the functions referenced by pointers. I can add support for new hardware variants without touching the higher-level routines.
I used to use switch/case statements to select the proper function versions, but this became impractical as the program grew to support more and more hardware variants. I had to add case statements all over the place.
I also tried intermediate function layers to figure out which function to use, but they didn't help much. I still had to update case statements in multiple places whenever we added a new variant. With the function pointers, I only have to change the initialization function.
Function pointers can be used in C to create an interface against which to program. Depending on the specific functionality that is needed at runtime, a different implementation can be assigned to the function pointer.
My main use of them has been CALLBACKS: when you need to save information about a function to call later.
Say you're writing Bomberman. 5 seconds after the person drops the bomb, it should explode (call the explode() function).
Now there's 2 ways to do it. One way is by "probing" all bombs on the screen to see if they're ready to explode in the main loop.
foreach bomb in game
if bomb.boomtime()
bomb.explode()
Another way is to attach a callback to your clock system. When a bomb is planted, you add a callback to make it call bomb.explode() when the time is right.
// user placed a bomb
Bomb* bomb = new Bomb()
make callback( function=bomb.explode, time=5 seconds ) ;
// IN the main loop:
foreach callback in callbacks
if callback.timeToRun
callback.function()
Here callback.function() can be any function, because it is a function pointer.
Like Rich said above, it is very usual for functions pointers in Windows to reference some address that stores function.
When you programming in C language on Windows platform you basically load some DLL file in primary memory(using LoadLibrary) and to use the functions stored in DLL you need to create functions pointers and point to these address (using GetProcAddress).
References:
LoadLibrary
GetProcAddress
Use of function pointer
To call function dynamically based on user input.
By creating a map of string and function pointer in this case.
#include<iostream>
#include<map>
using namespace std;
//typedef map<string, int (*)(int x, int y) > funMap;
#define funMap map<string, int (*)(int, int)>
funMap objFunMap;
int Add(int x, int y)
{
return x+y;
}
int Sub(int x, int y)
{
return x-y;
}
int Multi(int x, int y)
{
return x*y;
}
void initializeFunc()
{
objFunMap["Add"]=Add;
objFunMap["Sub"]=Sub;
objFunMap["Multi"]=Multi;
}
int main()
{
initializeFunc();
while(1)
{
string func;
cout<<"Enter your choice( 1. Add 2. Sub 3. Multi) : ";
int no, a, b;
cin>>no;
if(no==1)
func = "Add";
else if(no==2)
func = "Sub";
else if(no==3)
func = "Multi";
else
break;
cout<<"\nEnter 2 no :";
cin>>a>>b;
//function is called using function pointer based on user input
//If user input is 2, and a=10, b=3 then below line will expand as "objFuncMap["Sub"](10, 3)"
int ret = objFunMap[func](a, b);
cout<<ret<<endl;
}
return 0;
}
This way we have used function pointer in our actual company code.
You may write 'n' number of function and call them using this method.
OUTPUT:
Enter your choice( 1. Add 2. Sub 3. Multi) : 1
Enter 2 no :2 4
6
Enter your choice( 1. Add 2. Sub 3. Multi) : 2
Enter 2 no : 10 3
7
Enter your choice( 1. Add 2. Sub 3. Multi) : 3
Enter 2 no : 3 6
18
A different perspective, in addition to other good answers here:
In C, you only use function pointers, not (directly) functions.
I mean, you write functions, but you cant manipulate functions. There's no run-time representation of a function as such which you are able to use. You can't even call "a function". When you write:
my_function(my_arg);
what you're actually saying is "perform a call to the my_function pointer with the specified argument". You're making a call via a function pointer. This decay to function pointer means that the following commands are equivalent to the previous function call:
(&my_function)(my_arg);
(*my_function)(my_arg);
(**my_function)(my_arg);
(&**my_function)(my_arg);
(***my_function)(my_arg);
and so on (thanks #LuuVinhPhuc).
So, you're already using function pointers as values. Obviously you would want to have variables for those values - and here is where all the uses other metion come in: Polymorphism/customization (like in qsort), callbacks, jump tables etc.
In C++ things are a bit more complicated, since we have lambdas, and objects with operator(), and even an std::function class, but the principle is still mostly the same.
I use function pointers extensively, for emulating microprocessors that have 1-byte opcodes. An array of 256 function pointers is the natural way to implement this.
For OO languages, to perform polymorphic calls behind the scenes (this is also valid for C up to some point I guess).
Moreover, they're very useful to inject different behaviour to another function (foo) at runtime. That makes function foo higher-order function. Besides it's flexibility, that makes the foo code more readable since it let's you pull that extra logic of "if-else" out of it.
It enables many other useful things in Python like generators, closures etc.
One use of function pointer could be where we may not want to modify the code where the function is getting called (meaning thereby the call might be conditional and under different conditions, we need to do different sort of processing).
Here the function pointers are very handy, since we do not need to modify the code at the the place where the function is getting called. We simply call the function using the function pointer with appropriate arguments.
The function pointer can be made to point to different functions conditionally. (This can be done somewhere during initialization phase). Moreover the above model is very helpful, if we are not in position to modify the code where it is getting called (suppose it's a library API we can't modify). The API uses a function pointer for calling the appropriate user defined function.
I'll try to give a somewhat comprehensive list here:
Callbacks: Customize some (library) functionality with user supplied code. Prime example is qsort(), but also useful to handle events (like a button calling a callback when it's clicked), or necessary to start a thread (pthread_create()).
Polymorphism: The vtable in a C++ class is nothing but a table of function pointers. And a C program may also choose to provide a vtable for some of its objects:
struct Base;
struct Base_vtable {
void (*destruct)(struct Base* me);
};
struct Base {
struct Base_vtable* vtable;
};
struct Derived;
struct Derived_vtable {
struct Base_vtable;
void (*frobnicate)(struct Derived* me);
};
struct Derived {
struct Base;
int bar, baz;
}
The constructor of Derived would then set its vtable member variable to a global object with the derived's class's implementations of destruct and frobnicate, and code that needed to destruct a struct Base* would simply call base->vtable->destruct(base), which would call the correct version of the destructor, independent of which derived class base actually points to.
Without function pointers, polymorphism would need to be coded out with an army of switch constructs like
switch(me->type) {
case TYPE_BASE: base_implementation(); break;
case TYPE_DERIVED1: derived1_implementation(); break;
case TYPE_DERIVED2: derived2_implementation(); break;
case TYPE_DERIVED3: derived3_implementation(); break;
}
This gets rather unwieldy rather quickly.
Dynamically loaded code: When a program loads a module into memory and tries to call into its code, it must go through a function pointer.
All the uses of function pointers that I've seen fall squarely into one of these three broad classes.
They enhance re-use and modularization of code thus making code more maintainable, readable and less prone to errors.
With function pointers:
Note how we have an iterator method that gets passed to it a function pointer. This function pointer tells us what we should do with each elements in the list.
#include <iostream>
#include <vector>
int square(int x) {
return x * x;
}
int root(int x) {
return sqrt(x);
}
int negative(int x) {
return -x;
}
std::vector<int> listIterator(std::vector<int> list, int (*itemOperation)(int)) {
for (int i = 0; i < list.size(); i++) {
list[i] = itemOperation(list[i]);
}
return list;
}
int main() {
std::vector<int> list = { 9, 16, 4, 25 };
for (int i : listIterator(list, square)) {
std::cout << i << ' ';
}
std::cout << std::endl;
for (int i : listIterator(list, root)) {
std::cout << i << ' ';
}
std::cout << std::endl;
for (int i : listIterator(list, negative)) {
std::cout << i << ' ';
}
return 0;
}
Without function pointers:
Without function pointers, you would need to include an iterator in each of the square, root and negative methods.

Why override operator()?

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?
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");
Many have answered that it makes a functor, without telling one big reason why a functor is better than a plain old function.
The answer is that a functor can have state. Consider a summing function - it needs to keep a running total.
class Sum
{
public:
Sum() : m_total(0)
{
}
void operator()(int value)
{
m_total += value;
}
int m_total;
};
You may also look over the C++ faq's Matrix example. There are good uses for doing it but it of course depends on what you are trying to accomplish.
The use of operator() to form functors in C++ is related to functional programming paradigms that usually make use of a similar concept: closures.
A functor is not a function, so you cannot overload it.
Your co-worker is correct though that the overloading of operator() is used to create "functors" - objects that can be called like functions. In combination with templates expecting "function-like" arguments this can be quite powerful because the distinction between an object and a function becomes blurred.
As other posters have said: functors have an advantage over plain functions in that they can have state. This state can be used over a single iteration (for example to calculate the sum of all elements in a container) or over multiple iterations (for example to find all elements in multiple containers satisfying particular criteria).
Start using std::for_each, std::find_if, etc. more often in your code and you'll see why it's handy to have the ability to overload the () operator. It also allows functors and tasks to have a clear calling method that won't conflict with the names of other methods in the derived classes.
Functors are basically like function pointers. They are generally intended to be copyable (like function pointers) and invoked in the same way as function pointers. The main benefit is that when you have an algorithm that works with a templated functor, the function call to operator() can be inlined. However, function pointers are still valid functors.
One strength I can see, however this can be discussed, is that the signature of operator() looks and behaves the same across different types. If we had a class Reporter which had a member method report(..), and then another class Writer, which had a member method write(..), we would have to write adapters if we would like to use both classes as perhaps a template component of some other system. All it would care about is to pass on strings or what have you. Without the use of operator() overloading or writing special type adapters, you couldn't do stuff like
T t;
t.write("Hello world");
because T has a requirement that there is a member function called write which accepts anything implicitly castable to const char* (or rather const char[]). The Reporter class in this example doesn't have that, so having T (a template parameter) being Reporter would fail to compile.
However, as far I can see this would work with different types
T t;
t("Hello world");
though, it still explicitly requires that the type T has such an operator defined, so we still have a requirement on T. Personally, I don't think it's too wierd with functors as they are commonly used but I would rather see other mechanisms for this behavior. In languages like C# you could just pass in a delegate. I am not too familiar with member function pointers in C++ but I could imagine you could achieve the same behaviour there aswell.
Other than syntatic sugar behaviour I don't really see the strengths of operator overloading to perform such tasks.
I am sure there are more knowingly people who have better reasons than I have but I thought I'd lay out my opinion for the rest of you to share.
Another co-worker pointed out that it could be a way to disguise functor objects as functions. For example, this:
my_functor();
Is really:
my_functor.operator()();
So does that mean this:
my_functor(int n, float f){ ... };
Can be used to overload this as well?
my_functor.operator()(int n, float f){ ... };
Other posts have done a good job describing how operator() works and why it can be useful.
I've recently been using some code that makes very extensive use of operator(). A disadvantage of overloading this operator is that some IDEs become less effective tools as a result. In Visual Studio, you can usually right-click on a method call to go to the method definition and/or declaration. Unfortunately, VS isn't smart enough to index operator() calls. Especially in complex code with overridden operator() definitions all over the place, it can be very difficult to figure out what piece of code is executing where. In several cases, I found I had to run the code and trace through it to find what was actually running.
Overloading operator() can make the class object calling convention easier. Functor is one of the applications of operator() overloading.
It is easy to get confused between Functor and user-defined conversion function.
Below 2 examples show the difference between
1. Functor
2. User-defined conversion function
1. Functor:
struct A {
int t = 0;
int operator()(int i) { return t += i; } // must have return type or void
};
int main() {
A a;
cout << a(3); // 3
cout << a(4); // 7 (Not 4 bcos it maintaines state!!!)
}
2. User-defined conversion function:
struct A {
int t = 3;
operator int() { return t; } // user-defined conversion function
// Return type is NOT needed (incl. void)
};
int main() {
cout << A(); // 3 - converts the object{i:3} into integer 3
A a;
cout << a; // 3 - converts the object{i:3} into integer 3
}