Шаблонная проблема неоднозначности обработчика «Слушателя» - PullRequest
2 голосов
/ 20 марта 2011

Я использую JUCE в качестве платформы x-платформы и использую классы слушателей шаблонов для сопоставления обратных вызовов кнопки / комбинированного списка и т. Д. С определенными функциями-обработчиками. Поскольку разные виджеты имеют собственное имя функции обратного вызова, я использую следующую структуру:

template<typename Type, typename Widget>
class ListenerBase : public 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);
  }
};

И это прекрасно работает, пока я использую только одну из специализаций обработчиков в моем классе. Как только я использую более одного, VC ++ 2008 жалуется на неоднозначность между вызовами addHandler, как будто компилятор не может различить addHandler (Button *, ...) и addHandler (Label *, ...) !! Эти функции имеют разные прототипы из-за того, что их шаблонизируют, поэтому я понятия не имею, почему компилятор доставляет мне неприятности. Идеи?

Изменить из-за запросов:

Класс с разными слушателями может выглядеть так:

class MyClass : public ButtonListenerHandler<MyClass>
              , public LabelListenerHandler<MyClass>
{
...
   void buttonHandlerFunction();
   void labelHandlerFunction();

   Button* m_btn;
   Label* m_label;
};

A, где возникает ошибка:

MyClass::MyClass()
{
...
   addHandler(m_btn, &MyClass::buttonHandlerFunction);  <<< error
   addHandler(m_label, &MyClass::labelHandlerFunction);  <<< error
}

И ошибка:

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>'

1 Ответ

0 голосов
/ 20 марта 2011

Редактировать
Хорошо, после переосмысления всего, проблема заключается в ListenerBase<MyClass, Button> и ListenerBase<MyClass, Label>, каждая из которых определяет функцию addHandler, которая из-за наследования не считается перегрузкой, даже если у них разные подписи (одна с Button* параметр, другой с Label* один). Одно возможное исправление, которое я нашел для этого, состоит в том, чтобы полностью квалифицировать вызов к addHandler, немного многословно и, возможно, не то, что было действительно желательно, но это работает (для удобства, я typedef сделал базовые классы):

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;
};

'Редактировать
Благодаря быстрому ответу на мой вопрос здесь , я могу дать ему еще одно редактирование. Упомянутый там метод using также относится к вашей проблеме. :)

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;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...