fork download
  1. #include <memory>
  2. #include <vector>
  3. #include <functional>
  4. #include <iostream>
  5. #include <algorithm>
  6.  
  7. template<class T>
  8. class observer_ptr;
  9.  
  10. template <typename T>
  11. class observable_delete {
  12. std::vector<observer_ptr<T>*> notifyList;
  13. public:
  14. void remove_observable(observer_ptr<T>* remove_this);
  15. void add_observable(observer_ptr<T>* add_this);
  16. void operator()(T* obj) const;
  17. };
  18.  
  19. template <typename T>
  20. class observer_ptr {
  21. T* pt = nullptr;
  22. observable_delete<T>* deleter;
  23. bool has_callback;
  24. std::function<void (T*)> callback;
  25. public:
  26. observer_ptr(const observer_ptr<T> &other) : pt(other.pt), deleter(other.deleter), has_callback(other.has_callback), callback(other.callback) {
  27. deleter->add_observable(this);
  28. }
  29. observer_ptr(observer_ptr<T> &&other) : pt(other.pt), deleter(other.deleter), has_callback(other.has_callback), callback(std::move(other.callback)) {
  30. deleter->remove_observable(&other);
  31. other.pt = nullptr; //flags temporary as expired.
  32. deleter->add_observable(this);
  33. }
  34. observer_ptr<T> operator=(const observer_ptr<T> &other) = delete;
  35.  
  36. observer_ptr(std::unique_ptr<T, observable_delete<T>>* observed) : pt(observed->get()), deleter(&observed->get_deleter()), has_callback(false) {
  37. deleter->add_observable(this);
  38. }
  39.  
  40. observer_ptr(std::unique_ptr<T, observable_delete<T>>* observed, const std::function<void(T*)> &callback) : pt(observed->get()), deleter(&observed->get_deleter()), callback(callback), has_callback(true) {
  41. deleter->add_observable(this);
  42. }
  43.  
  44. ~observer_ptr() {
  45. if (!expired()) {
  46. deleter->remove_observable(this);
  47. }
  48. }
  49.  
  50. void observed_has_died() {
  51. if (has_callback) {
  52. callback(pt);
  53. }
  54. pt = nullptr;
  55. }
  56.  
  57. bool expired() const {
  58. return pt == nullptr;
  59. }
  60.  
  61. T* operator->() const { return pt; }
  62. T& operator*() const { return *pt; }
  63. };
  64.  
  65. template <typename T>
  66. void observable_delete<T>::remove_observable(observer_ptr<T>* remove_this) {
  67. auto found = std::find(notifyList.begin(), notifyList.end(), remove_this);
  68. if (found != notifyList.end()) {
  69. notifyList.erase(found);
  70. }
  71. }
  72.  
  73. template <typename T>
  74. void observable_delete<T>::add_observable(observer_ptr<T>* add_this) {
  75. notifyList.push_back(add_this);
  76. }
  77.  
  78. template <typename T>
  79. void observable_delete<T>::operator()(T* obj) const {
  80. for (auto&& item : notifyList) {
  81. try {
  82. item->observed_has_died();
  83. } catch (...) {
  84. delete obj;
  85. throw;
  86. }
  87. }
  88. delete obj;
  89. }
  90.  
  91. template<typename T, typename... Args>
  92. std::unique_ptr<T, observable_delete<T>> make_observable_unique(Args&&... args) {
  93. return std::unique_ptr<T, observable_delete<T>>(new T(std::forward<Args>(args)...));
  94. }
  95.  
  96. template<typename T>
  97. observer_ptr<T> make_observer(std::unique_ptr<T, observable_delete<T>> &observed) {
  98. return observer_ptr<T>(&observed);
  99. }
  100.  
  101. template<typename T, typename F>
  102. observer_ptr<T> make_observer(std::unique_ptr<T, observable_delete<T>> &observed, const F &callback) {
  103. return observer_ptr<T>(&observed, callback);
  104. }
  105.  
  106. int main() {
  107. auto uniquePtrValue = make_observable_unique<int>(5);
  108. auto observer = make_observer(uniquePtrValue, [](int *value) { std::cout << "We're destroying it! " << *value << std::endl; });
  109. std::cout << (!observer.expired() ? *observer : -1) << std::endl;
  110. uniquePtrValue.reset();
  111. std::cout << (!observer.expired() ? *observer : -1) << std::endl;
  112. return 0;
  113. }
Success #stdin #stdout 0s 3416KB
stdin
Standard input is empty
stdout
5
We're destroying it! 5
-1