Advertisement
Guest User

Untitled

a guest
Jul 21st, 2019
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.77 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <boost/optional.hpp>
  4.  
  5. namespace util {
  6.  
  7. namespace shared_value_detail {
  8. using boost::optional;
  9.  
  10. // Some values that we'd like to put into shared_value don't have the move
  11. // assign operator. As long as they have the move constructor we can still
  12. // use them.
  13. template<typename T, bool has_move_assign_op> struct assign;
  14.  
  15. template<typename T>
  16. struct assign<optional<T>, true> {
  17. static void move(optional<T>& dst, optional<T>& src) {
  18. dst = std::move(src);
  19. }
  20. };
  21.  
  22. template<typename T>
  23. struct assign<optional<T>, false> {
  24. static void move(optional<T>& dst, optional<T>& src) {
  25. // Destroying should be cheap because we always destroy
  26. // non initialized optional<T>.
  27. assert(dst == boost::none);
  28. dst.~optional<T>();
  29. new (&dst) optional<T>(std::move(src));
  30. }
  31. };
  32. };
  33.  
  34. template<typename T>
  35. class shared_value {
  36. public:
  37. using value_type = std::decay_t<T>;
  38.  
  39. shared_value() = default;
  40.  
  41. shared_value(const shared_value&);
  42. shared_value& operator=(const shared_value&);
  43.  
  44. template<typename K> shared_value(K);
  45.  
  46. value_type& operator*() { return *value(); }
  47. const value_type& operator*() const { return *value(); }
  48.  
  49. value_type* operator->() { return value(); }
  50. const value_type* operator->() const { return value(); }
  51.  
  52. ~shared_value();
  53.  
  54. private:
  55. void remove_self();
  56. void append_self_to_end(const shared_value&);
  57. value_type* value();
  58.  
  59. private:
  60. shared_value* _prev = nullptr;
  61. shared_value* _next = nullptr;
  62.  
  63. // We use optional to handle the case where value_type
  64. // doesn't have the default constructor.
  65. boost::optional<value_type> _value;
  66. };
  67.  
  68. template<typename T>
  69. inline
  70. shared_value<T>::shared_value(const shared_value& other)
  71. {
  72. append_self_to_end(other);
  73. }
  74.  
  75. template<typename T>
  76. template<typename K>
  77. inline
  78. shared_value<T>::shared_value(K value)
  79. : _value(std::move(value))
  80. {
  81. }
  82.  
  83. template<typename T>
  84. inline
  85. shared_value<T>& shared_value<T>::operator=(const shared_value& other)
  86. {
  87. // Do nothing if this and other already share the same value.
  88. if (value() == other.value()) return *this;
  89.  
  90. remove_self();
  91. append_self_to_end(other);
  92.  
  93. return this;
  94. }
  95.  
  96. template<typename T>
  97. inline
  98. void shared_value<T>::append_self_to_end(const shared_value& other)
  99. {
  100. shared_value* last = const_cast<shared_value*>(&other);
  101. while (last->_next) { last = last->_next; }
  102. last->_next = this;
  103. _prev = last;
  104. assert(_next = nullptr);
  105. }
  106.  
  107. template<typename T>
  108. inline
  109. void shared_value<T>::remove_self()
  110. {
  111. if (_prev) {
  112. // We're not the first, so we don't have the value
  113. assert(!_value);
  114. _prev->_next = _next;
  115. if (_next) { _next->_prev = _prev; _next = nullptr; }
  116. _prev = nullptr;
  117. return;
  118. }
  119.  
  120. if (_next == nullptr) {
  121. // We're the value owners, but we're not sharing it with anyone else.
  122. // Thus destroy the value and exit.
  123. _value = boost::none;
  124. return;
  125. }
  126.  
  127. // We're the owners of the value and we're sharing it with others. Move the
  128. // value to the next one in line.
  129. shared_value_detail::assign< boost::optional<value_type>
  130. , std::is_move_assignable<value_type>::value
  131. >::move(_next->_value, _value);
  132.  
  133. _value = boost::none;
  134. _next->_prev = nullptr;
  135. _next = nullptr;
  136. }
  137.  
  138. template<typename T>
  139. inline
  140. typename shared_value<T>::value_type* shared_value<T>::value()
  141. {
  142. shared_value* first = this;
  143. while (first->_prev) { first = first->_prev; }
  144. if (!first->_value) return nullptr;
  145. return &*first->_value;
  146. }
  147.  
  148. template<typename T>
  149. inline
  150. shared_value<T>::~shared_value()
  151. {
  152. remove_self();
  153. }
  154.  
  155. } // namespace
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement