0

Is it possible to create a Factory that generates all derived classes (and class names) at runtime, based on all the classes that are specified in a particular file?

For example, given a specific file where users are constantly adding derived classes:

class Laptop: public Computer {
  public:
     virtual void Run(){mHibernating = false;}
     virtual void Stop(){mHibernating = true;}
 private:
     bool mHibernating; // Whether or not the machine is hibernating
 };

class Desktop: public Computer {
 public:
     virtual void Run(){mOn = true;}
     virtual void Stop(){mOn = false;}
 private:
     bool mOn; // Whether or not the machine has been turned on
 };

// ....[more classes derived from Computer]...

Can a Factory generate a list of possible classes to map to, based on their name?

 class ComputerFactory {
 public:
     static Computer *NewComputer(const std::string &description)
     {
         if(description == "Laptop")
             return new Laptop;
         } else if (description == "Desktop") {
             return new Desktop;
         } else if  // ...[more comparisons based on the classes defined at runtime]...
         } else return NULL;
     }
 };
sgarza62
  • 5,998
  • 8
  • 49
  • 69
  • 2
    This isn't possible without some additional information in the source file. The usual way to do this is to have a macro `REGISTER_TYPE` that makes the relevant information available in some way, and then to `REGISTER_TYPE(Laptop)`, `REGISTER_TYPE(Computer)` etc. – Mankarse May 13 '14 at 09:01
  • 1
    Why can't the same users who keep adding classes to the file, also maintain said map? – StoryTeller - Unslander Monica May 13 '14 at 09:01
  • @sgarza62 short answer is No. What you could to is to write an external tools that looks inside the files and identifies the classes it has. That tool can generate the factory for you. – Raxvan May 13 '14 at 09:01
  • @StoryTeller I agree; you're correct. I'm working on an HTTP server, and we've been asked to use a config file, where users associate URIs (as regexs) to derived HttpRequestHandler classes. So a particular handler would be called, based on the URI requested. – sgarza62 May 13 '14 at 18:50

1 Answers1

1

You can write a parser and have the class process the input file, but I doubt that's what you want.

You can also use the crtp pattern to your advantage:

template<class T>
struct Base
{
   Base()
   { 
      reg;
   }
   virtual std::string name() = 0;
   static bool reg;
   static bool init() 
   { 
      T t; 
      Factory::registerClass(t.name());
      return true;
   }
};

template<class T>
bool Base<T>::reg = Base<T>::init();

source

You'd then derive classes as

struct Derived1 : Base<Derived1> 
{
 ...
}

This would automatically register your class with Factory given its name (you have to implement name in non-abstract classes because it's pure).

Additionally, you can pass a callback to registerClass that knows how to create your derived class.

Community
  • 1
  • 1
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625