Panda3D
pointerTo.h
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pointerTo.h
10  * @author drose
11  * @date 1998-10-23
12  */
13 
14 #ifndef POINTERTO_H
15 #define POINTERTO_H
16 
17 /**
18  * This file defines the classes PointerTo and ConstPointerTo (and their
19  * abbreviations, PT and CPT). These should be used in place of traditional
20  * C-style pointers wherever implicit reference counting is desired.
21  *
22  * The syntax is: instead of:
23  *
24  * PointerTo<MyClass> p; MyClass *p;
25  * PT(MyClass) p;
26  *
27  * ConstPointerTo<MyClass> p; const MyClass *p;
28  * CPT(MyClass) p;
29  *
30  * PointerTo and ConstPointerTo will automatically increment the object's
31  * reference count while the pointer is kept. When the PointerTo object is
32  * reassigned or goes out of scope, the reference count is automatically
33  * decremented. If the reference count reaches zero, the object is freed.
34  *
35  * Note that const PointerTo<MyClass> is different from
36  * ConstPointerTo<MyClass>. A const PointerTo may not reassign its pointer,
37  * but it may still modify the contents at that address. On the other hand, a
38  * ConstPointerTo may reassign its pointer at will, but may not modify the
39  * contents. It is like the difference between (MyClass * const) and
40  * (const MyClass *).
41  *
42  * In order to use PointerTo, it is necessary that the thing pointed to
43  * --MyClass in the above example--either inherits from ReferenceCount, or is
44  * a proxy built with RefCountProxy or RefCountObj (see referenceCount.h).
45  * However, also see PointerToArray, which does not have this restriction.
46  *
47  * It is crucial that the PointerTo object is only used to refer to objects
48  * allocated from the free store, for which delete is a sensible thing to do.
49  * If you assign a PointerTo to an automatic variable (allocated from the
50  * stack, for instance), bad things will certainly happen when the reference
51  * count reaches zero and it tries to delete it.
52  *
53  * It's also important to remember that, as always, a virtual destructor is
54  * required if you plan to support polymorphism. That is, if you define a
55  * PointerTo to some base type, and assign to it instances of a class derived
56  * from that base class, the base class must have a virtual destructor in
57  * order to properly destruct the derived object when it is deleted.
58  */
59 
60 #include "pandabase.h"
61 #include "pointerToBase.h"
62 #include "register_type.h"
63 
64 /**
65  * PointerTo is a template class which implements a smart pointer to an object
66  * derived from ReferenceCount.
67  */
68 template <class T>
69 class PointerTo : public PointerToBase<T> {
70 public:
71  typedef typename PointerToBase<T>::To To;
72 PUBLISHED:
73  ALWAYS_INLINE constexpr PointerTo() noexcept = default;
74  ALWAYS_INLINE explicit constexpr PointerTo(std::nullptr_t) noexcept {}
75  ALWAYS_INLINE PointerTo(To *ptr) noexcept;
76  INLINE PointerTo(const PointerTo<T> &copy);
77 
78 public:
79  INLINE PointerTo(PointerTo<T> &&from) noexcept;
80 
81  template<class Y>
82  ALWAYS_INLINE explicit PointerTo(Y *ptr) noexcept;
83  template<class Y>
84  ALWAYS_INLINE PointerTo(const PointerTo<Y> &r) noexcept;
85  template<class Y>
86  ALWAYS_INLINE PointerTo(PointerTo<Y> &&r) noexcept;
87 
88  INLINE PointerTo<T> &operator = (PointerTo<T> &&from) noexcept;
89 
90  template<class Y>
91  ALWAYS_INLINE PointerTo<T> &operator = (const PointerTo<Y> &r) noexcept;
92  template<class Y>
93  ALWAYS_INLINE PointerTo<T> &operator = (PointerTo<Y> &&r) noexcept;
94 
95  constexpr To &operator *() const noexcept;
96  constexpr To *operator -> () const noexcept;
97  // MSVC.NET 2005 insists that we use T *, and not To *, here.
98  constexpr operator T *() const noexcept;
99 
100  INLINE T *&cheat();
101 
102 PUBLISHED:
103  // When downcasting to a derived class from a PointerTo<BaseClass>, C++
104  // would normally require you to cast twice: once to an actual BaseClass
105  // pointer, and then again to your desired pointer. You can use the handy
106  // function p() to avoid this first cast and make your code look a bit
107  // cleaner.
108 
109  // e.g. instead of (MyType *)(BaseClass *)ptr, use (MyType *)ptr.p()
110 
111  // If your base class is a derivative of TypedObject, you might want to use
112  // the DCAST macro defined in typedObject.h instead, e.g. DCAST(MyType,
113  // ptr). This provides a clean downcast that doesn't require .p() or any
114  // double-casting, and it can be run-time checked for correctness.
115  constexpr To *p() const noexcept;
116 
117  INLINE PointerTo<T> &operator = (To *ptr);
118  INLINE PointerTo<T> &operator = (const PointerTo<T> &copy);
119 
120  // These functions normally wouldn't need to be redefined here, but we do so
121  // anyway just to help out interrogate (which doesn't seem to want to
122  // automatically export the PointerToBase class). When this works again in
123  // interrogate, we can remove these.
124 #ifdef CPPPARSER
125  INLINE bool is_null() const;
126  INLINE void clear();
127 #endif
128 };
129 
130 
131 /**
132  * A ConstPointerTo is similar to a PointerTo, except it keeps a const pointer
133  * to the thing.
134  *
135  * (Actually, it keeps a non-const pointer, because it must be allowed to
136  * adjust the reference counts, and it must be able to delete it when the
137  * reference count goes to zero. But it presents only a const pointer to the
138  * outside world.)
139  *
140  * Notice that a PointerTo may be assigned to a ConstPointerTo, but a
141  * ConstPointerTo may not be assigned to a PointerTo.
142  */
143 template <class T>
144 class ConstPointerTo : public PointerToBase<T> {
145 public:
146  typedef typename PointerToBase<T>::To To;
147 PUBLISHED:
148  ALWAYS_INLINE constexpr ConstPointerTo() noexcept = default;
149  ALWAYS_INLINE explicit constexpr ConstPointerTo(std::nullptr_t) noexcept {}
150  ALWAYS_INLINE ConstPointerTo(const To *ptr) noexcept;
151  INLINE ConstPointerTo(const PointerTo<T> &copy);
152  INLINE ConstPointerTo(const ConstPointerTo<T> &copy);
153 
154 public:
155  INLINE ConstPointerTo(PointerTo<T> &&from) noexcept;
156  INLINE ConstPointerTo(ConstPointerTo<T> &&from) noexcept;
157 
158  template<class Y>
159  ALWAYS_INLINE explicit ConstPointerTo(const Y *ptr) noexcept;
160  template<class Y>
161  ALWAYS_INLINE ConstPointerTo(const PointerTo<Y> &r) noexcept;
162  template<class Y>
163  ALWAYS_INLINE ConstPointerTo(const ConstPointerTo<Y> &r) noexcept;
164  template<class Y>
165  ALWAYS_INLINE ConstPointerTo(PointerTo<Y> &&r) noexcept;
166  template<class Y>
167  ALWAYS_INLINE ConstPointerTo(ConstPointerTo<Y> &&r) noexcept;
168 
169  INLINE ConstPointerTo<T> &operator = (PointerTo<T> &&from) noexcept;
170  INLINE ConstPointerTo<T> &operator = (ConstPointerTo<T> &&from) noexcept;
171 
172  template<class Y>
173  ALWAYS_INLINE ConstPointerTo<T> &operator = (const PointerTo<Y> &r) noexcept;
174  template<class Y>
175  ALWAYS_INLINE ConstPointerTo<T> &operator = (const ConstPointerTo<Y> &r) noexcept;
176  template<class Y>
177  ALWAYS_INLINE ConstPointerTo<T> &operator = (PointerTo<Y> &&r) noexcept;
178  template<class Y>
179  ALWAYS_INLINE ConstPointerTo<T> &operator = (ConstPointerTo<Y> &&r) noexcept;
180 
181  constexpr const To &operator *() const noexcept;
182  constexpr const To *operator -> () const noexcept;
183  constexpr operator const T *() const noexcept;
184 
185  INLINE const T *&cheat();
186 
187 PUBLISHED:
188  constexpr const To *p() const noexcept;
189 
190  INLINE ConstPointerTo<T> &operator = (const To *ptr);
191  INLINE ConstPointerTo<T> &operator = (const PointerTo<T> &copy);
192  INLINE ConstPointerTo<T> &operator = (const ConstPointerTo<T> &copy);
193 
194  // This functions normally wouldn't need to be redefined here, but we do so
195  // anyway just to help out interrogate (which doesn't seem to want to
196  // automatically export the PointerToBase class). When this works again in
197  // interrogate, we can remove this.
198 #ifdef CPPPARSER
199  INLINE void clear();
200 #endif
201 };
202 
203 
204 // The existence of these functions makes it possible to sort vectors of
205 // PointerTo objects without incurring the cost of unnecessary reference count
206 // changes. The performance difference is dramatic!
207 template <class T>
208 void swap(PointerTo<T> &one, PointerTo<T> &two) noexcept {
209  one.swap(two);
210 }
211 
212 template <class T>
213 void swap(ConstPointerTo<T> &one, ConstPointerTo<T> &two) noexcept {
214  one.swap(two);
215 }
216 
217 
218 // Define owner_less specializations, for completeness' sake.
219 namespace std {
220  template<class T>
221  struct owner_less<PointerTo<T> > {
222  bool operator () (const PointerTo<T> &lhs,
223  const PointerTo<T> &rhs) const noexcept {
224  return lhs < rhs;
225  }
226  };
227 
228  template<class T>
229  struct owner_less<ConstPointerTo<T> > {
230  bool operator () (const ConstPointerTo<T> &lhs,
231  const ConstPointerTo<T> &rhs) const noexcept {
232  return lhs < rhs;
233  }
234  };
235 }
236 
237 
238 // Finally, we'll define a couple of handy abbreviations to save on all that
239 // wasted typing time.
240 
241 #define PT(type) PointerTo< type >
242 #define CPT(type) ConstPointerTo< type >
243 
244 // Now that we have defined PointerTo, we can define what it means to take the
245 // TypeHandle of a PointerTo object.
246 
247 template<class T>
248 INLINE TypeHandle _get_type_handle(const PointerTo<T> *) {
249  return T::get_class_type();
250 }
251 
252 template<class T>
253 INLINE TypeHandle _get_type_handle(const ConstPointerTo<T> *) {
254  return T::get_class_type();
255 }
256 
257 
258 #include "pointerTo.I"
259 
260 #endif
void clear()
A convenient way to set the PointerTo object to NULL.
constexpr To * p() const noexcept
Returns an ordinary pointer instead of a PointerTo.
Definition: pointerTo.I:160
const T *& cheat()
Returns a reference to the underlying pointer.
Definition: pointerTo.I:396
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
constexpr bool is_null() const
Returns true if the PointerTo is a NULL pointer, false otherwise.
Definition: pointerToVoid.I:27
This is the base class for PointerTo and ConstPointerTo.
Definition: pointerToBase.h:29
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
constexpr const To * p() const noexcept
Returns an ordinary pointer instead of a ConstPointerTo.
Definition: pointerTo.I:406
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A ConstPointerTo is similar to a PointerTo, except it keeps a const pointer to the thing.
Definition: pointerTo.h:144
This file defines the classes PointerTo and ConstPointerTo (and their abbreviations,...
Definition: pointerTo.h:69
T *& cheat()
Returns a reference to the underlying pointer.
Definition: pointerTo.I:150
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.