RxDock 0.1.0
A fast, versatile, and open-source program for docking ligands to proteins and nucleic acids
Loading...
Searching...
No Matches
SmartPointer.h
1/***********************************************************************
2 * The rDock program was developed from 1998 - 2006 by the software team
3 * at RiboTargets (subsequently Vernalis (R&D) Ltd).
4 * In 2006, the software was licensed to the University of York for
5 * maintenance and distribution.
6 * In 2012, Vernalis and the University of York agreed to release the
7 * program as Open Source software.
8 * This version is licensed under GNU-LGPL version 3.0 with support from
9 * the University of Barcelona.
10 * http://rdock.sourceforge.net/
11 ***********************************************************************/
12
13// Smart pointer template which can handle normal class inheritance
14// relationships. Inspired by Omar Loggiodice's ookit SharedPtr and
15// David Harvey's "Smart pointer templates in C++" article
16//(http://web.ftech.net/~honeyg/articles/smartp.htm)
17//
18// We don't use a separate reference counting object, but rather store two
19// pointers in each smart pointer:
20// 1) Pointer to underlying object
21// 2) Pointer to unsigned int (reference counter)
22//
23// Pros: the only way I could think of to be able to implement assignment of
24// subclass smart pointer to base class smart pointer
25// Possibly faster access to underlying object (only one dereference
26// rather than two)
27// Cons: Less memory efficient (store two pointers per smart pointer, not one)
28//
29// To do: Should probably throw some other exception than std::exception if
30// assert fails
31// NOTE: it's a BAD idea to pass a nullptr pointer to the SmartPtr<T>
32// constructor
33
34#ifndef _RBTSMARTPOINTER_H_
35#define _RBTSMARTPOINTER_H_
36
37//#include "rxdock/Error.h"
38
39namespace rxdock {
40
41// Only check smart pointer assertions in debug build
42//#ifdef _NDEBUG
43// const Bool SMART_CHECK = false;
44//#else
45// const Bool SMART_CHECK = true;
46//#endif //_NDEBUG
47
48template <class T> class SmartPtr {
49public:
51 // CONSTRUCTORS, DESTRUCTORS, ASSIGNMENT
52
53 // Default constructor, initialise both pointers to 0
54 SmartPtr() : m_pT(nullptr), m_pCount(nullptr) {}
55
56 // Parameterised constructor
57 // Create new counter, initialise to 1
58 SmartPtr(T *pT) : m_pT(pT), m_pCount(new unsigned int(1)) {}
59
60 // Copy constructor - copy both pointers, increment counter
61 SmartPtr(const SmartPtr<T> &sp) : m_pT(sp.m_pT), m_pCount(sp.m_pCount) {
62 if (!Null())
63 GetRef();
64 }
65
66 // Copy constructor - template version for creating a base class smart pointer
67 // from a subclass smart pointer. Need to use public accessor methods for
68 // copying the pointers
69 template <class T2> SmartPtr(const SmartPtr<T2> &sp) {
70 m_pCount = sp.GetCountPtr();
71 T2 *pT2 = const_cast<T2 *>(sp.Ptr());
72 m_pT = dynamic_cast<T *>(pT2);
73 if (!Null())
74 GetRef();
75 }
76
77 // Destructor - decrement counter, delete underlying object
78 // if no refs remaining
79 ~SmartPtr() { UnBind(); }
80
81 // Assignment operator - check for self assignment
82 const SmartPtr<T> &operator=(const SmartPtr<T> &sp) {
83 if (this != &sp) {
84 UnBind();
85 m_pCount = sp.m_pCount;
86 m_pT = sp.m_pT;
87 if (!sp.Null())
88 sp.GetRef();
89 }
90 return *this;
91 }
92
93 // Assignment operator - template version for assigning a subclass smart
94 // pointer to a base class smart pointer. Will only compile if T2 is a
95 // subclass of T No need to worry about self assignment here so can unbind the
96 // existing ref first. Need to use public accessor methods to access the
97 // pointers on rhs
98 template <class T2> const SmartPtr<T> &operator=(const SmartPtr<T2> &sp) {
99 UnBind();
100 m_pCount = sp.GetCountPtr();
101 T2 *pT2 = const_cast<T2 *>(sp.Ptr());
102 m_pT = dynamic_cast<T *>(pT2);
103 if (!Null())
104 GetRef();
105 return *this;
106 }
107
109 // FRIEND FUNCTIONS - declaration
110 // operator== checks for equivalence of underlying pointers
111 // friend bool operator==(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs);
112
114 // PUBLIC ACCESSOR METHODS
115
116 // Tests if smart pointer is empty (i.e. does it have a counter?)
117 // Doesn't actually tell you if the underlying pointer is null
118 bool Null() const { return m_pCount == nullptr; }
119
120 // Returns pointer to counter
121 unsigned *GetCountPtr() const { return m_pCount; }
122
123 // Returns underlying pointer
124 T *Ptr() { return m_pT; }
125 const T *Ptr() const { return m_pT; }
126
127 // Manually remove reference to underlying object
128 void SetNull() { UnBind(); }
129
130 // Various means of dereferencing the underlying object
131 // Const and non-const versions
132 // Throw assert error if smart pointer is empty
133 T *operator->() {
134 // Assert<Assertion>(!SMART_CHECK||!Null());
135 return m_pT;
136 }
137 const T *operator->() const {
138 // Assert<Assertion>(!SMART_CHECK||!Null());
139 return m_pT;
140 }
141 T &operator*() {
142 // Assert<Assertion>(!SMART_CHECK||!Null());
143 return *m_pT;
144 }
145 const T &operator*() const {
146 // Assert<Assertion>(!SMART_CHECK||!Null());
147 return *m_pT;
148 }
149
150 // DM 12 Jun 2000 - yet another way to dereference the smart pointer
151 // Allows a smart pointer to be passed as a regular pointer in a function call
152 // for example.
153 operator T *() const { return m_pT; }
154
156 // PRIVATE METHODS AND DATA
157private:
158 // Increments counter and returns new value
159 unsigned GetRef() const { return ++(*m_pCount); }
160 // Decrements counter and returns new value
161 // ASSERT: counter should be non-zero before decrementing
162 unsigned FreeRef() const {
163 // Assert<Assertion>(!SMART_CHECK||(*m_pCount)!=0);
164 return --(*m_pCount);
165 }
166 // Decrements counter and deletes underlying object and counter
167 // if count is zero
168 void UnBind() {
169 if (!Null() && FreeRef() == 0) {
170 delete m_pT;
171 delete m_pCount;
172 }
173 m_pT = nullptr;
174 m_pCount = nullptr;
175 }
176
177 T *m_pT; // Pointer to the underlying object
178 unsigned *m_pCount; // Pointer to counter
179};
180
182// FRIEND FUNCTIONS - implementation
183// operator== checks for equivalence of underlying pointers
184// DM 22 May 2000 - use .Ptr() method so we don't have to declare as friend
185template <class T>
186bool operator==(const SmartPtr<T> &lhs, const SmartPtr<T> &rhs) {
187 return lhs.Ptr() == rhs.Ptr();
188}
189
190// operator!= checks for non-equivalence of underlying pointers
191template <class T>
192bool operator!=(const SmartPtr<T> &lhs, const SmartPtr<T> &rhs) {
193 return !(lhs == rhs);
194}
195
196// DM 13 Jul 2000 - operator< for sorting containers of smart pointers
197template <class T>
198bool operator<(const SmartPtr<T> &lhs, const SmartPtr<T> &rhs) {
199 return lhs.Ptr() < rhs.Ptr();
200}
201
202// DM 13 Jul 2000 - operator> for sorting containers of smart pointers
203template <class T>
204bool operator>(const SmartPtr<T> &lhs, const SmartPtr<T> &rhs) {
205 return lhs.Ptr() > rhs.Ptr();
206}
207
208} // namespace rxdock
209
210#endif //_RBTSMARTPOINTER_H_
Definition SmartPointer.h:48