递归c ++模板问题

时间:2010-10-25 18:17:09

标签: c++ templates

假设我有一个模板类,它从源代码获取消息,为它们做一些聪明的事情,然后将它们发送到接收器:

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;
}
};

3 个答案:

答案 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需要在其处理程序上进行参数化。如果SourceHandler确实需要以您描述的方式紧密耦合,那么模板似乎不会超出接口定义。在我看来,你可以拥有一个封装Source的非模板Handler<Source, Sink>类。

答案 2 :(得分:1)

看起来HandlerSource一无所知。如何简单的线性依赖:

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