fork download
  1. #include <iostream>
  2. #include <memory>
  3.  
  4. class Container {
  5.  
  6. struct Var;
  7. typedef std::ostream Out;
  8. typedef std::shared_ptr<Var> VarPtr;
  9. std::shared_ptr<VarPtr> varptr_;
  10.  
  11. struct BadType {};
  12.  
  13. struct Var {
  14. virtual ~Var () = default;
  15. virtual Out & print (Out &os) { return os << "(BadType)"; }
  16. virtual void set (int) { throw BadType(); }
  17. virtual void set (const std::string &) { throw BadType(); }
  18. };
  19.  
  20. struct VarInteger : Var {
  21. int data;
  22. VarInteger (int v) : data(v) {}
  23. Out & print (Out &os) { return os << data; }
  24. void set (int v) throw() { data = v; }
  25. };
  26.  
  27. struct VarString : Var {
  28. std::string data;
  29. VarString (const std::string &v) : data(v) {}
  30. Out & print (Out &os) { return os << data; }
  31. void set (const std::string &v) throw() { data = v; }
  32. };
  33.  
  34. static VarPtr make_var () { return std::make_shared<Var>(); }
  35. static VarPtr make_var (int v) { return std::make_shared<VarInteger>(v); }
  36. static VarPtr make_var (const std::string &v) {
  37. return std::make_shared<VarString>(v);
  38. }
  39.  
  40. VarPtr & var () { return *varptr_; }
  41. const VarPtr & var () const { return *varptr_; }
  42.  
  43. public:
  44.  
  45. Container () : varptr_(std::make_shared<VarPtr>(make_var())) {}
  46. Container (int v) : varptr_(std::make_shared<VarPtr>(make_var(v))) {}
  47. Container (const std::string &v)
  48. : varptr_(std::make_shared<VarPtr>(make_var(v))) {}
  49.  
  50. void set (int v) {
  51. try { var()->set(v); }
  52. catch (BadType) { var() = make_var(v); }
  53. }
  54.  
  55. void set (const std::string &v) {
  56. try { var()->set(v); }
  57. catch (BadType) { var() = make_var(v); }
  58. }
  59.  
  60. void createLink (const Container &val) { varptr_ = val.varptr_; }
  61.  
  62. friend Out & operator << (Out &os, const Container &val) {
  63. return val.var()->print(os);
  64. }
  65. };
  66.  
  67. int main () {
  68. Container cont1("some value");
  69. Container cont2;
  70. cont2.createLink(cont1);
  71. std::cout << cont1 << '\n';
  72. cont2.set(20);
  73. std::cout << cont1 << '\n';
  74. }
Success #stdin #stdout 0s 3236KB
stdin
Standard input is empty
stdout
some value
20