fork download
  1. // Remove "x" to invoke feature.
  2. #define xTEST_ABSTRACT_CLONE
  3.  
  4. #if defined( CPP11 )
  5. # define OVERRIDE override
  6. # define IS_DELETED = delete
  7. # include <memory>
  8. template< class Type >
  9. struct Ownership { using Ptr = std::unique_ptr<Type>; };
  10. #else
  11. # define OVERRIDE
  12. # define IS_DELETED
  13. # include <memory> // Note: std::auto_ptr is deprecated.
  14. template< class Type >
  15. struct Ownership { typedef std::auto_ptr<Type> Ptr; };
  16. #endif
  17.  
  18. //---------------------------------------------------------------------------
  19. #include <assert.h> // assert
  20. #include <iostream> // std::wcout, std::wcerr, std::endl
  21. #include <memory> // std::unique_ptr
  22. #include <string> // std::string
  23. #include <typeinfo> // std::typeinfo, i.e. typeid usage.
  24. using namespace std;
  25.  
  26. class Cloneable
  27. {
  28. private:
  29. virtual Cloneable* virtualClone() const = 0;
  30. protected:
  31. virtual ~Cloneable() {}
  32. };
  33.  
  34. template< class DerivedClass, class BaseClass >
  35. class WithCloningOf_
  36. : public BaseClass
  37. {
  38. private:
  39. WithCloningOf_& operator=( WithCloningOf_ const& ) IS_DELETED;
  40.  
  41. virtual WithCloningOf_* virtualClone() const
  42. {
  43. assert( typeid( *this ) == typeid( DerivedClass ) );
  44. return new DerivedClass( *static_cast<DerivedClass const*>( this ) );
  45. }
  46.  
  47. DerivedClass* derivedClassClone() const
  48. {
  49. return static_cast<DerivedClass*>( virtualClone() );
  50. }
  51.  
  52. public:
  53. typename Ownership<DerivedClass>::Ptr clone() const
  54. {
  55. return typename Ownership<DerivedClass>::Ptr( derivedClassClone() );
  56. }
  57.  
  58. WithCloningOf_(): BaseClass() {}
  59.  
  60. template< class Arg1 >
  61. WithCloningOf_( Arg1 const& a1 )
  62. : BaseClass( a1 )
  63. {}
  64.  
  65. template< class Arg1, class Arg2 >
  66. WithCloningOf_( Arg1 const& a1, Arg2 const& a2 )
  67. : BaseClass( a1, a2 )
  68. {}
  69. };
  70.  
  71. class Person
  72. : public WithCloningOf_<Person, Cloneable>
  73. {
  74. typedef WithCloningOf_<Person, Cloneable> Base;
  75. private:
  76. string name_;
  77.  
  78. Person& operator=( Person const& ) IS_DELETED;
  79.  
  80. public:
  81. string name() const { return name_; }
  82.  
  83. Person( string const& name )
  84. : name_( name )
  85. {}
  86. };
  87.  
  88. class Student
  89. : public WithCloningOf_<Student, Person>
  90. {
  91. typedef WithCloningOf_<Student, Person> Base;
  92. private:
  93. int studentId_;
  94.  
  95. Student& operator=( Student const& ) IS_DELETED;
  96.  
  97. public:
  98. int studentId() const { return studentId_; }
  99.  
  100. Student( string const& name, int const studentId )
  101. : Base( name ), studentId_( studentId )
  102. {}
  103. };
  104.  
  105. wostream& operator<<( wostream& stream, string const& s )
  106. {
  107. return (stream << s.c_str());
  108. }
  109.  
  110. int main()
  111. {
  112. Person a( "Hillary Clinton" );
  113. Student b1( "John Smith", 12345 );
  114. Student b2( "Mary Jones", 88888 );
  115. Person& bAsPerson = b1; // OK.
  116. Ownership<Person>::Ptr pClone;
  117.  
  118. wcout
  119. << "Name: " << b1.name()
  120. << ". Student id: " << b1.studentId() << "."
  121. << endl;
  122.  
  123. #ifdef TEST_ABSTRACT_CLONE
  124. pClone = bAsPerson.clone(); // OK, clones John Smith the Student.
  125. #else
  126. pClone = b2.clone(); // More obviously (?) OK, clones Mary.
  127. #endif
  128. Student& studentRef = dynamic_cast<Student&>( *pClone );
  129.  
  130. wcout
  131. << "Name: " << studentRef.name()
  132. << ". Student id: " << studentRef.studentId() << "."
  133. << endl;
  134. }
  135.  
Success #stdin #stdout 0.01s 2876KB
stdin
Standard input is empty
stdout
Name: John Smith. Student id: 12345.
Name: Mary Jones. Student id: 88888.