fork(1) download
  1. // Remove "x" to invoke feature.
  2. #define xTEST_BAD_ASSIGN
  3.  
  4. #if defined( CPP11 )
  5. # define OVERRIDE override
  6. # define NOEXCEPT noexcept
  7. #else
  8. # define OVERRIDE
  9. # define NOEXCEPT throw()
  10. #endif
  11.  
  12. //---------------------------------------------------------------------------
  13. #include <algorithm> // std::swap
  14. #include <iostream> // std::wcout, std::endl
  15. #include <string> // std::string
  16. #include <utility> // std::forward
  17. using namespace std;
  18.  
  19. #if defined( CPP11 )
  20. template< class Base >
  21. class Assignable_ final
  22. : public Base
  23. {
  24. public:
  25. using Base::Base;
  26. using Base::operator=;
  27. };
  28. #else
  29. template< class Base >
  30. class Assignable_;
  31.  
  32. class IsFinalAssignable
  33. {
  34. template< class > friend class Assignable_;
  35. private:
  36. IsFinalAssignable() {}
  37. };
  38.  
  39. template< class Base >
  40. class Assignable_
  41. : private virtual IsFinalAssignable
  42. , public Base
  43. {
  44. public:
  45. Assignable_(): Base() {}
  46.  
  47. template< class Arg1 >
  48. Assignable_( Arg1 const& a1 )
  49. : Base( a1 )
  50. {}
  51.  
  52. template< class Arg1, class Arg2 >
  53. Assignable_( Arg1 const& a1, Arg2 const& a2 )
  54. : Base( a1, a2 )
  55. {}
  56.  
  57. using Base::operator=;
  58. };
  59. #endif
  60.  
  61. class Person
  62. {
  63. private:
  64. string name_;
  65.  
  66. protected:
  67. void swapWith( Person& other ) NOEXCEPT
  68. {
  69. swap( name_, other.name_ );
  70. }
  71.  
  72. void operator=( Person other ) { swapWith( other ); }
  73.  
  74. public:
  75. typedef Assignable_<Person> Assignable;
  76.  
  77. string name() const { return name_; }
  78.  
  79. Person( string const& name )
  80. : name_( name )
  81. {}
  82. };
  83.  
  84. class Student
  85. : public Person
  86. {
  87. private:
  88. int studentId_;
  89.  
  90. protected:
  91. void swapWith( Student& other ) NOEXCEPT
  92. {
  93. Person::swapWith( other );
  94. swap( studentId_, other.studentId_ );
  95. }
  96.  
  97. void operator=( Student other ) { swapWith( other ); }
  98.  
  99. public:
  100. typedef Assignable_<Student> Assignable;
  101.  
  102. int studentId() const { return studentId_; }
  103.  
  104. Student( string const& name, int const studentId )
  105. : Person( name ), studentId_( studentId )
  106. {}
  107. };
  108.  
  109. #ifdef TEST_EXTENSION
  110. class Extension
  111. : public Person::Assignable
  112. {
  113. public:
  114. Extension(): Person::Assignable( "Somebody" ) {}
  115. };
  116. #endif
  117.  
  118. wostream& operator<<( wostream& stream, string const& s )
  119. {
  120. return (stream << s.c_str());
  121. }
  122.  
  123. int main()
  124. {
  125. Person::Assignable a( "Hillary Clinton" );
  126. Student::Assignable b1( "John Smith", 12345 );
  127. Student b2( "Mary Jones", 88888 );
  128. Person& bAsPerson = b1; // OK.
  129.  
  130. wcout
  131. << "Name: " << b1.name()
  132. << ". Student id: " << b1.studentId() << "."
  133. << endl;
  134.  
  135. #ifdef TEST_BAD_ASSIGN
  136. bAsPerson = a; // Does not compile. :-)
  137. #else
  138. b1 = b2; // Good/allowed assignment.
  139. #endif
  140.  
  141. wcout
  142. << "Name: " << b1.name()
  143. << ". Student id: " << b1.studentId() << "."
  144. << endl;
  145. }
  146.  
Success #stdin #stdout 0.01s 2876KB
stdin
Standard input is empty
stdout
Name: John Smith. Student id: 12345.
Name: Mary Jones. Student id: 88888.