vil_smart_ptr.h
Go to the documentation of this file.
1 // This is core/vil/vil_smart_ptr.h
2 #ifndef vil_smart_ptr_h_
3 #define vil_smart_ptr_h_
4 //:
5 // \file
6 // \brief Contains a templated smart pointer class
7 // \author Richard Hartley (original Macro version),
8 // William A. Hoffman (current templated version)
9 //
10 // \verbatim
11 // Modifications
12 // 2000.05.15 Francois BERTEL Added some missing <T>
13 // 2000.05.16 Peter Vanroose Operators > < >= <= made const
14 // 2000.09.13 fsm Added rationale for unprotect().
15 // PDA (Manchester) 23/03/2001: Tidied up the documentation
16 // Peter Vanroose 27/05/2001: Corrected the documentation
17 // Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
18 // 2002.9.20 Ian Scott Copied into vil1, renamed and simplified.
19 // \endverbatim
20 
21 #include <iosfwd>
22 #ifdef _MSC_VER
23 # include <vcl_msvc_warnings.h>
24 #endif
25 
26 //: A templated smart pointer class
27 // This class requires that the class being templated over has
28 // the following signatures (methods) :
29 // \code
30 // void T::ref();
31 // void T::unref();
32 // \endcode
33 //
34 //
35 // See also vbl_ref_count
36 template <class T>
37 class vil_smart_ptr
38 {
39 
40  public:
42  : ptr_(nullptr) { }
43 
45  : ptr_(p.as_pointer()) { if (ptr_) ref(ptr_); }
46 
48  : ptr_(p) { if (ptr_) ref(ptr_); }
49 
51  {
52  // the strange order of events in this function is to avoid
53  // heap corruption if unref() causes *this to be deleted.
54  T *old_ptr = ptr_;
55  ptr_ = nullptr;
56  if (old_ptr)
57  unref(old_ptr);
58  }
59 
60  //: Assignment
62  {
63  return operator=(r.as_pointer());
64  }
65 
67  {
68  if (ptr_ != r)
69  {
70  // If there are circular references, calling unref() may
71  // cause *this to be destroyed and so assigning to 'ptr_'
72  // would be ill-formed and could cause heap corruption.
73  // Hence perform the unref() only at the very end.
74  T *old_ptr = ptr_;
75  ptr_ = r;
76 
77  if (ptr_)
78  ref(ptr_);
79 
80  // *this might get deleted now, but that's ok.
81  if (old_ptr)
82  unref(old_ptr);
83  }
84  return *this;
85  }
86 
87  //: Cast to bool
88  explicit operator bool () const
89  { return (ptr_ != nullptr) ? true : false; }
90 
91  //: Inverse bool
92  bool operator!() const
93  { return (ptr_ != nullptr) ? false : true; }
94 
95  //: Dereferencing the pointer
96  T &operator * () const { return *ptr_; }
97 
98  //: These methods all return the raw/dumb pointer.
99  T *operator -> () const { return ptr_; }
100 
101  //: These methods all return the raw/dumb pointer.
102  T *ptr () const { return ptr_; }
103 
104  //: These methods all return the raw/dumb pointer.
105  //
106  // WARNING : Do not add an automatic cast to T*.
107  // This is intrinsically incorrect as you loose the smartness!
108  // In cases where you really need the pointer, it is better
109  // to be explicit about it and use one of the methods.
110  T *as_pointer () const { return ptr_; }
111 
112  // Relational operators.
113  //There's no need for casts to void* or any other pointer type than T* here.
114 
115  //: Do a shallow equality
116  // Do they point to the same object.
117  bool operator==(T const *p) const { return ptr_ == p; }
118 
119  //: Do a shallow inequality
120  // Do the smart pointers not point to the same object.
121  bool operator!=(T const *p) const { return ptr_ != p; }
122 
123  //: Do a shallow equality
124  // Do they point to the same object.
125  bool operator==(vil_smart_ptr<T>const&p)const{return ptr_ == p.as_pointer();}
126 
127  //: Do a shallow inequality
128  // Do the smart pointers not point to the same object.
129  bool operator!=(vil_smart_ptr<T>const&p)const{return ptr_ != p.as_pointer();}
130  bool operator< (vil_smart_ptr<T>const&p)const{return ptr_ < p.as_pointer();}
131  bool operator> (vil_smart_ptr<T>const&p)const{return ptr_ > p.as_pointer();}
132  bool operator<=(vil_smart_ptr<T>const&p)const{return ptr_ <= p.as_pointer();}
133  bool operator>=(vil_smart_ptr<T>const&p)const{return ptr_ >= p.as_pointer();}
134 
135  private:
136  // These two methods should not be inlined as they call T's ref()
137  // and unref() or are specializations. The big gain from that is
138  // that vil_smart_ptr<T> can be forward declared even if T is still
139  // an incomplete type.
140  static void ref (T *p);
141  static void unref(T *p);
142 
143  //: Pointer to object, or 0.
144  T *ptr_;
145 };
146 
147 
148 //: Comparison of pointer with smart-pointer (cannot be a member function)
149 template <class T>
150 inline bool operator== (T const* p, vil_smart_ptr<T> const& a)
151 {
152  return a.as_pointer() == p;
153 }
154 
155 template <class T>
156 inline bool operator!= (T const* p, vil_smart_ptr<T> const& a)
157 {
158  return a.as_pointer() != p;
159 }
160 
161 // GCC need a std::ostream operator. It need not be inline
162 // because if you're about to make a system call you can afford the
163 // cost of a function call.
164 template <class T>
165 std::ostream& operator<< (std::ostream&, vil_smart_ptr<T> const&);
166 
167 #define VIL_SMART_PTR_INSTANTIATE(T) \
168 extern "please include vil/vil_smart_ptr.hxx instead"
169 
170 #endif // vil_smart_ptr_h_
static void ref(T *p)
bool operator>=(vil_smart_ptr< T >const &p) const
vil_smart_ptr(T *p)
Definition: vil_smart_ptr.h:47
A templated smart pointer class.
Definition: vil_fwd.h:16
bool operator!() const
Inverse bool.
Definition: vil_smart_ptr.h:92
T & operator *() const
Dereferencing the pointer.
Definition: vil_smart_ptr.h:96
bool operator>(vil_smart_ptr< T >const &p) const
bool operator==(T const *p, vil_smart_ptr< T > const &a)
Comparison of pointer with smart-pointer (cannot be a member function).
T * operator ->() const
These methods all return the raw/dumb pointer.
Definition: vil_smart_ptr.h:99
vil_smart_ptr(vil_smart_ptr< T > const &p)
Definition: vil_smart_ptr.h:44
bool operator!=(T const *p) const
Do a shallow inequality.
bool operator==(vil_smart_ptr< T >const &p) const
Do a shallow equality.
bool operator!=(T const *p, vil_smart_ptr< T > const &a)
bool operator<(vil_smart_ptr< T >const &p) const
bool operator<=(vil_smart_ptr< T >const &p) const
std::ostream & operator<<(std::ostream &, vil_smart_ptr< T > const &)
bool operator!=(vil_smart_ptr< T >const &p) const
Do a shallow inequality.
T * as_pointer() const
These methods all return the raw/dumb pointer.
T * ptr_
Pointer to object, or 0.
vil_smart_ptr< T > & operator=(vil_smart_ptr< T > const &r)
Assignment.
Definition: vil_smart_ptr.h:61
bool operator==(T const *p) const
Do a shallow equality.
T * ptr() const
These methods all return the raw/dumb pointer.
static void unref(T *p)