fork download
  1. #include <iostream>
  2. #include <functional>
  3. #include <memory>
  4. #include <unordered_map>
  5.  
  6. template <typename BASE>
  7. struct
  8. Factory {
  9. private: using
  10. TCloneFn = std::function<std::shared_ptr<BASE>(BASE const * const)>;
  11.  
  12. private:
  13. static std::unordered_map<BASE const*,TCloneFn> cloneFnMap;
  14.  
  15. public: template <typename DERIVED_TYPE, typename...TS>
  16. static std::shared_ptr<BASE>
  17. create(TS...args) {
  18. BASE* obj = new DERIVED_TYPE(args...);
  19. const std::shared_ptr<BASE> pNewObj =
  20. std::shared_ptr<BASE>(
  21. obj,
  22. [&](BASE* p){
  23. cloneFnMap.erase(p);
  24. delete p;
  25. }
  26. );
  27.  
  28. cloneFnMap[obj] = [&](BASE const * const orig){
  29. std::shared_ptr<BASE> pClone = create<DERIVED_TYPE>(std::ref(static_cast<DERIVED_TYPE const &>(*orig)));
  30. return pClone;
  31. };
  32. return pNewObj;
  33. }
  34.  
  35. public: static std::shared_ptr<BASE>
  36. clone(std::shared_ptr<BASE const> original) {
  37. return cloneFnMap[original.get()](original.get());
  38. }
  39. };
  40.  
  41. template <typename BASE> std::unordered_map<BASE const*,typename Factory<BASE>::TCloneFn> Factory<BASE>::cloneFnMap;
  42.  
  43. class Base {
  44. public: virtual ~Base() throw() {}
  45. public: virtual void whoAmI() const {
  46. std::cout << "I am Base instance " << this << "\n";
  47. }
  48. };
  49.  
  50.  
  51. class Derived : public Base {
  52. std::string name;
  53. public: Derived(std::string name) : name(name) {}
  54. public: Derived(const Derived&other) : name("copy of "+other.name) {
  55. }
  56. private: virtual void whoAmI() const {
  57. std::cout << "I am Derived instance " << this << " " << name << "\n";
  58. }
  59. };
  60.  
  61. int main() {
  62. std::shared_ptr<Base> a = Factory<Base>::create<Derived>("Original");
  63. a->whoAmI();
  64. std::shared_ptr<Base> copy_of_a = Factory<Base>::clone(a);
  65. copy_of_a->whoAmI();
  66. std::shared_ptr<Base> copy_of_a_copy = Factory<Base>::clone(copy_of_a);
  67. copy_of_a_copy->whoAmI();
  68. return 0;
  69. }
  70.  
  71.  
  72.  
  73.  
Success #stdin #stdout 0s 3280KB
stdin
Standard input is empty
stdout
I am Derived instance 0x94dd058 Original
I am Derived instance 0x94dd0b0 copy of Original
I am Derived instance 0x94dd130 copy of copy of Original