3

I'm working on the implementation of a genetic algorithm that is supposed to work on an abstract genome type.

My setup is something like this:

class AbstractGenome
{
  virtual void init() = 0;
  virtual void mutate() = 0;
  .
  .
  .
};

class GeneticAlgorithm
{
  std::vector<AbstractGenome*> genomes;

  void init(int numGenomes)
  {
    for (int i=0; i < numGenomes; ++i)
    {
      AbstractGenome *genome = new DerivedGenome(); <=This is where my problem is
      genome->init();
      genomes.push_back(genome);
    }
  }

}

where DerivedGenome is to be defined later (at some point) as:

class DerivedGenome: public AbstractGenome
{
  void init() { do stuff; }
  void mutate() {do stuff; }
}

My problem is that the only thing I know about DerivedGenome is that it derives from AbstractGenome - therefore I can't make a general call to the DerivedGenome constructor.

One way I can think of solving this is to derive from GeneticAlgorithm and override the init function for all genome types, but I was wondering if there was a way to solve this in a nicer way, for example via templates?

Thanks a lot in advance.

Tamás Szabó
  • 733
  • 6
  • 9

1 Answers1

5

You could pass the DerivedGenome type into init():

template <typename Derived>
void init(int numGenomes)
{
    for (int i=0; i < numGenomes; ++i)
    {
        AbstractGenome *genome = new Derived();
        genome->init();
        genomes.push_back(genome);
    }
}

Which you can call via:

init<DerivedGenome>(42);

If you want a more explicit compile error in case you try to do init<int>(5), you could change the return-type to require that inheritance:

template <typename Derived>
typename std::enable_if<
    std::is_base_of<AbstractGenome, Derived>::value
>::type init(int numGenomes) { .. }
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    Thanks a lot. This is pretty much what I hoped to have. – Tamás Szabó Apr 17 '15 at 13:18
  • I have tried your suggestion, but I'm not quite sure what to make of this: Undefined symbols for architecture x86_64: "void NSGAII::init(unsigned int)", referenced from: _main in main.o where I have definitely defined my NSGAII::init as per your suggestion – Tamás Szabó Apr 17 '15 at 13:38
  • @TamásSzabó Probably relevent [templates can only be implemented in headers](http://stackoverflow.com/q/495021/2069064) – Barry Apr 17 '15 at 13:44