Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to upcast a function pointer?

I have base classes Object and an Event

class Object
{
//...
};

class Event
{
};

And a typedef for a function pointer

typedef void (Object::*PF) (Event*);

And an unrelated class which stores two pointers

class Dispatcher
{
public:
    Dispatcher (Object* obj, PF pf) : _obj (obj), _pf (pf)

    void call (Event* event)
    {
        _obj->*pf (event);
    }

    Object* _obj;
    PF _pf;
};

I then have a concrete object and a concrete event

class ConcreteEvent : public Event
{
};

class ConcreteObject : public Object
{
public:
   void handle (ConcreteEvent* event)
   {
      // Do something specific for ConcreteEvent
   }
};

And then call it like this

ConcreteObject* obj = new ConcreteObject();
Dispatcher dispatcher (obj, static_cast<PF>(&ConcreteObject::handle));

ConcreteEvent* event = new ConcreteEvent ();
dispatcher.call (event);

I guarantee that the dispatcher will always be called with a correct event, i.e. I will not call a dispatcher and pass it ConcreteEvent when the function pointer it encapsulates in fact takes SomeOtherConcreteEvent

The question is: Is this guaranteed to work? Is certainly works fine in gcc 4.7 on both linux and mingw.


1 Answers

From the C++11 standard, section 4.11.2:

A prvalue of type “pointer to member of B of type cv T”, where B is a class type, can be converted to a prvalue of type “pointer to member of D of type cv T”, where D is a derived class (Clause 10) of B. If B is an inaccessible (Clause 11), ambiguous (10.2), or virtual (10.1) base class of D, or a base class of a virtual base class of D, a program that necessitates this conversion is ill-formed. The result of the conversion refers to the same member as the pointer to member before the conversion took place, but it refers to the base class member as if it were a member of the derived class.

So yes, this should be safe.

Edit: so if you actually meant downcasting: that's also legal, according to C++11 5.2.9.12:

A prvalue of type “pointer to member of D of type cv1 T” can be converted to a prvalue of type “pointer to member of B” of type cv2 T, where B is a base class (Clause 10) of D, if a valid standard conversion from “pointer to member of B of type T” to “pointer to member of D of type T” exists (4.11), and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. 69


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!