2013-08-22 6 views
1

다른 유형의 데이터를 전송하는 데 필요한 일부 반복 기능에 대한 템플릿 클래스를 만들려고합니다. 하지만, 내 문제는 (내가 생각하는) InterfacePublisher :: addSubscription() 부스트 :: signals2 :: 신호를 사용한다 기능을 정말 :()를 연결합니다.Signals2는 템플릿과 함께 사용합니다.

처럼 함수는 기본 클래스의 위치를 ​​취합니다. 파생 클래스가이를 재정의하더라도 마찬가지입니다. 나는 이것을위한 고침이있을 것이라고 확신하지만, 오랫동안 그것으로 붙어있다.

아래 코드를 붙여 넣습니다. ,

#include <string> 
#include <iostream> 

#include <boost/lambda/lambda.hpp> 
#include <boost/signals2/signal.hpp> 
#include <boost/signals2/signal_base.hpp> 
#include <boost/signals2/slot.hpp> 
#include <boost/signals2/slot_base.hpp> 

template <class T> 
class InterfaceSubscriber 
{ 
public: 
    InterfaceSubscriber(const std::string& name) 
     : mName   (name) {} 

    virtual void onData (const std::string& source, T& data) 
    { 
     std::cout << "InterfaceSubscriber::onData::BASE SHOULD BE IGNORED\n"; 
    } 
protected: 
    const std::string mName; 
}; 




template <class T> 
class InterfacePublisher 
{ 
public: 
    InterfacePublisher(const std::string& publisherName) 
     : mPublisherName   (publisherName) 
    { 
    } 

    void publish(T& data) 
    { 
     mSignalArgs(mPublisherName, data); 
    } 

    void addSubscription (InterfaceSubscriber<T>* subsc) 
    { 
     // The section where I think problem is. There is where the solution should be 
     mSignalArgs.connect(std::bind (InterfaceSubscriber<T>::onData , *subsc, std::placeholders::_1, std::placeholders::_2)); 
    } 

protected: 
    boost::signals2::signal<void (const std::string& publisherName, T& data)> mSignalArgs; 
    const std::string mPublisherName; 
}; 

class StringSubscriber : public InterfaceSubscriber<std::string> 
{ 
public: 
    StringSubscriber (const std::string& subscName) : InterfaceSubscriber(subscName) {} 
    void onData (const std::string& source, std::string&  data) override 
    { 
     std::cout << mName << ":[" << source << "]Received string of value: " << data << std::endl; 
    } 
}; 


class StringPublisher : public InterfacePublisher<std::string> 
{ 
public: 
    StringPublisher (const std::string& name) : InterfacePublisher(name) {} 
}; 


int main() 
{ 
    StringSubscriber subscriber1("String_Subscriber_1"); 
    StringSubscriber subscriber2("String_Subscriber_2"); 
    StringPublisher publisher("Publisher_Of_String"); 
    publisher.addSubscription(&subscriber1); 
    publisher.addSubscription(&subscriber2); 
    std::string str = "Hello World"; 

    // This should lead to StringSubscriber::onData being called, but instead ends up calling InterfaceSubscriber<T>::onData 
    publisher.publish(str); 

} 

답변

0

StringSubscriberstd::bind 펑터의 건설 기간 동안 슬라이스되고에서 실행 InterfaceSubscriber<T>::onData() 결과 : 아이디어는 템플릿을 통해 클래스 이름을 하드 코딩하지 않고 StringSubscriber에 StringPublisher에서 문자열을 전달하는 것입니다 런타임 유형이 인 오브젝트가 InterfacePublisher<T>::addSubscription()에 제공된 오브젝트의 런타임 유형이 아닌 오브젝트.

void addSubscription(InterfaceSubscriber<T>* subsc) 
{ 
    mSignalArgs.connect(std::bind(&InterfaceSubscriber<T>::onData, 
           *subsc, ...); 
          // ^~~ sliced 
} 

이 문제를 해결하려면 직접 포인터를 전달하거나 std::ref 개체를 인스턴스로 전달하십시오.

void addSubscription(InterfaceSubscriber<T>* subsc) 
{ 
    mSignalArgs.connect(std::bind(&InterfaceSubscriber<T>::onData, 
           subsc, ...); 
          // ^~~ pointer 
} 

또는

void addSubscription(InterfaceSubscriber<T>* subsc) 
{ 
    mSignalArgs.connect(std::bind(&InterfaceSubscriber<T>::onData, 
           std::ref(*subsc), ...); 
          // ^~~ reference 
} 
+0

감사합니다. 다음 줄은 내 문제를 해결했습니다 :
mSignalArgs.connect (std :: bind (& InterfaceSubscriber :: onData, std :: ref (* subsc), std :: placeholders :: _ 1, std :: placeholders :: _ 2)); 나는 어제 많은 시간을 std :: ref로 시도했지만 그 위에 잠들 필요가 있다고 생각한다. '&'기호 btw에 유의하십시오. –

+0

@BrainCracker : 아, 그래, 난 컴파일러를 사용할 수 없어, 그냥 슬라이스를 발견했다. 적절한 구문으로 답변을 업데이트했습니다. –

관련 문제