2013-07-12 152 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並傳遞對象,成員函數和參數(如上面所見)。
  • 迄今爲止似乎很好!

的問題是,我只是最近templetizedBroker。因此,當我將Broker類和回調信息傳遞給ConnectionHandler時,我不得不提供特定的(和無用的)模板參數。你看到問題了嗎?其實一邊試圖generalizeBroker,我不得不specializeConnectionHandler!通過它自己的ConnectionHandler,Broker模板參數沒有其他業務。

我想如果你能幫助我更好的建議傳遞函數指針ConnectionHandler而不涉及經紀模板參數,它會讓我的一天:)

謝謝

回答

2

我相信兩個選項是:

  1. 從充當一個接口,定義了用於通過ConnectionHandler作爲虛擬functi核心功能的非模板基類派生的Broker模板附件。然後Broker模板將覆蓋這些功能。 ConnectionHandler只能用於指向新基類的指針(在ConnectionHandler實現中不再有模板參數)。缺點:可能性能較差,因爲進入Broker的呼叫將不得不經過一個額外的解引用級別。

  2. 使ConnectionHandler成爲模板,並採用與Broker相同的參數。缺點:對於模板參數的每個組合,您將需要一個單獨的ConnectionHandler實例。從你展示的代碼來看,這不會是一個問題,但。

    下面是一個簡短的代碼示例,顯示瞭如何在初始化時導出ConnectionHandler的模板參數。這是通過實現功能模板make_connectionhandler完成的,該功能模板以一個代理(任何類型)作爲參數,然後使用與Broker匹配的模板參數創建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 }; } 
    

    這裏是一個main程序,顯示make_connectionhandler功能如何使用:

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

    我已經使用了上面的C++ 11語法。在C++ 03,你不能使用auto,不幸意味着,在上述handler聲明,模板參數仍然會出現:

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

    不幸的是,沒有太多可以做,以避免這種完全在C++ 03中。

+0

jogojapan,謝謝你的建議。選項-1:似乎是一個非常好的解決方案。我會嘗試一下並回復你。選項-2:在我的屍體:)因爲ConnectionHandler將成爲我的核心庫的一部分。經紀人也是如此!這就是爲什麼我將它推廣以便人們可以創建子類併爲其虛擬功能提供定義。如果在創建Broker子類的同時有一種方法可以爲模板化的ConnectionHandler自動指定參數類型,那麼這個選項也會回答我的需求。 – rahman

+0

哦,所以你會接受使'ConnectionHandler'成爲一個模板,如果只有模板參數會在初始化時自動推斷出來?這可以做... – jogojapan

+0

@rahman你可以使用C++ 11嗎? – jogojapan

相關問題