dune-common  2.2.0
shared_ptr.hh
Go to the documentation of this file.
1 // $Id: smartpointer.hh 5504 2009-04-08 13:35:31Z christi $
2 
3 #ifndef DUNE_SHARED_PTR_HH
4 #define DUNE_SHARED_PTR_HH
5 
6 #if defined SHARED_PTR_HEADER
7 # include SHARED_PTR_HEADER
8 #endif
9 #if defined HAVE_BOOST_SHARED_PTR_HPP
10 #if defined HAVE_BOOST_MAKE_SHARED_HPP
11 # include <boost/make_shared.hpp>
12 #endif
13 #endif
14 
15 #include<dune/common/nullptr.hh>
23 namespace Dune
24 {
25  // A shared_ptr implementation has been found if SHARED_PTR_NAMESPACE is set at all
26 #ifdef SHARED_PTR_NAMESPACE
27  using SHARED_PTR_NAMESPACE :: shared_ptr;
28 #else
29 
41  template<class T>
42  class shared_ptr
43  {
44  public:
50  typedef T element_type;
51 
55  inline shared_ptr();
56 
65  inline shared_ptr(T * pointer);
66 
79  template<class Deleter>
80  inline shared_ptr(T * pointer, Deleter deleter);
81 
86  inline shared_ptr(const shared_ptr<T>& pointer);
87 
91  inline ~shared_ptr();
92 
94  inline shared_ptr& operator=(const shared_ptr<T>& pointer);
95 
97  inline element_type& operator*();
98 
100  inline element_type* operator->();
101 
103  inline const element_type& operator*() const;
104 
106  inline const element_type* operator->() const;
107 
109  element_type* get() const {
110  return rep_==0 ? 0 : rep_->rep_;
111  }
112 
114  inline void swap(shared_ptr& other);
115 
119  inline void reset();
120 
122  inline void reset(T* pointer);
123 
124  //** \brief Same as shared_ptr(pointer,deleter).swap(*this)
125  template<class Deleter>
126  inline void reset(T* pointer, Deleter deleter);
127 
129  int use_count() const;
130 
131  private:
133  class PointerRep
134  {
135  friend class shared_ptr<element_type>;
136  protected:
138  int count_;
140  element_type * rep_;
142  PointerRep(element_type * p) : count_(1), rep_(p) {}
144  virtual ~PointerRep() {};
145  };
146 
148  template<class Deleter>
149  class PointerRepImpl :
150  public PointerRep
151  {
152  friend class shared_ptr<element_type>;
153 
155  PointerRepImpl(element_type * p, const Deleter& deleter) :
156  PointerRep(p),
157  deleter_(deleter)
158  {}
159 
161  ~PointerRepImpl()
162  { deleter_(this->rep_); }
163 
164  // store a copy of the deleter
165  Deleter deleter_;
166  };
167 
169  struct DefaultDeleter
170  {
171  void operator() (element_type* p) const
172  { delete p; }
173  };
174 
175 
176  PointerRep *rep_;
177 
178  // Needed for the implicit conversion to "bool"
179  typedef T* shared_ptr::PointerRep::*__unspecified_bool_type;
180 
181  public:
183  operator __unspecified_bool_type() const // never throws
184  {
185  return rep_ == 0 ? 0 : &shared_ptr::PointerRep::rep_;
186  }
187 
188 
189  };
190 
191  template<class T>
193  {
194  rep_ = new PointerRepImpl<DefaultDeleter>(p, DefaultDeleter());
195  }
196 
197  template<class T>
198  template<class Deleter>
199  inline shared_ptr<T>::shared_ptr(T * p, Deleter deleter)
200  {
201  rep_ = new PointerRepImpl<Deleter>(p, deleter);
202  }
203 
204  template<class T>
206  {
207  rep_ = nullptr;
208  }
209 
210  template<class T>
211  inline shared_ptr<T>::shared_ptr(const shared_ptr<T>& other) : rep_(other.rep_)
212  {
213  if (rep_)
214  ++(rep_->count_);
215  }
216 
217  template<class T>
219  {
220  if (other.rep_)
221  (other.rep_->count_)++;
222 
223  if(rep_!=0 && --(rep_->count_)<=0)
224  delete rep_;
225 
226  rep_ = other.rep_;
227  return *this;
228  }
229 
230  template<class T>
232  {
233  if(rep_!=0 && --(rep_->count_)==0){
234  delete rep_;
235  rep_=0;
236  }
237  }
238 
239  template<class T>
241  {
242  return *(rep_->rep_);
243  }
244 
245  template<class T>
247  {
248  return rep_->rep_;
249  }
250 
251  template<class T>
252  inline const T& shared_ptr<T>::operator*() const
253  {
254  return *(rep_->rep_);
255  }
256 
257  template<class T>
258  inline const T *shared_ptr<T>::operator->() const
259  {
260  return rep_->rep_;
261  }
262 
263  template<class T>
264  inline int shared_ptr<T>::use_count() const
265  {
266  return rep_->count_;
267  }
268 
269  template<class T>
270  inline void shared_ptr<T>::swap(shared_ptr<T>& other)
271  {
272  PointerRep* dummy = rep_;
273  rep_ = other.rep_;
274  other.rep_ = dummy;
275  }
276 
277  template<class T>
278  inline void shared_ptr<T>::reset()
279  {
280  shared_ptr<T>().swap(*this);
281  }
282 
283  template<class T>
284  inline void shared_ptr<T>::reset(T* pointer)
285  {
286  shared_ptr<T>(pointer).swap(*this);
287  }
288 
289  template<class T>
290  template<class Deleter>
291  inline void shared_ptr<T>::reset(T* pointer, Deleter deleter)
292  {
293  shared_ptr<T>(pointer, deleter).swap(*this);
294  }
295 
297 #endif // #ifdef SHARED_PTR_NAMESPACE
298 
299 
300 // C++0x and Boost have a make_shared implementation, TR1 does not.
301 // Unfortunately, TR1 gets picked over Boost if present.
302 // Moreover, boost::make_shared() only exists for (remotely) recent versions of Boost.
303 #if HAVE_MAKE_SHARED
304 #ifdef SHARED_PTR_NAMESPACE
306 #endif
307 #else
308 
309  template<typename T>
311  {
312  return shared_ptr<T>(new T());
313  }
314 
315  template<typename T, typename Arg1>
316  shared_ptr<T> make_shared(const Arg1& arg1)
317  {
318  return shared_ptr<T>(new T(arg1));
319  }
320 
321  template<typename T, typename Arg1, typename Arg2>
322  shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2)
323  {
324  return shared_ptr<T>(new T(arg1,arg2));
325  }
326 
327  template<typename T, typename Arg1, typename Arg2, typename Arg3>
328  shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
329  {
330  return shared_ptr<T>(new T(arg1,arg2,arg3));
331  }
332 
333  template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
334  shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)
335  {
336  return shared_ptr<T>(new T(arg1,arg2,arg3,arg4));
337  }
338 
339  template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
340  typename Arg5>
341  shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
342  const Arg5& arg5)
343  {
344  return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5));
345  }
346 
347  template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
348  typename Arg5, typename Arg6>
349  shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
350  const Arg5& arg5, const Arg6& arg6)
351  {
352  return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6));
353  }
354 
355  template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
356  typename Arg5, typename Arg6, typename Arg7>
357  shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
358  const Arg5& arg5, const Arg6& arg6, const Arg7& arg7)
359  {
360  return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6,arg7));
361  }
362 
363  template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
364  typename Arg5, typename Arg6, typename Arg7, typename Arg8>
365  shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
366  const Arg5& arg5, const Arg6& arg6, const Arg7& arg7, const Arg8& arg8)
367  {
368  return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8));
369  }
370 
371  template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4,
372  typename Arg5, typename Arg6, typename Arg7, typename Arg8, typename Arg9>
373  shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4,
374  const Arg5& arg5, const Arg6& arg6, const Arg7& arg7, const Arg8& arg8,
375  const Arg9& arg9)
376  {
377  return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9));
378  }
379 
380 #endif // custom make_shared
381 
410  template<class T>
412  {
413  void operator() (T* p) const {}
414  };
415 
424  template<typename T>
425  inline shared_ptr<T> stackobject_to_shared_ptr(T & t)
426  {
427  return shared_ptr<T>(&t, null_deleter<T>());
428  }
429 
443  template<typename T, typename T2>
444  inline shared_ptr<T2> stackobject_to_shared_ptr(T & t)
445  {
446  return shared_ptr<T2>(dynamic_cast<T2*>(&t), null_deleter<T2>());
447  }
448 
449 }
450 #endif