假设我有一个模板类,它从源代码获取消息,为它们做一些聪明的事情,然后将它们发送到接收器:
template <typename Source, typename Sink>
class MsgHandler
{
MsgHandler(Source* pSource)
: m_pSource(pSource)
{
m_pSource->setHandler(this);
}
};
//Now the definition of the Source:
template <typename Handler>
class Source
{
void setHandler(Handler* pHandler)
{
m_pHandler = pHandler;
}
};
一切都很好,但现在我不能制作来源或处理程序。例如:
MsgHandler<FileSource<MsgHandler<FileSource.... recursing parameters...
FileSource<MsgHandler<FileSource<MsgHandler.... same problem when trying to build a source
有没有办法解决这个问题而不使用Handler的虚拟基类?
虚拟基类解决方案:
class MyHandler
{
virtual ~MyHandler() {};
virtual void handleSomething() = 0;
};
template <typename Source, typename Sink>
class MsgHandler : public MyHandler
{
MsgHandler(Source* pSource)
: m_pSource(pSource)
{
m_pSource->setHandler(this);
}
void handleSomething() {}
};
class Source
{
void setHandler(MyHandler* pHandler)
{
m_pHandler = pHandler;
}
};
答案 0 :(得分:2)
您可以使用模板化参数作为处理程序的source参数:
class MySink;
template <template<typename Handler> class Source, typename Sink>
class MsgHandler
{
Source<MsgHandler>* m_pSource;
MsgHandler(Source<MsgHandler>* pSource)
: m_pSource(pSource)
{
m_pSource->setHandler(this);
}
};
//Now the definition of the Source:
template <typename Handler>
class Source
{
void setHandler(Handler* pHandler)
{
m_pHandler = pHandler;
}
};
//Now you can define variables like this
MsgHandler<Source, MySink> myHandler;
当然,要求MsgHandler的Source参数是一个只有一个参数(处理程序)的模板,但是如果你能接受这个约束,这将解决你的定义问题(否则你可能(或者可能不依赖于什么)确切地说你会尝试)能够使用一些额外的模板foo来规避这个限制(创建另一个模板,它将处理程序作为参数并且具有相应SourcesType的typedef)。
在这种情况下,向MsgHandler添加typedef Source<MsgHandler> SourceType
以使调用者可以看到Source-Instantiation(而不是要求程序员猜测MsgHandler将实例化Source。)可能也是一个好主意。
答案 1 :(得分:1)
我不明白为什么你的Source
需要在其处理程序上进行参数化。如果Source
和Handler
确实需要以您描述的方式紧密耦合,那么模板似乎不会超出接口定义。在我看来,你可以拥有一个封装Source
的非模板Handler<Source, Sink>
类。
答案 2 :(得分:1)
看起来Handler
对Source
一无所知。如何简单的线性依赖:
template <typename Sink>
class Handler {
private:
Sink* sink; // get this pointer in the constructor?
public:
void handle( const Msg& m ) {
// processing
sink->accept( m );
}
};
template <typename Handler>
class Source {
private:
Handler* handler;
public:
void genMessage() {
Msg m;
// get message off the wire?
handler->handle( m );
}
};
也可以扭曲为“处理”和“沉没”为policies。