fork download
  1. #include <algorithm>
  2. #include <iostream>
  3.  
  4. template<class T>
  5. struct default_delete {
  6. void operator()(T* ptr) const {delete ptr;}
  7. };
  8. template<class T>
  9. struct array_delete {
  10. void operator()(T* ptr) const {delete [] ptr;}
  11. };
  12.  
  13. template<class T, class D>
  14. class unique_ptr;
  15. template<class T, class D=default_delete<T> >
  16. class move_unique_ptr {
  17. //template<class U>
  18. //friend move_unique_ptr<T, default_delete<T> > make_unique(const U& vs);
  19. //friend move_unique_ptr<T, default_delete<T> > make_unique();
  20. //friend move_unique_ptr<T, D> move(unique_ptr<T, D>& rhs);
  21. friend class unique_ptr<T, D>;
  22. typedef T* pointer;
  23.  
  24. D mutable dtor;
  25. pointer mutable ptr;
  26.  
  27. move_unique_ptr& operator=(const move_unique_ptr& rhs);
  28. public:
  29. move_unique_ptr(T* rhs, D del) : dtor(del), ptr(rhs) {}
  30. move_unique_ptr(const move_unique_ptr& rhs)
  31. :dtor(rhs.dtor), ptr(rhs.ptr)
  32. { rhs.ptr = NULL; }
  33. ~move_unique_ptr() {dtor(ptr); ptr=NULL;}
  34. };
  35.  
  36. template<class T, class D=default_delete<T> >
  37. class unique_ptr : private D {
  38. public:
  39. unique_ptr() : D(), ptr(NULL) {}
  40. unique_ptr(const move_unique_ptr<T, D>& rhs)
  41. : D(rhs.dtor), ptr(rhs.ptr)
  42. {rhs.ptr = NULL;}
  43. ~unique_ptr() {D::operator()(ptr);}
  44. unique_ptr& operator=(move_unique_ptr<T, D>& rhs) {
  45. unique_ptr t(rhs);
  46. swap(t);
  47. return *this;
  48. }
  49. void reset(T* ptr_=NULL) {
  50. D::operator()(ptr);
  51. ptr = ptr_;
  52. };
  53. T* get() const {return ptr;}
  54. T* operator->() const {return ptr;}
  55. T& operator*() const {return *ptr;}
  56. D& get_deleter() {return *this;}
  57. const D& get_deleter() const {return *this;}
  58. operator void*() const {return ptr;}
  59. T* release() {T* t = ptr; ptr = NULL; return t;} //you should almost never use this
  60. void swap(unique_ptr& rhs) {
  61. using std::swap;
  62. swap(ptr, rhs.ptr);
  63. swap(static_cast<D&>(*this), static_cast<D&>(*this));
  64. }
  65. void swap(move_unique_ptr<T, D>& rhs) {
  66. swap(ptr, rhs.ptr);
  67. swap(static_cast<D&>(*this), rhs.dtor);
  68. }
  69. private:
  70. T* ptr;
  71. unique_ptr(unique_ptr& rhs); //no impl
  72. unique_ptr& operator=(unique_ptr& rhs); //no impl
  73. };
  74. template<class T, class D>
  75. void swap(unique_ptr<T, D>& lhs, unique_ptr<T, D>& rhs)
  76. {lhs.swap(rhs);}
  77. template<class T, class U>
  78. move_unique_ptr<T, default_delete<T> > make_unique(const U& v) //dont use auto
  79. {return move_unique_ptr<T, default_delete<T> >(new T(v), default_delete<T>());}
  80. template<class T>
  81. move_unique_ptr<T, default_delete<T> > make_unique() //dont use auto
  82. {return move_unique_ptr<T, default_delete<T> >(new T(), default_delete<T>());}
  83. template<class T, class D>
  84. move_unique_ptr<T, D> move(unique_ptr<T, D>& rhs)
  85. {return move_unique_ptr<T, D>(rhs.release(), rhs.get_deleter());}
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96. struct reporter {
  97. reporter() {std::cout<<"default construct\n";}
  98. reporter(const reporter&) {std::cout<<"copy construct\n";}
  99. reporter& operator=(const reporter&) {std::cout<<"assignment\n";}
  100. ~reporter() {std::cout<<"destructor\n";}
  101. };
  102. move_unique_ptr<reporter> myfunc(unique_ptr<reporter> obj)
  103. {
  104. std::cout << "o="<<obj << '\n';
  105. return move(obj);
  106. }
  107.  
  108. int main() {
  109. unique_ptr<reporter> a;
  110. std::cout << "a="<<a << '\n';
  111. unique_ptr<reporter> b = make_unique<reporter>();
  112. std::cout << "b="<<b << '\n';
  113. //unique_ptr<reporter > c = myfunc(b); //fails to compile
  114. unique_ptr<reporter> c = myfunc(move(b));
  115. std::cout << "b="<<b << '\n';
  116. std::cout << "c="<<c << '\n';
  117. a = myfunc(move(c));
  118. std::cout << "a="<<a << '\n';
  119. std::cout << "c="<<c << '\n';
  120. //b = a; //fails to compile
  121. b = move(a);
  122. std::cout << "a="<<a << '\n';
  123. std::cout << "b="<<b << '\n';
  124. return 0;
  125. }
  126.  
  127. /* output should be:
  128. a=0x00000000
  129. default construct
  130. b=POINTER
  131. o=POINTER
  132. b=0x00000000
  133. c=POINTER
  134. o=POINTER
  135. a=POINTER
  136. c=0x00000000
  137. a=0x00000000
  138. b=POINTER
  139. DESTRUCTOR
  140. */
  141.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp: In member function ‘reporter& reporter::operator=(const reporter&)’:
prog.cpp:99: warning: no return statement in function returning non-void
prog.cpp: In function ‘int main()’:
prog.cpp:111: error: no matching function for call to ‘unique_ptr<reporter, default_delete<reporter> >::unique_ptr(unique_ptr<reporter, default_delete<reporter> >)’
prog.cpp:71: note: candidates are: unique_ptr<T, D>::unique_ptr(unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:40: note:                 unique_ptr<T, D>::unique_ptr(const move_unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:114: error: no matching function for call to ‘unique_ptr<reporter, default_delete<reporter> >::unique_ptr(unique_ptr<reporter, default_delete<reporter> >)’
prog.cpp:71: note: candidates are: unique_ptr<T, D>::unique_ptr(unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:40: note:                 unique_ptr<T, D>::unique_ptr(const move_unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:114: error:   initializing argument 1 of ‘move_unique_ptr<reporter, default_delete<reporter> > myfunc(unique_ptr<reporter, default_delete<reporter> >)’
prog.cpp:114: error: no matching function for call to ‘unique_ptr<reporter, default_delete<reporter> >::unique_ptr(unique_ptr<reporter, default_delete<reporter> >)’
prog.cpp:71: note: candidates are: unique_ptr<T, D>::unique_ptr(unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:40: note:                 unique_ptr<T, D>::unique_ptr(const move_unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:117: error: no matching function for call to ‘unique_ptr<reporter, default_delete<reporter> >::unique_ptr(unique_ptr<reporter, default_delete<reporter> >)’
prog.cpp:71: note: candidates are: unique_ptr<T, D>::unique_ptr(unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:40: note:                 unique_ptr<T, D>::unique_ptr(const move_unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:117: error:   initializing argument 1 of ‘move_unique_ptr<reporter, default_delete<reporter> > myfunc(unique_ptr<reporter, default_delete<reporter> >)’
prog.cpp:117: error: no match for ‘operator=’ in ‘a = myfunc(unique_ptr<reporter, default_delete<reporter> >)()’
prog.cpp:44: note: candidates are: unique_ptr<T, D>& unique_ptr<T, D>::operator=(move_unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:72: note:                 unique_ptr<T, D>& unique_ptr<T, D>::operator=(unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:121: error: no match for ‘operator=’ in ‘b = move(unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]()’
prog.cpp:44: note: candidates are: unique_ptr<T, D>& unique_ptr<T, D>::operator=(move_unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
prog.cpp:72: note:                 unique_ptr<T, D>& unique_ptr<T, D>::operator=(unique_ptr<T, D>&) [with T = reporter, D = default_delete<reporter>]
stdout
Standard output is empty