Templated "Listener" handler ambiguity problem
I'm using JUCE as a x-platform framework, and I'm using template listener classes to map button/combobox etc. callbacks to certain handler functions. Since the different widgets have their own callback function name, I use the following structure:
template<typename Type, typename Widget>
class ListenerBase : p开发者_开发技巧ublic Widget::Listener
{
public:
typedef void (Type::*TCallbackType)(void);
protected:
void notifyCallback(Widget* notifier)
{
...
}
void addHandler(Widget* notifier, TCallbackType callback)
{
notifier->addListener(this);
...
}
};
template<typename Type>
class ButtonListenerHandler : public ListenerBase<Type, Button>
{
protected:
void buttonClicked(Button* btn)
{
notifyCallback(btn);
}
};
template<typename Type>
class LabelListenerHandler : public ListenerBase<Type, Label>
{
protected:
void labelTextChanged(Label* lbl)
{
notifyCallback(lbl);
}
};
And it works fine, as long as I use only one of the handler specializations in my class. As soon as I use more than one, VC++ 2008 complains of ambiguity between the addHandler calls as if the compiler cannot distiguish between addHandler(Button*, ...) and addHandler(Label*, ...) !! These functions are of different prototypes due to being templatized, so I have no idea why the compiler is giving me a hard time. Ideas ?
Edit due to requests:
A class with different listeners may look like:
class MyClass : public ButtonListenerHandler<MyClass>
, public LabelListenerHandler<MyClass>
{
...
void buttonHandlerFunction();
void labelHandlerFunction();
Button* m_btn;
Label* m_label;
};
A where the error occurs:
MyClass::MyClass()
{
...
addHandler(m_btn, &MyClass::buttonHandlerFunction); <<< error
addHandler(m_label, &MyClass::labelHandlerFunction); <<< error
}
And the error is:
1>MyClass.cpp(287) : error C2385: ambiguous access of 'addHandler'
1> could be the 'addHandler' in base 'ListenerBase<MyClass,juce::Button>'
1> or could be the 'addHandler' in base 'ListenerBase<MyClass,juce::Label>'
Edit
Okay, after rethinking everything, the problem lies with ListenerBase<MyClass, Button>
and ListenerBase<MyClass, Label>
each defining an addHandler
function, which because of inheritance doesn't seem to count as overloading, even though they have different signatures (one with a Button*
parameter, the other with a Label*
one). One possible fix I found for this is to fully qualify the call to addHandler
, a bit verbose and maybe not what was really desired, but it works (for convenience, I typedef
'd the base classes):
template<class Type>
class ButtonListenerHandler : public ListenerBase<Type, Button>{
public:
typedef ListenerBase<Type, Button> ButtonListenerBase;
};
template<class Type>
class LabelListenerHandler : public ListenerBase<Type, Label>{
public:
typedef ListenerBase<Type, Label> LabelListenerBase;
};
class MyClass : public ButtonListenerHandler<MyClass>,
public LabelListenerHandler<MyClass>{
public:
void buttonHandlerFunction();
void labelHandlerFunction();
MyClass(){
ButtonListenerHandler<MyClass>::addHandler(m_btn, &MyClass::buttonHandlerFunction);
LabelListenerHandler<MyClass>::addHandler(m_label, &MyClass::labelHandlerFunction);
}
private:
Button* m_btn;
Label* m_label;
};
'nother Edit
Thanks to the fast answer to my question here, I can give it another edit. The using
method mentioned there also applies to your problem. :)
class MyClass : public ButtonListenerHandler<MyClass>,
public LabelListenerHandler<MyClass>{
public:
using ButtonListenerHandler<MyClass>::addHandler;
using LabelListener<MyClass>::addHandler;
void buttonHandlerFunction(){
}
void labelHandlerFunction(){
}
MyClass(){
addHandler(m_btn, &MyClass::buttonHandlerFunction);
addHandler(m_label, &MyClass::labelHandlerFunction);
}
private:
Button* m_btn;
Label* m_label;
};
精彩评论