DGtal  1.0.0
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) noexcept : myPtr(p) {}
75  // no need for ~CowPtr - the CountedPtr takes care of everything.
76  CowPtr(const CowPtr& r) noexcept : myPtr(r.myPtr) {}
106  CowPtr(const CountedPtr<T> & r, bool /* unused */ ) : myPtr( r ) {}
108  {
109  if (this != &r)
110  myPtr = r.myPtr;
111  return *this;
112  }
113 
114 
115  const T& operator*() const noexcept {return *myPtr;}
116  const T* operator->() const noexcept {return myPtr.get();}
117  const T* get() const noexcept {return myPtr.get();}
118 
119  /* The following non-const methods are deactivated if T is a const type.
120  * The goal here is to avoid unecessary copies when it is known that
121  * the T object will not be modified.
122  *
123  * The problem is that C++ uses the non-const methods whenever it's possible
124  * (ie when CowPtr<T> is non-const), even if the full expression doesn't
125  * modify the object. A solution is to const_cast the CowPtr<T> before
126  * using one of these methods to force the usage of the const versions above.
127  *
128  * However, in the trivial case when T is a const type, we can simplify this
129  * by deactivating those methods.
130  *
131  * To do that, we use std::enable_if (see http://en.cppreference.com/w/cpp/types/enable_if )
132  * in the template parameters (it is also possible in the return type or
133  * as a parameter but it will change the signature). It depends on
134  * the constness of T returned by the type trait std::is_const.
135  * The `typename U = T` is necessary in order that the SFINAE rule works at the overload
136  * resolution step.
137  */
138  template < typename U = T, typename std::enable_if< ! std::is_const<U>::value >::type* = nullptr >
139  T& operator*() {copy(); return *myPtr;}
140 
141  template < typename U = T, typename std::enable_if< ! std::is_const<U>::value >::type* = nullptr >
142  T* operator->() {copy(); return myPtr.get();}
143 
144  template < typename U = T, typename std::enable_if< ! std::is_const<U>::value >::type* = nullptr >
145  T* get() {copy(); return myPtr.get();}
146 
153  bool operator==( const T* other ) const
154  {
155  return get() == other;
156  }
157 
164  bool operator!=( const T* other ) const
165  {
166  return get() != other;
167  }
168 
169 
173  unsigned int count() const { return myPtr.count(); }
174  inline T* drop() { return myPtr.drop(); }
175  inline bool unique() const noexcept { return myPtr.unique(); }
176 
177  private:
178 
179  // ------------------------- Private Datas --------------------------------
180  private:
181 
183 
184  // ------------------------- Internals ------------------------------------
185  private:
186  void copy() // create a new copy of myPtr
187  {
188  if (!myPtr.unique()) {
189  T* old_p = myPtr.get();
190  myPtr = CountedPtr<T>(new T(*old_p));
191  }
192  }
193 
194 
195  // ----------------------- Interface --------------------------------------
196  public:
197 
202  void selfDisplay ( std::ostream & out ) const;
203 
208  bool isValid() const;
209 
210  // ------------------------- Protected Datas ------------------------------
211  private:
212 
213  // ------------------------- Hidden services ------------------------------
214  protected:
215 
216 
217 
218  }; // end of class CowPtr
219 
220 
227  template <typename T>
228  std::ostream&
229  operator<< ( std::ostream & out, const CowPtr<T> & object );
230 
231 } // namespace DGtal
232 
233 
235 // Includes inline functions.
236 #include "DGtal/base/CowPtr.ih"
237 
238 // //
240 
241 #endif // !defined CowPtr_h
242 
243 #undef CowPtr_RECURSES
244 #endif // else defined(CowPtr_RECURSES)
T element_type
Definition: CowPtr.h:72
const T * operator->() const noexcept
Definition: CowPtr.h:116
bool operator==(const T *other) const
Definition: CowPtr.h:153
const T & operator *() const noexcept
Definition: CowPtr.h:115
void selfDisplay(std::ostream &out) const
Aim: Smart pointer based on reference counts.
Definition: CountedPtr.h:79
bool isValid() const
CowPtr(const CowPtr &r) noexcept
Definition: CowPtr.h:76
bool operator!=(const T *other) const
Definition: CowPtr.h:164
T * operator->()
Definition: CowPtr.h:142
const T * get() const noexcept
Definition: CowPtr.h:117
CowPtr(T *p=0) noexcept
Definition: CowPtr.h:74
CountedPtr< T > myPtr
Definition: CowPtr.h:182
std::ostream & operator<<(std::ostream &out, const ClosedIntegerHalfPlane< TSpace > &object)
T * drop()
Definition: CowPtr.h:174
unsigned int count() const
Definition: CowPtr.h:173
CowPtr(const CountedPtr< T > &r, bool)
Definition: CowPtr.h:106
CowPtr & operator=(const CowPtr &r)
Definition: CowPtr.h:107
DGtal is the top-level namespace which contains all DGtal functions and types.
void copy()
Definition: CowPtr.h:186
bool unique() const noexcept
Definition: CowPtr.h:175
T * get()
Definition: CowPtr.h:145
Aim: Copy on write shared pointer.
Definition: CowPtr.h:67