-1

I have seen a number of examples how to make a function pointer to a C++ class non-static member of a specific class type. However, I would have use for such pointer that would work for any type class. To demonstrate the idea, I wrote a pseudo example:

class A
{
    public:
    A(){} //constructor    
    void callMe() { /* do something */ }
};

class B
{
    public:
    B(){} //constructor    
    void callMe() { /* do something */ }
};


main()
{
    A aa;
    B bb;

    //pseudo part:
    generic_method_pointer_type p; //how to define the type of p?

    p=HOWTO;//set pointer p to point to A::callMe. How to do?

    p(aa); //A::callMe on instance aa gets called

    p=HOWTO;//set pointer p to point to B::callMe. How to do?

    p(bb); //B::callMe on instance bb gets called
}

Does this look possible?

I know C++11 has new tricks such as std::function for this. I did some experiments on std::function and found it too slow for a real-time app running on a small microcontroller. That is why I would prefer direct hard coded pointers which would cause minimum overhead.

Thank you for your advice!

TeroK
  • 103
  • 2
  • 10
  • Did you read the posts under the tags you provided, specifically under member-function-pointers? –  Mar 01 '17 at 23:41
  • Did couple of hours of searching all over the net. If you know a link to an answer, I'd appreciate that. – TeroK Mar 01 '17 at 23:43
  • 1
    What do you expect to happen if you set `p=&A::callMe;` and then do `p(bb);`? – aschepler Mar 01 '17 at 23:48
  • 1
    You need to know what kind of `this` to invoke the method on and that puts you in a sticky spot. if you want a generic function pointer that can hold anything, this can be done, but all type safety goes out the window. Your program becomes an accident waiting to happen unless you are very good and very, very careful. Have you considered discarding the exceptionally broad "amy" and having all of your classes you actually need to fit your problem extend a pure virtual base class that defines the function interface? – user4581301 Mar 02 '17 at 00:36
  • @aschepler that probably would not do any good, but not an issue as it's rather easily avoided. – TeroK Mar 02 '17 at 19:46
  • @user4581301 yes, I generally dislike function pointers due to all hazards out there, but they are irresistibly efficient when doing hard real time code. I've checked also virtual methods route: they translate into if/else if/else structure in assembly and it gets slower when more choices become available. Calling a pointer will not slow down no matter how many callback choices you have available. – TeroK Mar 02 '17 at 19:53

1 Answers1

0

Found one perfectly working solution from MBED project source codes (their FunctionPointer class):

Working example:

A foo;
FunctionPointer  cb;
cb.attach(&foo,&A::callMe);
for(i=0;i<100000000;i++) //callback overhead test
    cb.call();

The code inside FunctionPointer is not very obvious to me how it works. It memcpy some data etc. Any ideas if it could be simplified & made faster? It still causes significantly more overhead compared to a case where class type is fixed, such as:

A foo;
typedef void (A::*MethodPtr) ();
MethodPtr method = &A::callMe;
Foo *obj = &foo;
for(i=0;i<100000000;i++) //callback overhead test
    (obj->*method)();

The above method is about 4x faster compared to FunctionPointer method when callMe contains only asm("nop"). Some benchmarks on x86 & GCC:

  • direct call 205 ms
  • the above function pointer example 258 ms
  • FunctionPointer example 1049 ms
  • std::function 3951 ms

Any optimization ideas are very much appreciated!

TeroK
  • 103
  • 2
  • 10
  • Looking at `FPointer`, you can strip out all of the `c_callback` because you always have an object and if you trust yourself all of the NULL pointer checks. What's going on in here is the "all type safety goes out the window" stuff I was talking about above. You can pack in anything you want and after that pray you got it right because the compiler can't help you. – user4581301 Mar 02 '17 at 20:36
  • Found that MBED Callback class does this little bit more efficiently, but not very significant performance difference. Runs test in about 900ms. Removeing checking also saves few millisecs. – TeroK Mar 07 '17 at 23:57