2013-07-12 4 views
1

난 그냥 흥미로운 도전에 직면,의 그것을 함께 해결하자이 같은템플릿 클래스의 멤버 함수에 포인터를 전달하는 방법은 무엇입니까?

//Broker.h 
#pragma once 
#include <boost/shared_ptr.hpp> 
template<class AGENT_MSG_TYPE,class BUFFER_MSG_TYPE> 
class Broker 
{ 
public: 
    void messageReceiveCallback(boost::shared_ptr<ConnectionHandler>cnnHadler , std::string message){} 

}; 

와 연결 처리기 :

//ConnectionHandler.h 
#pragma once 
#include <boost/enable_shared_from_this.hpp> 
#include <iostream> 

//connection handler 
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember)) 

template<class A,class B> 
class Broker; 

class ConnectionHandler: public boost::enable_shared_from_this<ConnectionHandler> 
{ 
    typedef void (Broker<int,int>::*messageReceiveCallback)(boost::shared_ptr<ConnectionHandler>,std::string); 
    messageReceiveCallback receiveCallBack; 
    Broker<int,int> &theBroker; 
public: 

    ConnectionHandler(
      //... 
      Broker<int,int>& broker, 
      messageReceiveCallback callback 
      //,... 
      ); 
    void some_function(std::string incomingMessage); 
}; 

///////////////////ConnectionHandler.cpp 
#include "cnn.h" 
#include "Broker.h" 
ConnectionHandler::ConnectionHandler(
//... 
     Broker<int,int>& broker, messageReceiveCallback callback 
     //... 
     ) : 
     receiveCallBack(callback), theBroker(broker) { 

} 

void ConnectionHandler::some_function(std::string incomingMessage) { 
    CALL_MEMBER_FN(theBroker, receiveCallBack)(shared_from_this(),incomingMessage); 
} 
  • 을 나는이 비슷한 브로커 클래스를했다 ConnectionHandler의 책임 중 하나는 브로커의 콜백 함수를 호출하여 수신 메시지를 Broker으로 전달하는 것입니다. (ConnectionHandler::some_function 참조).

  • 콜백 함수를 호출하는 유일한 방법은 매크로 CALL_MEMBER_FN을 정의하고 위에 보인 것과 같은 개체, 멤버 함수 및 인수를 전달하는 것입니다.
  • 지금까지 너무 좋아 보인다!

    문제

하지만 난 그냥 최근 Broker을 templetized이 점이다. 따라서 브로커 클래스와 콜백 정보를 ConnectionHandler으로 전달할 때 특정 (쓸모없는) 템플릿 인수를 제공해야했습니다. 문제가 보이니? 사실 generalize을 시도하는 동안 BrokerspecializeConnectionHandler입니다. ConnectionHandler는 자체적으로 Broker 템플릿 인수를 가진 다른 비즈니스를 가지고 있지 않습니다.

난 당신이 브로커 템플릿 인수를 포함하지 않고 ConnectionHandler에 함수 포인터를 전달하는 더 나은 제안을 도와 수 있다면 생각, 그것은 :)

내가 믿는 당신에게

답변

2

감사 나의 일 것 두 옵션 :

  1. 는 인터페이스 역할 가상 방지 동작으로 ConnectionHandler 사용되는 핵심 기능을 정의하는 템플릿이 아닌 기본 클래스로부터 파생 Broker 템플릿 ons. 그런 다음 Broker 템플리트가 해당 기능을 대체합니다. ConnectionHandler은 새로운 기본 클래스에 대한 포인터로만 작동합니다 (ConnectionHandler 구현의 템플릿 인수가 더 이상 없음). 단점 : Broker에 대한 호출이 역 참조를 한 단계 더 거쳐야하므로 성능이 느려질 수 있습니다.

  2. Broker과 동일한 매개 변수를 사용하여 ConnectionHandler도 템플릿으로 만듭니다. 단점 : 템플릿 인수의 모든 조합에 대해 ConnectionHandler의 별도 인스턴스가 필요합니다. 당신이 보여준 코드에서, 이것은 문제가되지 않습니다.

    다음은 초기화시에 ConnectionHandler의 템플릿 인수를 도출 할 수있는 방법을 보여주는 간단한 코드 예입니다. 브로커 (모든 유형의)를 인수로 취한 다음 Broker과 일치하는 템플릿 인수를 사용하여 ConnectionHandler을 만드는 기능 템플릿 make_connectionhandler을 구현하면됩니다.

    다음
    /* Using C++11 syntax. */ 
    #include <iostream> 
    
    template <typename T> 
    struct Broker 
    { 
        using type = T; 
    
        void act(type token) const 
        { 
        std::cout << token << std::endl; 
        } 
    }; 
    
    template <typename BrokerType> 
    struct ConnectionHandler 
    { 
    
        ConnectionHandler(const BrokerType &broker) 
        : broker_(broker) 
        { }; 
    
        void handle_request(typename BrokerType::type token) 
        { 
        broker_.act(token); 
        } 
    
    private: 
        const BrokerType &broker_; 
    }; 
    
    
    template <typename BrokerType> 
    ConnectionHandler<BrokerType> make_connectionhandler(const BrokerType &broker) 
    { return { broker }; } 
    

    make_connectionhandler 기능을 사용하는 방법을 나타내는 main 프로그램입니다 : 기능 템플릿 (클래스 템플릿 반대) 그들이 주어진 인수에서 자신의 템플릿 매개 변수를 추론 할 수 있기 때문 작동

    int main() 
    { 
        Broker<int> broker; 
    
        auto handler = make_connectionhandler(broker); 
    
        handler.handle_request(42); 
    
        return 0; 
    } 
    

    위의 C++ 11 구문을 사용했습니다. C++ 03에서는, 당신은 불행하게도 위의 handler의 선언에 템플릿 인수는 여전히 나타납니다 즉, auto을 사용할 수 없습니다 : 불행하게도

    ConnectionHandler<Brokern<int> > handler = make_connectionhandler(broker); 
    

    , 당신은이 문제를 방지 할 수있는 정도가 아니다 완전히 C++ 03.

+0

jogojapan, 의견을 보내 주셔서 감사합니다. options-1 : 아주 좋은 해결책 인 것 같습니다. 나는 그것을 시도하고 다시 당신에게 돌아갈 것입니다. 옵션 -2 : 죽은 몸 위로 :) coz ConnectionHandler가 내 핵심 라이브러리의 일부가 될 것이다. 브로커도 마찬가지입니다! 그래서 사람들이 서브 클래스를 만들고 가상 함수에 대한 정의를 제공 할 수 있도록 일반화하고 있습니다. 브로커 서브 클래스를 만들 때 동시에 templatized ConnectionHandler에 대한 인수 유형을 지정하는 방법이 있다면이 옵션은 내 요구 사항에도 응답 할 것입니다. – rahman

+0

오, 템플릿 인자 만 초기화 시간에 자동으로 추론한다면'ConnectionHandler' 템플릿을 사용하는 것을 허용할까요? 그건 할 수 ... – jogojapan

+0

@rahman C++ 11을 사용할 수 있습니까? – jogojapan

관련 문제