views:

90

answers:

2

Im trying to compare the address of two functions for equality. Type of my stored function is known. This system normally works, consider the following code (written as sample not from the program):

virtual bool compare(void *fn2) {
  void (*fn)(int);

  if(fn==fn2)
     return true;
}

However when class functions came into consideration the same method doesn't work.

virtual bool compare(void *fn2) {
  void(__thiscall myclass::*fn)(int);
  void *fn2;

  if(fn==fn2)  //error C2440 type cast: cannot convert void* to void(__thiscall...
     return true;
}

These functions override a common base class' pure virtual function similar to following:

virtual bool compare(void*) = 0;

Since I cannot use template<> in virtual functions I am out of options. Is there a way (anyway) to unify class functions and regular functions?

Thanks in advance, Cem

+4  A: 

Posix requires the ability to convert function pointers to void*. Standard C++ does not support it.

Member function pointers are not pointers in the ordinary sense, they're more like offsets (even for a non-virtual member function).

Both implementations you show for compare would have Undefined Behavior even if the comparisions and casts were valid, because they fail to return anything in the case where the pointers don't compare equal. Instead of if(blah == bag){ return true; } just do return (blah == bah);.

The problems stem from casting away necessary type information. That's generally not a good idea. Why are you casting away the type information that you need?

Solution: (1) don't cast away necessary type information, and (2) redesign to get rid of that compare function. Also take note of Roger Pate's comment that it seems you're asking about a particular attempted solution rather then the problem. What is the problem?

Cheers & hth.,

Alf P. Steinbach
Sry, I was a bit vague, my aim is to write a bubbling event system. Its already working and is used, but to remove functions from the list I return indexes and using those indexes one can remove a function from the list. However, I wish to add an ability to remove a function by resupplying it. If member functions are stored as offsets there is no way to uniquely identify them (am I wrong?), therefore there is no way to implement this functionality.
Cem Kalyoncu
@Cem: If you are trying to identify by the function pointer alone, then no it is not unique. But usually you would also have stored the object on which the function will be called, and together it would be unique. However, a better approach would be to wrap the target and member function in a functor object. You can define an interface with pure virtual functions for invocation (i.e. `operator()` and comparison) and then use have a template class for the concrete instances. That's the typesafe way to solve this in C++.
Ben Voigt
I think i will create function which will try to convert base class to the sub class I want using dynamic_cast, if conversion is NULL compare is failed for sure, if not it will use non-common compare function using compare(void(__thiscall myclass::*fn)(int)) {...} function which can 1-1 compare them. Btw compare function knows which class to operate and compare (actually it has two arguments).
Cem Kalyoncu
+2  A: 

This doesn't work because member function pointers are not actually convertible to regular pointers- their size is undefined. In some implementations of some class hierarchies, the member function pointer can be five times the size of a regular pointer. How is this going to work with a comparison to void*?

DeadMG