C++. How to define template parameter of type T fo

2019-05-31 22:14发布

Executor class has template of type P and it takes a P object in constructor. Algo class has a template E and also has a static variable of type E. Processor class has template T and a collection of Ts.

Question how can I define Executor< Processor<Algo> > and Algo<Executor> ? Is this possible? I see no way to defining this, its kind of an "infinite recursive template argument"

See code.

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

EDIT ****************************

A little clarification. Executor is a singleton that provides a service. All Algo objects need the services of Executor. Executor will sometimes generate reports that need to be sent to a specific Algo object. They get sent to the correct Algo through Processor.

Basic issue is that Algo is needed to define Executor and Executor is needed to define Algo.

5条回答
乱世女痞
2楼-- · 2019-05-31 22:30

AFAICS, you cannot do that with the same Executor type. Otherwise you would have to define

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

It might work, if you define it with some other type, provided that makes any sense technically

class X {
...
};

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

or with typedef

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

Executor<PALGO> executor(PALGO());
查看更多
地球回转人心会变
3楼-- · 2019-05-31 22:33

You can use inheritance.

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

Else, this is not possible.

查看更多
Emotional °昔
4楼-- · 2019-05-31 22:42

Since Executor is a singleton, you can move its definition out of Algo either in it's own singleton class or in Executor. Then make all the Algo function that need to know about Executor template member functions.

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");
    }
}
查看更多
Emotional °昔
5楼-- · 2019-05-31 22:50

Solved! see comments. //****

#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);

}
查看更多
We Are One
6楼-- · 2019-05-31 22:53

Tried reproducing your code, not quite sure what you are trying to achieve. For starters, this is what I modified it to:

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

Modified Proc to Processor in Executor definition - (what is Proc?) and gave it template argument, in the typedef Processor> PALGO; Then AEPAGO::E --> thats a template param, not class Algo member - so AEPAGO::e. Now you will get an error that can be more manageable. It needs a copy constructor to convert types.

查看更多
登录 后发表回答