Downcasting non-template base class to templated derived class: is it possible?

帅比萌擦擦* 提交于 2019-12-05 09:01:24

In general when closing templates, you need to make sure that > are separated by spaces so the compiler doesn't parse them as a right-shift operator.

Here you're trying to static cast a reference to a non-reference, which even if it worked could invoke object slicing. You need to static cast to a derived reference.

bool  equal(const BaseEventHandler& other) const
{
    EventHandler<T,TEvent>& derivedOther = static_cast<EventHandler<T,TEvent>&>(other);
    return derivedOther.getInstance() == this->getInstance() && derivedOther.getCallback()==this->getCallback();
}

Thank you both, Mark and Steve: that led me on the right direction. There was another problem since I was trying to cast a const to a non-const but this one was much easier to spot after that.

This is what I've got in the end, after a few tweaks:

void EventManager::unregisterHandler(EventHandlerPtr hdl,TEventType evtType)
{
    if (!mEventHandlers.empty() && mEventHandlers.count(evtType))
    {
        TEventHandlerList::iterator newEnd=remove_if(mEventHandlers[evtType].begin(),
            mEventHandlers[evtType].end(),EventHandlerComparisonFunctor(hdl));
        mEventHandlers[evtType].erase(newEnd,mEventHandlers[evtType].end());
        if (mEventHandlers[evtType].size()==0)
            mEventHandlers.erase(evtType);
    }
}

I changed remove with remove_if because boost::shared_ptr implements the == operator by directly comparing the pointers, instead of their contents. The terribly-named EventHandlerComparisonFunctor is now the responsible to perform the equality check.

It is implemented like this:

class EventHandlerComparisonFunctor
{
private:
    EventHandlerPtr mInstance;
public:
    EventHandlerComparisonFunctor(EventHandlerPtr instance):mInstance(instance){}
    bool operator()(EventHandlerPtr& other) const
    {
        return *(mInstance.get())==*(other.get());
    }
};

And finally, the equal method in EventHandler (@gf, the method was indeed declared in the EventHandler template, but for some reason I cut it out to paste the class code in here, my mistake)

bool equal(const BaseEventHandler& other) const
{
    EventHandler<T,TEvent>& derivedOther = static_cast<EventHandler<T,TEvent>&>(const_cast<BaseEventHandler&>(other));
    return derivedOther.getInstance() == this->getInstance() && derivedOther.getCallback()==this->getCallback();
}

Everything is working OK now.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!