maybe_ref.h
Go to the documentation of this file.
1 #ifndef cetlib_maybe_ref_h
2 #define cetlib_maybe_ref_h
3 
4 // ======================================================================
5 //
6 // maybe_ref<>: Reference-like types that may refer to nothing
7 //
8 // A maybe_ref<> object has the following members of special interest:
9 // - isValid() : does it have a referent?
10 // - ref() : produce a C++ reference to its referent (iff it is valid)
11 //
12 // When valid, a maybe_ref<> object mimics a C++ reference in that it
13 // takes no ownership of its referent, thus is unaware of the referent's
14 // lifetime. Therefore it is the user's responsibility to keep the
15 // referent alive so long as there is a valid maybe_ref<> to it.
16 //
17 // Unlike a C++ reference, a maybe_ref<> object can be reseated (made to
18 // refer to a different referent).
19 //
20 // When invalid, a maybe_ref<> object throws if asked to produce a C++
21 // reference.
22 //
23 // One typical usage pattern:
24 // cet::maybe_ref<T const> m( call some accessor );
25 // if ( !m ) return; // or continue
26 // T const & r( m.ref() );
27 //
28 // ======================================================================
29 
30 #include <ostream>
31 #include <stdexcept>
32 
33 namespace cet {
34  template <class T>
35  class maybe_ref;
36 
37  template <class T>
39 
40  template <class T>
41  bool operator==(maybe_ref<T> const& left, maybe_ref<T> const& right);
42 
43  template <class T>
44  std::ostream& operator<<(std::ostream& os, maybe_ref<T> const& item);
45 }
46 
47 // ======================================================================
48 
49 template <class T>
50 class cet::maybe_ref {
51 public:
52  typedef T value_type;
53 
54  maybe_ref() : ptr_(0) {}
55  explicit maybe_ref(T& t) : ptr_(&t) {}
56 
57  // use compiler-generated copy c'tor, copy assignment, and d'tor
58 
59  bool
60  isValid() const
61  {
62  return ptr_;
63  }
64  explicit operator bool() const { return isValid(); }
65 
66  void
68  {
69  ptr_ = 0;
70  }
71  void
73  {
74  ptr_ = &p;
75  }
76 
77  T&
78  ref()
79  {
80  return ref_iff_valid();
81  }
82  T const&
83  ref() const
84  {
85  return ref_iff_valid();
86  }
87 
88  void
90  {
91  std::swap(ptr_, other.ptr_);
92  }
93 
94 private:
95  T* ptr_;
96 
97  T&
98  ref_iff_valid() const
99  {
100  if (isValid())
101  return *ptr_;
102 
103  // TODO: consider throwing a cet::exception
104  throw std::logic_error("cet::maybe_ref<>: referent does not exist");
105  }
106 
107 }; // maybe_ref<>
108 
109 // ======================================================================
110 
111 template <class T>
112 inline void
114 {
115  r1.swap(r2);
116 }
117 
118 template <class T>
119 inline bool
121 {
122  return (&left.ref()) == (&right.ref());
123 }
124 
125 template <class T>
126 inline std::ostream&
127 cet::operator<<(std::ostream& os, maybe_ref<T> const& item)
128 {
129  os << &item.ref();
130  return os;
131 }
132 
133 // ======================================================================
134 
135 #endif /* cetlib_maybe_ref_h */
136 
137 // Local Variables:
138 // mode: c++
139 // End:
void swap(maybe_ref &other)
Definition: maybe_ref.h:89
maybe_ref(T &t)
Definition: maybe_ref.h:55
bool isValid() const
Definition: maybe_ref.h:60
T & ref_iff_valid() const
Definition: maybe_ref.h:98
T const & ref() const
Definition: maybe_ref.h:83
p
Definition: test.py:223
constexpr bool operator==(exempt_ptr< E >, exempt_ptr< E >) noexcept
Definition: exempt_ptr.h:211
void swap(exempt_ptr< E > &, exempt_ptr< E > &) noexcept
Definition: exempt_ptr.h:191
void reseat(T &p)
Definition: maybe_ref.h:72
void swap(maybe_ref< T > &, maybe_ref< T > &)
Definition: maybe_ref.h:113
int bool
Definition: qglobal.h:345
void reseat()
Definition: maybe_ref.h:67