DGtal  0.9.2
CowPtr.h
1 
17 #pragma once
18 
33 #if defined(CowPtr_RECURSES)
34 #error Recursive header files inclusion detected in CowPtr.h
35 #else // defined(CowPtr_RECURSES)
36 
37 #define CowPtr_RECURSES
38 
39 #if !defined CowPtr_h
40 
41 #define CowPtr_h
42 
44 // Inclusions
45 #include <iostream>
46 #include <type_traits>
47 #include "DGtal/base/Common.h"
48 #include "DGtal/base/CountedPtr.h"
50 
51 namespace DGtal
52 {
53 
55  // template class CowPtr
66  template <typename T>
67  class CowPtr
68  {
69  // ----------------------- Standard services ------------------------------
70  public:
71 public:
72  typedef T element_type;
73 
74  explicit CowPtr(T* p = 0) throw() : myPtr(p) {}
75  // no need for ~CowPtr - the CountedPtr takes care of everything.
76  CowPtr(const CowPtr& r) throw() : myPtr(r.myPtr) {}
80  CowPtr(const CountedPtr<T> & r) : myPtr( r ) {}
81  CowPtr& operator=(const CowPtr& r)
82  {
83  if (this != &r)
84  myPtr = r.myPtr;
85  return *this;
86  }
87 
88 
89  const T& operator*() const throw() {return *myPtr;}
90  const T* operator->() const throw() {return myPtr.get();}
91  const T* get() const throw() {return myPtr.get();}
92 
93  /* The following non-const methods are deactivated if T is a const type.
94  * The goal here is to avoid unecessary copies when it is known that
95  * the T object will not be modified.
96  *
97  * The problem is that C++ uses the non-const methods whenever it's possible
98  * (ie when CowPtr<T> is non-const), even if the full expression doesn't
99  * modify the object. A solution is to const_cast the CowPtr<T> before
100  * using one of these methods to force the usage of the const versions above.
101  *
102  * However, in the trivial case when T is a const type, we can simplify this
103  * by deactivating those methods.
104  *
105  * To do that, we use std::enable_if (see http://en.cppreference.com/w/cpp/types/enable_if )
106  * in the template parameters (it is also possible in the return type or
107  * as a parameter but it will change the signature). It depends on
108  * the constness of T returned by the type trait std::is_const.
109  * The `typename U = T` is necessary in order that the SFINAE rule works at the overload
110  * resolution step.
111  */
112  template < typename U = T, typename std::enable_if< ! std::is_const<U>::value >::type* = nullptr >
113  T& operator*() {copy(); return *myPtr;}
114 
115  template < typename U = T, typename std::enable_if< ! std::is_const<U>::value >::type* = nullptr >
116  T* operator->() {copy(); return myPtr.get();}
117 
118  template < typename U = T, typename std::enable_if< ! std::is_const<U>::value >::type* = nullptr >
119  T* get() {copy(); return myPtr.get();}
120 
127  bool operator==( const T* other ) const
128  {
129  return get() == other;
130  }
131 
138  bool operator!=( const T* other ) const
139  {
140  return get() != other;
141  }
142 
143 
147  unsigned int count() const {return myPtr.count();}
148  inline T* drop() { return myPtr.drop(); }
149  inline bool unique() const throw() { return myPtr.unique(); }
150 
151  private:
152 
153  // ------------------------- Private Datas --------------------------------
154  private:
155 
157 
158  // ------------------------- Internals ------------------------------------
159  private:
160  void copy() // create a new copy of myPtr
161  {
162  if (!myPtr.unique()) {
163  T* old_p = myPtr.get();
164  myPtr = CountedPtr<T>(new T(*old_p));
165  }
166  }
167 
168 
169  // ----------------------- Interface --------------------------------------
170  public:
171 
176  void selfDisplay ( std::ostream & out ) const;
177 
182  bool isValid() const;
183 
184  // ------------------------- Protected Datas ------------------------------
185  private:
186 
187  // ------------------------- Hidden services ------------------------------
188  protected:
189 
190 
191 
192  }; // end of class CowPtr
193 
194 
201  template <typename T>
202  std::ostream&
203  operator<< ( std::ostream & out, const CowPtr<T> & object );
204 
205 } // namespace DGtal
206 
207 
209 // Includes inline functions.
210 #include "DGtal/base/CowPtr.ih"
211 
212 // //
214 
215 #endif // !defined CowPtr_h
216 
217 #undef CowPtr_RECURSES
218 #endif // else defined(CowPtr_RECURSES)
const T & operator*() const
Definition: CowPtr.h:89
CowPtr(const CowPtr &r)
Definition: CowPtr.h:76
T element_type
Definition: CowPtr.h:72
Aim: Smart pointer based on reference counts.
Definition: CountedPtr.h:79
CowPtr(T *p=0)
Definition: CowPtr.h:74
T * operator->()
Definition: CowPtr.h:116
bool unique() const
Definition: CountedPtr.h:204
T * get() const
Definition: CountedPtr.h:195
bool operator!=(const T *other) const
Definition: CowPtr.h:138
CowPtr(const CountedPtr< T > &r)
Definition: CowPtr.h:80
CountedPtr< T > myPtr
Definition: CowPtr.h:156
T * drop()
Definition: CowPtr.h:148
bool operator==(const T *other) const
Definition: CowPtr.h:127
CowPtr & operator=(const CowPtr &r)
Definition: CowPtr.h:81
unsigned int count() const
Definition: CowPtr.h:147
DGtal is the top-level namespace which contains all DGtal functions and types.
void copy()
Definition: CowPtr.h:160
const T * operator->() const
Definition: CowPtr.h:90
bool isValid() const
T & operator*()
Definition: CowPtr.h:113
void selfDisplay(std::ostream &out) const
bool unique() const
Definition: CowPtr.h:149
Aim: Copy on write shared pointer.
Definition: CowPtr.h:67