【问题标题】:C++. How to define template parameter of type T for class A when class T needs a type A template parameter?C++。当类 T 需要 A 类模板参数时,如何为 A 类定义 T 类模板参数?
【发布时间】:2012-12-19 22:28:00
【问题描述】:

Executor 类具有 P 类型的模板,它在构造函数中接受一个 P 对象。 Algo 类有一个模板 E,也有一个 E 类型的静态变量。处理器类有模板 T 和一个 Ts 的集合。

问题我如何定义 Executor< Processor<Algo> >Algo<Executor> ?这可能吗?我看不出有什么办法来定义它,它是一种“无限递归模板参数”

查看代码。

template <class T>
class Processor { 
    map<string,T> ts;
    void Process(string str, int i)
    {
        ts[str].Do(i);
    }
} 

template <class P>
class Executor {
    P &p;
    Executor(P &inp) : p(inp) {}

    void Bar(string str, int i) {
        p.Process(str,i);
    }

    Execute(string str)
    {
    }
} 

template <class E>
class Algo
{
    static E e;

    void Do(int i) {}
    void Foo()
    {
        e.Execute("xxx");
    }
}

main ()
{
    typedef Processor<Algo> PALGO; // invalid
    typedef Executor<PALGO> EPALGO;
    typedef Algo<EPALGO> AEPALGO;

    Executor<PALGO> executor(PALGO());
    AEPALGO::E = executor;
}

编辑 ************ ****************强>

稍微澄清一下。 Executor 是一个提供服务的单例。所有的 Algo 对象都需要 Executor 的服务。 Executor 有时会生成需要发送到特定 Algo 对象的报告。它们通过处理器被发送到正确的算法。

基本问题是需要 Algo 来定义 Executor 并且需要 Executor 来定义 Algo。

【问题讨论】:

  • 在 Algo 类中如何使用 e?为什么是静态的?
  • 编辑代码:添加了 e
  • 好的,但是现在谁调用 Algo:Foo?我的问题是,为什么 E 需要成为 Algo 的一部分?
  • 所有算法对象都使用 E 作为服务。 Algo::Foo 被外部调用。

标签: c++ templates design-patterns template-meta-programming


【解决方案1】:

尝试复制您的代码,但不太确定您要实现的目标。首先,我将其修改为:

   #include <string>   //Added
   #include <map>      //Added
   using namespace std;//Added

   template <class T>
   class Processor {    
      map<string,T> ts;    
      void Process(string str, int i) {        
         ts[str].Do(i);    
      }
   };

   template <class P>
   class Executor {
      Processor<P> &p;    //Was Proc ???
      Executor(P &p) : Processor<P>(p) {}    //Was Proc ???
      void Foo(string str, int i) {
         p.Process(str,i);
      }
      void Execute(string str){}  //Added return type void
   };

   template <class E>
   class Algo {
   public:                 //Added
      static E e;
      void Do(int i) {}
   };

   main () {
      typedef Processor< Algo<int> > PALGO; //Added template argument to Algo
      typedef Executor<PALGO> EPALGO;
      typedef Algo<EPALGO> AEPALGO;

      Executor<PALGO> executor(PALGO());
      AEPALGO::e = executor;
   }

在 Executor 定义中将 Proc 修改为处理器 - (什么是 Proc?)并在 typedef Processor> PALGO 中为其提供模板参数; 然后 AEPAGO::E --> 那是一个模板参数,而不是类 Algo 成员 - 所以 AEPAGO::e。 现在您将收到一个更易于管理的错误。它需要一个复制构造函数来转换类型。

【讨论】:

  • Algo 失败了。 Algo 需要 Executor 的静态变量。它需要是 Algo.... >>> 它是一个无限循环。
【解决方案2】:

您可以使用继承。

class X : public Executor<Processor<Algo<X>>> {};

否则,这是不可能的。

【讨论】:

  • 我刚试过这个,它编译到目前为止。但似乎,我无法定义一个有效的构造函数。你会怎么做?
  • 我知道了:X(Processor&lt;Algo&lt;X&gt; &gt; &amp;p) : Executor&lt;Processor&lt;Algo&lt;X&gt; &gt; &gt;(p) {}
【解决方案3】:

AFAICS,你不能用 same Executor 类型做到这一点。否则你将不得不定义

Executor<Processor<Algo<Executor<Processor<Algo<...> > > > > >

如果你用其他类型定义它,它可能会起作用,前提是在技术上有意义

class X {
...
};

Executor<Processor<Algo<Executor<Processor<Algo<X> > > > > >

typedef

class X {...};
typedef Processor<Algo<X> > PALGO;
typedef Executor<PALGO> EPALGO;
typedef Algo<EPALGO> AEPALGO;

Executor<PALGO> executor(PALGO());

【讨论】:

    【解决方案4】:

    由于 Executor 是一个单例,您可以将它的定义移出 Algo,既可以在它自己的单例类中,也可以在 Executor 中。然后制作所有需要了解的关于Executor模板成员函数的Algo函数。

    template <class P>
    class Executor {
    
        static Executor e;
    
        P &p;
        Executor(P &p) : Proc(p) {}
    
        void Bar(string str, int i) {
            p.Process(str,i);
        }
    
        Execute(string str)
        {
        }
    
        public:
        static Executor& getE(){ return e;}
    } 
    
    class Algo
    {
    
        void Do(int i) {}
        template <class E>
        void Foo()
        {
            E::getE().Execute("xxx");
        }
    }
    

    【讨论】:

    • 我如何从 Do() 调用 Foo()? Foo>() ?那么这不是通用的,我可以在 Algo 内部声明static Executor&lt;Processor&lt;Algo&gt;&gt; e;
    • 所有需要 Executor 的算法成员函数都必须是模板函数。不那么漂亮,但它应该可以工作。
    【解决方案5】:

    解决了!见 cmets。 //****

    #include <string>
    #include <map>
    #include <iostream>
    using namespace std;
    
    template <class T>
    class Processor {
    public:
        map<string,T*> ts;
        void Process(string str, int i)
        {
            ts[str]->Do(i);
        }
    };
    
    template <class P>
    class Executor  {
    public:
        P &p;
        Executor(P &inp) : p(inp) {}
    
        void Bar(string str, int i) {
            p.Process(str,i);
        }
    
        void Execute(string str)
        {
            cout << " Executor::Execute " << str << endl;
        }
    };
    
    template <template <class> class E> //**********
    class Algo
    {
        string str;
    public:
        Algo(const string &s) : str(s) {}
    
        static E<Processor<Algo>> *e; //**********
    
        void Do(int i) { cout << str << "::Do(" << i <<")"<< endl; }
    
        void Foo()
        {
            e->Execute(str);
        }
    };
    
    template <template <class> class E>
    E< Processor<Algo<E> > >* Algo<E>::e;  //**********
    
    int main(int argc, char **argv)
    {
        typedef Algo<Executor> EALGO;
        typedef Processor<EALGO> PALGO;
        typedef Executor<PALGO> EPALGO;
    
        PALGO p;
        EPALGO executor(p);
    
        EALGO::e = &executor; //**********
    
        EALGO ealgo1("algo1"), ealgo2("algo2");
    
        p.ts["algo1"] = &ealgo1;
        p.ts["algo2"] = &ealgo2;
        ealgo1.Foo();
        ealgo2.Foo();
        executor.Bar("algo1",1111);
        executor.Bar("algo2",2222);
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多