I have the following classes:
class A {
public:
  virtual std::string Serialize();
  virtual void Deserialize(std::string);
  template <typename T>
  T* Clone()
  {
    std::string s = Serialize();
    T* t = new T();
    t->Deserialize(s);
    return t;
  }
};
class B : public A {
public:
  std::string Serialize() { ... }
  void Deserialize(std::string) { ... }
};
Now, if I want to clone B, I do the following:
B b1;
B* b2 = b1.Clone<B>();
Is there any way to remove the template type without re-implementing Clone in each and every derived classes?
I want something like this:
B b1;
B* b2 = b1.Clone();
                The way to do this is with CRTP:
class A {
public:
    virtual std::string Serialize();
    virtual void Deserialize(std::string);
    virtual A* Clone() = 0;  
};
template <class T>
class HelperA : public A {
    T* Clone() override
        {
            std::string s = Serialize();
            T* t = new T();
            t->Deserialize(s);
            return t;
        }
};
class B : public HelperA<B> {
public:
    std::string Serialize() { ... }
    void Deserialize(std::string) { ... }
};
These 3 level hierarchies are quite common. Basically, the top class is pure interface, as before (note: you should = 0 the other functions too). The middle class uses the CRTP pattern: it is templated on the derived typed. the idea is that by having static access to the derived type, it can automatically implement things like Clone. Then the derived type implements any implementation that cannot be done generically.
Notice that the derived-most type inherits from the CRTP class templated on itself. That's where the name comes from (Curiously Recurring Template Pattern). Of course, since inheritance is transitive B also inherits from A still, as originally, enabling the same sort of things.
Here is a full working example that you can execute: http://coliru.stacked-crooked.com/a/8f2b201a06b5abcc. I kept the code in the answer as similar to the question as possible, but in the coliru example there are a few small but important differences:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With