CBMC
small_shared_ptr.h
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Small intrusive shared pointers
4 
5 Author: Reuben Thomas, reuben.thomas@diffblue.com
6 
7 \*******************************************************************/
8 
9 #ifndef CPROVER_UTIL_SMALL_SHARED_PTR_H
10 #define CPROVER_UTIL_SMALL_SHARED_PTR_H
11 
12 #include <iosfwd> // ostream
13 #include <utility> // swap
14 
15 // TODO We should liberally scatter `constexpr`s and `noexcept`s on platforms
16 // that support them.
17 
23 template <typename T>
24 class small_shared_ptrt final
25 {
26 public:
27  small_shared_ptrt() = default;
28 
29  explicit small_shared_ptrt(T *t) : t_(t)
30  {
31  if(t_)
32  {
34  }
35  }
36 
38  {
39  if(t_)
40  {
42  }
43  }
44 
46  {
47  auto copy(rhs);
48  swap(copy);
49  return *this;
50  }
51 
53  {
54  swap(rhs);
55  }
56 
58  {
59  swap(rhs);
60  return *this;
61  }
62 
64  {
65  if(!t_)
66  {
67  return;
68  }
69  if(pointee_use_count(*t_) == 1)
70  {
71  delete t_;
72  return;
73  }
75  }
76 
78  {
79  std::swap(t_, rhs.t_);
80  }
81 
82  T *get() const
83  {
84  return t_;
85  }
86 
87  T &operator*() const
88  {
89  return *t_;
90  }
91 
92  T *operator->() const
93  {
94  return t_;
95  }
96 
97  auto use_count() const -> decltype(pointee_use_count(std::declval<T>()))
98  {
99  return t_ ? pointee_use_count(*t_) : 0;
100  }
101 
102  explicit operator bool() const
103  {
104  return t_ != nullptr;
105  }
106 
107 private:
108  T *t_ = nullptr;
109 };
110 
111 template <typename T>
112 std::ostream &operator<<(std::ostream &os, const small_shared_ptrt<T> &ptr)
113 {
114  return os << ptr.get();
115 }
116 
122 template <typename T, typename... Ts>
124 {
125  return small_shared_ptrt<T>(new T(std::forward<Ts>(ts)...));
126 }
127 
128 template <typename T, typename U>
130  const small_shared_ptrt<T> &lhs,
131  const small_shared_ptrt<U> &rhs)
132 {
133  return lhs.get() == rhs.get();
134 }
135 
136 template <typename T, typename U>
138  const small_shared_ptrt<T> &lhs,
139  const small_shared_ptrt<U> &rhs)
140 {
141  return lhs.get() != rhs.get();
142 }
143 
144 template <typename T, typename U>
146 {
147  return lhs.get() < rhs.get();
148 }
149 
150 template <typename T, typename U>
152 {
153  return lhs.get() > rhs.get();
154 }
155 
156 template <typename T, typename U>
158  const small_shared_ptrt<T> &lhs,
159  const small_shared_ptrt<U> &rhs)
160 {
161  return lhs.get() <= rhs.get();
162 }
163 
164 template <typename T, typename U>
166  const small_shared_ptrt<T> &lhs,
167  const small_shared_ptrt<U> &rhs)
168 {
169  return lhs.get() >= rhs.get();
170 }
171 
173 
181 template <typename Num>
183 {
184 public:
186 
187  // These can't be `= default` because we need the use_count_ to be unaffected
189  {
190  }
192  {
193  return *this;
194  }
196  {
197  }
199  {
200  return *this;
201  }
202 
204  {
205  ++use_count_;
206  }
208  {
209  --use_count_;
210  }
211  Num use_count() const
212  {
213  return use_count_;
214  }
215 
216 protected:
217  // Enables public inheritance but disables polymorphic usage
219 
220 private:
221  Num use_count_ = 0;
222 };
223 
231 
232 template <typename Num>
234 {
236 }
237 
238 template <typename Num>
240 {
242 }
243 
244 template <typename Num>
246 {
247  return p.use_count();
248 }
249 
250 #endif
A helper class to store use-counts of objects held by small shared pointers.
~small_shared_pointeet()=default
small_shared_pointeet & operator=(small_shared_pointeet &&)
small_shared_pointeet()=default
small_shared_pointeet & operator=(const small_shared_pointeet &)
small_shared_pointeet(const small_shared_pointeet &)
small_shared_pointeet(small_shared_pointeet &&)
This class is really similar to boost's intrusive_pointer, but can be a bit simpler seeing as we're o...
small_shared_ptrt()=default
auto use_count() const -> decltype(pointee_use_count(std::declval< T >()))
small_shared_ptrt(const small_shared_ptrt &rhs)
small_shared_ptrt & operator=(small_shared_ptrt &&rhs)
small_shared_ptrt(small_shared_ptrt &&rhs)
small_shared_ptrt & operator=(const small_shared_ptrt &rhs)
T * operator->() const
T & operator*() const
void swap(small_shared_ptrt &rhs)
small_shared_ptrt< T > make_small_shared_ptr(Ts &&... ts)
This function is similar to std::make_unique and std::make_shared, and should be the preferred way of...
void pointee_decrement_use_count(small_shared_pointeet< Num > &p)
bool operator<(const small_shared_ptrt< T > &lhs, const small_shared_ptrt< U > &rhs)
bool operator>=(const small_shared_ptrt< T > &lhs, const small_shared_ptrt< U > &rhs)
void pointee_increment_use_count(small_shared_pointeet< Num > &p)
The following functions are required by small_shared_ptrt, and by default pass through to the member ...
bool operator>(const small_shared_ptrt< T > &lhs, const small_shared_ptrt< U > &rhs)
std::ostream & operator<<(std::ostream &os, const small_shared_ptrt< T > &ptr)
bool operator<=(const small_shared_ptrt< T > &lhs, const small_shared_ptrt< U > &rhs)
bool operator==(const small_shared_ptrt< T > &lhs, const small_shared_ptrt< U > &rhs)
Num pointee_use_count(const small_shared_pointeet< Num > &p)
bool operator!=(const small_shared_ptrt< T > &lhs, const small_shared_ptrt< U > &rhs)