我刚刚面临一个有趣的挑战,让我们一起解决它:
我有一个与此类似的经纪人课程:
//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模板参数,那么它将成为我的一天:)
谢谢
答案 0 :(得分:2)
我相信这两个选项是:
从充当接口的非模板基类派生Broker
模板,并将ConnectionHandler
使用的核心函数定义为虚函数。然后Broker
模板将覆盖这些函数。 ConnectionHandler
仅适用于指向新基类的指针(ConnectionHandler
实现中不再有模板参数)。缺点:可能性能较慢,因为对Broker
的调用必须通过一个额外的解除引用级别。
将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中完全避免这种情况。