代码之家  ›  专栏  ›  技术社区  ›  anio

递归C++模板问题

  •  1
  • anio  · 技术社区  · 14 年前

    假设我有一个模板类,它从源代码中获取MSG,对它们做一些聪明的事情,然后将它们发送到水槽:

    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
    

    有没有一种方法可以解决这个问题而不使用处理程序的虚拟基类?

    虚拟基类解决方案:

    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 回复  |  直到 14 年前
        1
  •  2
  •   Grizzly    14 年前

    您可以将模板化参数用于处理程序的源参数:

    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的源参数是一个只有一个参数的模板(处理程序),但是如果您能够接受这个约束,这将解决您的定义问题(否则,您可能(或者可能不取决于您将要尝试的具体内容)能够使用一些额外的模板foo来规避这个限制。打开(创建另一个模板,该模板将处理程序作为参数,并为相应的sourceStype创建typedef)。

    在这种情况下,添加 typedef Source<MsgHandler> SourceType 使调用方可以看到源实例化(而不是要求程序员猜测msghandler将实例化源)。

        2
  •  1
  •   Steve Townsend    14 年前

    我不明白为什么你 Source 需要在其处理程序上参数化。如果 来源 Handler 确实需要以您描述的方式紧密耦合,这似乎不像模板为您购买的界面定义以外的很多东西。在我看来,你可以有一个非模板 来源 封装的类 Handler<Source, Sink> .

        3
  •  1
  •   Nikolai Fetissov    14 年前

    看起来像 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 .