exempt_ptr.h
Go to the documentation of this file.
1 #ifndef cetlib_exempt_ptr_h
2 #define cetlib_exempt_ptr_h
3 
4 // ======================================================================
5 //
6 // exempt_ptr: A pointer taking no notice of its pointee's lifetime
7 // (thus exempt from any role in managing same, and thus
8 // copyable with no impact on its pointee)
9 //
10 // ----------------------------------------------------------------------
11 //
12 // This (not very) smart pointer template is intended as a replacement
13 // for bare/native/raw/built-in C++ pointers, especially when used to
14 // communicate with (say) legacy code that traffics in such pointers.
15 //
16 // Having such a template provides a standard vocabulary to denote
17 // non-owning pointers, with no need for further comment or other
18 // documentation to describe the semantics involved.
19 //
20 // As a small bonus, this template's c'tors ensure that all instance
21 // variables are initialized.
22 //
23 // ----------------------------------------------------------------------
24 //
25 // Questions:
26 // - We have operators ==, !=, < ; should <= > >= be supported?
27 // - With which, if any, other smart pointers should this template
28 // innately interoperate, and to what degree?
29 //
30 // ======================================================================
31 
32 #include <cstddef>
33 #include <exception>
34 #include <functional>
35 #include <type_traits>
36 #include <utility>
37 
38 namespace cet {
39 
40  template <class Element>
41  class exempt_ptr;
42 
43  template <class E>
44  void swap(exempt_ptr<E>&, exempt_ptr<E>&) noexcept;
45 
46  template <class E>
47  exempt_ptr<E> make_exempt_ptr(E*) noexcept;
48 
49  template <class E>
50  bool operator==(exempt_ptr<E> const&, exempt_ptr<E> const&);
51 
52  template <class E>
53  bool operator!=(exempt_ptr<E> const&, exempt_ptr<E> const&);
54 
55  template <class E>
56  bool operator==(exempt_ptr<E> const&, std::nullptr_t const&);
57 
58  template <class E>
59  bool operator!=(exempt_ptr<E> const&, std::nullptr_t const&);
60 
61  template <class E>
62  bool operator==(std::nullptr_t const&, exempt_ptr<E> const&);
63 
64  template <class E>
65  bool operator!=(std::nullptr_t const&, exempt_ptr<E> const&);
66 
67  template <class E>
68  bool operator<(exempt_ptr<E> const&, exempt_ptr<E> const&);
69 
70  template <class E>
71  bool operator>(exempt_ptr<E> const&, exempt_ptr<E> const&);
72 
73  template <class E>
74  bool operator<=(exempt_ptr<E> const&, exempt_ptr<E> const&);
75 
76  template <class E>
77  bool operator>=(exempt_ptr<E> const&, exempt_ptr<E> const&);
78 }
79 
80 // ======================================================================
81 
82 template <class Element>
83 class cet::exempt_ptr {
84 public:
85  // --- publish our template parameter and variations thereof:
86  using element_type = Element;
87  using pointer = std::add_pointer_t<Element>;
88  using reference = std::add_lvalue_reference_t<Element>;
89 
90 private:
91  template <class P>
93  : public std::is_convertible<std::add_pointer_t<P>, pointer> {};
94 
95 public:
96  // --- default c'tor:
97  constexpr exempt_ptr() noexcept : p{nullptr} {}
98 
99  // pointer-accepting c'tors:
100  constexpr exempt_ptr(std::nullptr_t) noexcept : p{nullptr} {}
101  explicit exempt_ptr(pointer other) noexcept : p{other} {}
102 
103  template <class E2>
105  std::enable_if_t<is_compatible<E2>::value>* = nullptr) noexcept
106  : p{other}
107  {}
108 
109  // copying c'tors:
110  // use compiler-generated copy c'tor
111  template <class E2>
113  std::enable_if_t<is_compatible<E2>::value>* = nullptr) noexcept
114  : p{other.get()}
115  {}
116 
117  // pointer-accepting assignments:
118  exempt_ptr& operator=(std::nullptr_t) noexcept
119  {
120  reset(nullptr);
121  return *this;
122  }
123 
124  template <class E2>
126  operator=(E2* other) noexcept
127  {
128  reset(other);
129  return *this;
130  }
131 
132  // copying assignments:
133  // use compiler-generated copy assignment
134  template <class E2>
136  operator=(exempt_ptr<E2> const& other) noexcept
137  {
138  reset(other.get());
139  return *this;
140  }
141 
142  // observers:
143  reference operator*() const noexcept { return *get(); }
144  pointer operator->() const noexcept { return get(); }
145  pointer
146  get() const noexcept
147  {
148  return p;
149  }
150  bool
151  empty() const noexcept
152  {
153  return get() == nullptr;
154  }
155  explicit operator bool() const noexcept { return !empty(); }
156 
157  // modifiers:
158  pointer
159  release() noexcept
160  {
161  pointer old = get();
162  reset();
163  return old;
164  }
165  void
166  reset(pointer t = nullptr) noexcept
167  {
168  p = t;
169  }
170  void
171  swap(exempt_ptr& other) noexcept
172  {
173  std::swap(p, other.p);
174  }
175 
176 private:
178 
179 }; // exempt_ptr<>
180 
181 // ======================================================================
182 // non-member functions:
183 
184 // ----------------------------------------------------------------------
185 // non-member swap:
186 
187 template <class E>
188 inline void
190 {
191  x.swap(y);
192 }
193 
194 // ----------------------------------------------------------------------
195 // non-member make_exempt_ptr:
196 
197 template <class E>
199 cet::make_exempt_ptr(E* p) noexcept
200 {
201  return exempt_ptr<E>(p);
202 }
203 
204 // ----------------------------------------------------------------------
205 // non-member (in)equality comparison:
206 
207 template <class E>
208 bool
210 {
211  return x.get() == y.get();
212 }
213 
214 template <class E>
215 bool
217 {
218  return !operator==(x, y);
219 }
220 
221 template <class E>
222 bool
223 cet::operator==(exempt_ptr<E> const& x, std::nullptr_t const& y)
224 {
225  return x.get() == y;
226 }
227 
228 template <class E>
229 bool
230 cet::operator!=(exempt_ptr<E> const& x, std::nullptr_t const& y)
231 {
232  return !operator==(x, y);
233 }
234 
235 template <class E>
236 bool
237 cet::operator==(std::nullptr_t const& x, exempt_ptr<E> const& y)
238 {
239  return x == y.get();
240 }
241 
242 template <class E>
243 bool
244 cet::operator!=(std::nullptr_t const& x, exempt_ptr<E> const& y)
245 {
246  return !operator==(x, y);
247 }
248 
249 // ----------------------------------------------------------------------
250 // non-member ordering:
251 
252 template <class E>
253 bool
254 cet::operator<(cet::exempt_ptr<E> const& x, cet::exempt_ptr<E> const& y)
255 {
256  using CT = std::common_type_t<typename exempt_ptr<E>::pointer,
257  typename exempt_ptr<E>::pointer>;
258  return std::less<CT>{}(x.get(), y.get());
259 }
260 
261 template <class E>
262 bool
264 {
265  return y < x;
266 }
267 
268 template <class E>
269 bool
270 cet::operator<=(cet::exempt_ptr<E> const& x, cet::exempt_ptr<E> const& y)
271 {
272  return !(y < x);
273 }
274 
275 template <class E>
276 bool
278 {
279  return !(x < y);
280 }
281 
282 // ======================================================================
283 
284 #endif /* cetlib_exempt_ptr_h */
285 
286 // Local Variables:
287 // mode: c++
288 // End:
pointer release() noexcept
Definition: exempt_ptr.h:159
const char * p
Definition: xmltok.h:285
bool operator!=(exempt_ptr< E > const &, exempt_ptr< E > const &)
Definition: exempt_ptr.h:216
pointer get() const noexcept
Definition: exempt_ptr.h:146
bool empty() const noexcept
Definition: exempt_ptr.h:151
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
std::add_pointer_t< art::RunPrincipal > pointer
Definition: exempt_ptr.h:87
exempt_ptr & operator=(std::nullptr_t) noexcept
Definition: exempt_ptr.h:118
const XML_Char int const XML_Char * value
Definition: expat.h:331
exempt_ptr(pointer other) noexcept
Definition: exempt_ptr.h:101
Float_t E
Definition: plot.C:20
exempt_ptr< E > make_exempt_ptr(E *) noexcept
reference operator*() const noexcept
Definition: exempt_ptr.h:143
constexpr exempt_ptr(std::nullptr_t) noexcept
Definition: exempt_ptr.h:100
std::enable_if_t< is_compatible< E2 >::value, exempt_ptr & > operator=(E2 *other) noexcept
Definition: exempt_ptr.h:126
void reset(pointer t=nullptr) noexcept
Definition: exempt_ptr.h:166
bool operator>(exempt_ptr< E > const &, exempt_ptr< E > const &)
Definition: exempt_ptr.h:263
void swap(exempt_ptr< E > &, exempt_ptr< E > &) noexcept
Definition: exempt_ptr.h:189
bool operator==(exempt_ptr< E > const &, exempt_ptr< E > const &)
Definition: exempt_ptr.h:209
std::enable_if_t< is_compatible< E2 >::value, exempt_ptr & > operator=(exempt_ptr< E2 > const &other) noexcept
Definition: exempt_ptr.h:136
bool operator>=(exempt_ptr< E > const &, exempt_ptr< E > const &)
Definition: exempt_ptr.h:277
std::add_lvalue_reference_t< art::RunPrincipal > reference
Definition: exempt_ptr.h:88
void swap(exempt_ptr &other) noexcept
Definition: exempt_ptr.h:171
exempt_ptr(exempt_ptr< E2 > const &other, std::enable_if_t< is_compatible< E2 >::value > *=nullptr) noexcept
Definition: exempt_ptr.h:112
pointer operator->() const noexcept
Definition: exempt_ptr.h:144
exempt_ptr(E2 *other, std::enable_if_t< is_compatible< E2 >::value > *=nullptr) noexcept
Definition: exempt_ptr.h:104
constexpr exempt_ptr() noexcept
Definition: exempt_ptr.h:97