Как реализовать шаблонный класс с зависимым от шаблона сигнальным членом от boost? - PullRequest
3 голосов
/ 06 сентября 2010

Я пытаюсь реализовать класс шаблона, который требует наличия члена-сигнала, который зависит от аргумента шаблона. Моей первой идеей было реализовать это так:

template<class T>
class SignalClass 
{
    typedef boost::signals2::signal<void (T &)> OnReceive;

public:
    SignalClass(const OnReceive::slot_type &_slot)
    {
       m_onReceive.cnnect(_slot);
    }
    virtual SignalClass(){};

    void Send(T &_val)
    {
       m_onReceive(_val);
    }
private:
    OnReceive m_onReceive;
};

Этот класс должен использоваться как:

class SignaledClass
{
public:
    SignaledClass(void)
    {   
       SignalClass<int>    var1(boost::bind(&SignaledClass::ReceiveINT, this));
       SignalClass<double> var2(boost::bind(&SignaledClass::ReceiveDOUBLE, this));
    }

   void ReceiveINT(int &_val)
   {
      ...
   }

   void ReceiveDOUBLE(double &_val)
   {
      ...
   }
}

(Кстати: я знаю, что нет смысла создавать объект SignalClass только внутри конструктора. Это просто для понимания моей проблемы.)

Для меня важно реализовать делегатоподобную концепцию с шаблоном в качестве параметра сигнала.

Проблема в том, что код конструктора не работает.

Но я нашел решение.

Если я дополнительно укажу typedef, например

typedef typename OnReceive::slot_type slot_type;

и используйте этот параметр для конструктора, например

PushInputSlot(const slot_type& _slot);

это работает. Но я понятия не имею, почему.

Я надеюсь, что кто-нибудь может мне помочь.

Thanx, Frank

P.S .: Я новичок в stackoverflow, поэтому я не знаком с правилами здесь. Надеюсь, я все сделал правильно ...; -) ....

1 Ответ

2 голосов
/ 08 сентября 2010

Вот причина, по которой добавляется typename (либо непосредственно в аргументе конструктора, либо в дополнительном определении типа):

Во-первых, тип OnReceive является так называемым «зависимым типом»,потому что это зависит от типа параметра шаблона.

Затем шаблоны обрабатываются в два этапа в компиляторе: первый этап - когда компилятор встречает исходный текст для шаблона, а второй этап - когдаШаблон фактически создан.На первом этапе обработки компилятор будет (должен) пытаться проверить, насколько это возможно, правильность определения шаблона, но он сталкивается с проблемой, когда дело касается зависимых типов.Поскольку зависимый тип зависит от параметров шаблона, компилятор не знает, как будет выглядеть фактический тип.В частности, при доступе к члену с помощью оператора :: компилятору требуется некоторая помощь, чтобы решить, должен ли член ссылаться на тип члена (typedef или вложенный класс) или нетипичный член (переменная, enum,так далее.).Эту проблему можно решить, добавив typename перед (полным) именем типа, если вы знаете, что оно должно ссылаться на тип.Другое место, где у компилятора могут возникнуть проблемы, - это различие между шаблоном-участником и элементом без шаблона, участвующим в сравнительном сравнении.Это решается добавлением ключевого слова template перед именем элемента-шаблона (сразу после оператора).

...