IMP  2.0.1
The Integrative Modeling Platform
base/Pointer.h
Go to the documentation of this file.
1 /**
2  * \file IMP/base/Pointer.h
3  * \brief A nullptr-initialized pointer to an \imp Object.
4  *
5  * Copyright 2007-2013 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPBASE_POINTER_H
10 #define IMPBASE_POINTER_H
11 
12 #include <IMP/base/base_config.h>
13 #include "internal/PointerBase.h"
14 #include "WeakPointer.h"
15 
16 IMPBASE_BEGIN_NAMESPACE
17 
18 //! A reference counted pointer to an object.
19 /** Any time you store an Object in a C++ program, you should use a
20  Pointer, rather than a raw C++ pointer. Using a pointer manages
21  the reference counting and makes sure that the object is not deleted
22  prematurely when, for example, all Python references go away and that
23  it is deleted properly if an exception is thrown during the function.
24  Use the IMP_NEW() macro to aid creation of pointers to new objects.
25 
26  For example, when implementing a Restraint that uses a PairScore,
27  store the PairScore like this:
28  \code
29  Pointer<PairScore> ps_;
30  \endcode
31 
32  When creating Object instances in C++, you should write code like:
33  \code
34  em::FitRestraint* create_fit_restraint(std::string mapname,
35  const ParticlesTemp &ps) {
36  IMP_NEW(core::LeavesRefiner, lr, (atom::Hierarchy::get_traits()));
37  IMP::Pointer<em::DensityMap> map= em::read_map("file_name.mrc");
38  IMP_NEW(em::FitRestraint, fr, (ps, map, lr));
39  return fr.release();
40  }
41  \endcode
42  which is equivalent to
43  \code
44  IMP::em::FitRestraint* create_fit_restraint(std::string mapname,
45  const ParticlesTemp &ps) {
46  Pointer<core::LeavesRefiner> lr
47  = new core::LeavesRefiner(atom::Hierarchy::get_traits());
48  IMP::Pointer<IMP::em::DensityMap> map
49  = em::read_map("file_name.mrc");
50  Pointer<em::FitRestraint> fr= new em::FitRestraint(ps, map, lr));
51  return fr.release();
52  }
53  \endcode
54  There are several important things to note in this code:
55  - the use of Pointer::release() on the return. Otherwise, when the
56  reference counted pointer goes out of scope, it will unref the
57  em::FitRestraint, notice the count is 0, and delete it, before
58  passing the (now invalid) pointer back to the calling function
59  - the use of reference counted pointers everywhere. This ensures that
60  if, for example, em::read_map() throws an exception since the
61  file name is invalid, the core::LeavesRefiner will be deleted
62  properly.
63 
64  \note Do not pass Pointers as arguments to functions, pass raw C++
65  pointers instead.
66 
67  \note Use an IMP::WeakPointer to break cycles or to point to
68  non-ref-counted objects.
69 
70  \param[in] O The type of IMP::RefCounted-derived object to point to
71 */
72 template <class O>
73 struct Pointer: internal::PointerBase<internal::RefCountedPointerTraits<O> > {
74  typedef internal::PointerBase<internal::RefCountedPointerTraits<O> > P;
75  template <class Any>
76  Pointer(const Any &o): P(o){}
77  Pointer(){}
78  template <class OT>
79  Pointer<O>& operator=( const internal::PointerBase<OT> &o){
80  P::operator=(o);
81  return *this;
82  }
83  template <class OT>
84  Pointer<O>& operator=( OT* o){
85  P::operator=(o);
86  return *this;
87  }
88 #if !IMP_COMPILER_HAS_NULLPTR
89  Pointer<O>& operator=(nullptr_t o) {
90  P::operator=(o);
91  return *this;
92  }
93 #endif
94  Pointer<O>& operator=(const P &o) {
95  P::operator=(o);
96  return *this;
97  }
98 };
99 
100 //! A reference counted pointer to an Object.
101 /** The object being pointed to must inherit from IMP::base::Object.
102  In addition to reference counting the object like Pointer,
103  Object::set_was_used(true) will be called so you don't get
104  warnings about unused objects.
105 
106  \param[in] O The type of IMP::RefCounted-derived object to point to
107  */
108 template <class O>
109 struct OwnerPointer: internal::PointerBase<internal::OwnerPointerTraits<O> > {
110  typedef internal::PointerBase<internal::OwnerPointerTraits<O> > P;
111  template <class Any>
112  OwnerPointer(const Any &o): P(o){}
113  OwnerPointer(){}
114  template <class OT>
115  OwnerPointer<O>& operator=( const internal::PointerBase<OT> &o){
116  P::operator=(o);
117  return *this;
118  }
119  template <class OT>
120  OwnerPointer<O>& operator=( OT* o){
121  P::operator=(o);
122  return *this;
123  }
124 #if !IMP_COMPILER_HAS_NULLPTR
125  OwnerPointer<O>& operator=(nullptr_t o) {
126  P::operator=(o);
127  return *this;
128  }
129 #endif
130  OwnerPointer<O>& operator=(const P &o) {
131  P::operator=(o);
132  return *this;
133  }
134 };
135 
136 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
137 template <class T>
138 inline std::ostream &operator<<(std::ostream &out, Pointer<T> o) {
139  out << Showable(o.get());
140  return out;
141 }
142 template <class T>
143 inline std::ostream &operator<<(std::ostream &out, OwnerPointer<T> o) {
144  out << Showable(o.get());
145  return out;
146 }
147 #endif
148 
149 IMPBASE_END_NAMESPACE
150 
151 #endif /* IMPBASE_POINTER_H */