1

I have a function Foo and a class CDelegate.

typedef void (*typeFctPtr)(void*);


void Foo(void* dummy)
{
  cout << "Foo\n";
}


class CDelegate 
{ 
  public:

  CDelegate (const typeFctPtr& f_ref_Wrapper, void* f_pvSubscriber) 
    : m_ref_Wrapper(f_ref_Wrapper), m_pvSubscriber(f_pvSubscriber) 
  {
  }

  inline void operator () () const
  {
    (*m_ref_Wrapper)(0);
  }

  inline void operator=(const CInterruptDelegate& D)
  {
  }

private:
  void* m_pvSubscriber;
  const typeFctPtr& m_ref_Wrapper;
};

A second class has a static member static CDelegate m_Delegate; which I initialize using the constructor like this:

CInterruptDelegate CSpi1::m_Delegate(FreeFunction, 0);

I want to call Foo by calling the ()operator of my static object: CSpi1::m_Delegate();

I get an exception at (*m_ref_Wrapper)(0); Is there something wrong with the syntax? I am not quite sure if what I try to do is possible at all. I have a working solution where the constructor of CDelegatedoes not take a const reference of a function pointer but the function pointer itself. I can then call the function in the ()operator without problems. I want to use a const reference because the function pointer call cannot be optimized and I hope the call via the const reference can because everything should be known at compile time.

4
  • Have you tried calling simply m_ref_Wrapper(0); ? Commented Jun 30, 2011 at 15:04
  • I'd be surprised if the optimiser is able to remove the indirect call with either a reference or a pointer. But an indirect call is really not that expensive. Commented Jun 30, 2011 at 15:13
  • @Cat Plus Plus, I use this mechanism for the interrupt handling in an embedded system. boost::function does everything I need but is kind of slow.. Also, the software is working with taking the argument as a function pointer. I want to optimize now by using a const reference... at least try to :) Commented Jul 1, 2011 at 6:33
  • @iammilind, I have, but it isn't working. @Alan Stokes, I thought it maybe can, because as I understand it the address must be known at compile time for passing a const ref to the constructor and define the members in the initializer list.. Isn't that enough for the compiler? I use this for calling ISRs, so if it is possible to speed things up I'd like to do so. Commented Jul 1, 2011 at 6:41

2 Answers 2

1

You're holding a reference to a pointer to a function (and the pointer is a temporary which has been destroyed by the time you use it, so things go badly wrong).

Try changing your typedef to be a function type:

typedef void typeFct(void*);
...
const typeFct & m_ref_Wrapper;

Then with your existing code you'll end up with a reference to a function, and you'll be fine. Or you could store a pointer to the function - const typeFct *.

And in either case the call can just be m_ref_Wrapper(0).

In general I prefer to typedef function types rather than pointer-to or reference-to, if only because the syntax is less ugly.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I can compile this and I don't get any run timer errors. But I get the warning warning C4180: qualifier applied to function type has no meaning; ignored for these lines: CDelegate(const typeFct& f_ref_Wrapper, void* f_pvSubscriber) and const typeFct& m_ref_Wrapper;
@Mirco Ah yes, my mistake. There shouldn't be a const applied to typeFct anywhere. const is great for data, meaningless for functions.
1

I believe that the problem is the declaration of the member:

const typeFctPtr& m_ref_Wrapper;

Instead, try to drop the &:

const typeFctPtr m_ref_Wrapper;

A reference must always reference another existing object. In this case, it will refer the temporary object created to hold the reference to the pointer at the time the constructor is called.

While we're at it, I would suggest that you should drop the reference from the constructor as well. The reason for this is that there is no gain when you work with scalar:s.

Another thing that would make your code more readable is if you would typedef the type of the function, rather than the pointer to the function. That way, it would be clear that you pass around a pointer.

The following is a cut-down version that summarized the changes I suggest above:

typedef void (typeFct)(void*);

class CDelegate
{
  public:

  CDelegate (typeFct * f_Wrapper, void* f_pvSubscriber)
    : m_ref_Wrapper(f_Wrapper), m_pvSubscriber(f_pvSubscriber) 
  {
  }

  inline void operator () () const
  {
    (*m_ref_Wrapper)(0);
  }

private:
  void* m_pvSubscriber;
  typeFct * m_ref_Wrapper;
};

2 Comments

Thanks! Btw, I learned something new from your post, I didn't know that you can make a reference to a function.
@Lindydancer, I think this is my working solution using a function pointer instead of using a reference to one - with the difference of the typedef. I will remember this and start to typedef the type of the function in the future :) Unfortunately I cannot +1 (still < 15) .. Thanks for helping

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.