如何将指针传递给模板类的成员函数?

时间:2013-07-12 05:51:56

标签: c++ templates boost function-pointers

我刚刚面临一个有趣的挑战,让我们一起解决它:

我有一个与此类似的经纪人课程:

//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并传递对象,成员函数和参数,就像你在上面看到的那样。
  • 到目前为止似乎很好!

BUT

问题在于,我只是最近已经逐神化 Broker。因此,在将Broker类和回调信息传递给ConnectionHandler时,我被迫提供特定的(和无用的)模板参数。你看到了问题吗?事实上,在尝试generalize Broker时,我不得不specialize ConnectionHandler! ConnectionHandler本身没有与Broker模板参数的其他业务。

我想如果你可以帮助我更好地建议将函数指针传递给ConnectionHandler而不涉及Broker模板参数,那么它将成为我的一天:)

谢谢

1 个答案:

答案 0 :(得分:2)

我相信这两个选项是:

  1. 从充当接口的非模板基类派生Broker模板,并将ConnectionHandler使用的核心函数定义为虚函数。然后Broker模板将覆盖这些函数。 ConnectionHandler仅适用于指向新基类的指针(ConnectionHandler实现中不再有模板参数)。缺点:可能性能较慢,因为对Broker的调用必须通过一个额外的解除引用级别。

  2. ConnectionHandler设为模板,使用与Broker相同的参数。缺点:对于模板参数的每个组合,您将需要一个单独的ConnectionHandler实例。从你展示的代码来看,这不会是一个问题。

    这是一个简短的代码示例,显示了如何在初始化时派生ConnectionHandler的模板参数。它是通过实现一个函数模板make_connectionhandler完成的,它将一个代理(任何类型)作为参数,然后使用与ConnectionHandler匹配的模板参数创建Broker。这是有效的,因为函数模板(与类模板相对)可以从给出的参数中推断出它们的模板参数:

    /* 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中完全避免这种情况。