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 <functional>
34 
35 namespace cet {
36 
37  template <class Element>
38  class exempt_ptr;
39 
40  template <class E>
41  void swap(exempt_ptr<E>&, exempt_ptr<E>&) noexcept;
42 
43  template <class E>
44  constexpr exempt_ptr<E> make_exempt_ptr(E*) noexcept;
45 
46  template <class E>
47  constexpr bool operator==(exempt_ptr<E>, exempt_ptr<E>) noexcept;
48 
49  template <class E>
50  constexpr bool operator!=(exempt_ptr<E>, exempt_ptr<E>) noexcept;
51 
52  template <class E>
53  constexpr bool operator==(exempt_ptr<E>, std::nullptr_t) noexcept;
54 
55  template <class E>
56  constexpr bool operator!=(exempt_ptr<E>, std::nullptr_t) noexcept;
57 
58  template <class E>
59  constexpr bool operator==(std::nullptr_t, exempt_ptr<E>) noexcept;
60 
61  template <class E>
62  constexpr bool operator!=(std::nullptr_t, exempt_ptr<E>) noexcept;
63 
64  template <class E>
65  constexpr bool operator<(exempt_ptr<E>, exempt_ptr<E>);
66 
67  template <class E>
68  constexpr bool operator>(exempt_ptr<E>, exempt_ptr<E>);
69 
70  template <class E>
71  constexpr bool operator<=(exempt_ptr<E>, exempt_ptr<E>);
72 
73  template <class E>
74  constexpr bool operator>=(exempt_ptr<E>, exempt_ptr<E>);
75 }
76 
77 // ======================================================================
78 
79 template <class Element>
80 class cet::exempt_ptr {
81 public:
82  // --- publish our template parameter and variations thereof:
83  using element_type = Element;
84  using pointer = std::add_pointer_t<Element>;
85  using reference = std::add_lvalue_reference_t<Element>;
86 
87 private:
88  template <class P>
90  : public std::is_convertible<std::add_pointer_t<P>, pointer> {};
91 
92  template <class P>
93  static constexpr bool is_compatible_v = is_compatible<P>::value;
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  constexpr explicit exempt_ptr(pointer other) noexcept : p{other} {}
102 
103  template <class E2>
104  constexpr exempt_ptr(
105  E2* other,
106  std::enable_if_t<is_compatible_v<E2>>* = nullptr) noexcept
107  : p{other}
108  {}
109 
110  // copying c'tors:
111  // use compiler-generated copy c'tor
112  template <class E2>
113  constexpr exempt_ptr(
114  exempt_ptr<E2> const other,
115  std::enable_if_t<is_compatible_v<E2>>* = nullptr) noexcept
116  : p{other.get()}
117  {}
118 
119  // pointer-accepting assignments:
120  constexpr exempt_ptr& operator=(std::nullptr_t) noexcept
121  {
122  reset(nullptr);
123  return *this;
124  }
125 
126  template <class E2>
127  constexpr std::enable_if_t<is_compatible_v<E2>, exempt_ptr&>
128  operator=(E2* other) noexcept
129  {
130  reset(other);
131  return *this;
132  }
133 
134  // copying assignments:
135  // use compiler-generated copy assignment
136  template <class E2>
137  constexpr std::enable_if_t<is_compatible_v<E2>, exempt_ptr&>
139  {
140  reset(other.get());
141  return *this;
142  }
143 
144  // observers:
145  constexpr reference operator*() const noexcept { return *get(); }
146  constexpr pointer operator->() const noexcept { return get(); }
147  constexpr pointer
148  get() const noexcept
149  {
150  return p;
151  }
152  constexpr bool
153  empty() const noexcept
154  {
155  return get() == nullptr;
156  }
157  constexpr explicit operator bool() const noexcept { return !empty(); }
158 
159  // modifiers:
160  constexpr pointer
161  release() noexcept
162  {
163  pointer old = get();
164  reset();
165  return old;
166  }
167  constexpr void
168  reset(pointer t = nullptr) noexcept
169  {
170  p = t;
171  }
172  void
173  swap(exempt_ptr& other) noexcept
174  {
175  std::swap(p, other.p);
176  }
177 
178 private:
180 
181 }; // exempt_ptr<>
182 
183 // ======================================================================
184 // non-member functions:
185 
186 // ----------------------------------------------------------------------
187 // non-member swap:
188 
189 template <class E>
190 inline void
192 {
193  x.swap(y);
194 }
195 
196 // ----------------------------------------------------------------------
197 // non-member make_exempt_ptr:
198 
199 template <class E>
200 constexpr cet::exempt_ptr<E>
201 cet::make_exempt_ptr(E* p) noexcept
202 {
203  return exempt_ptr<E>{p};
204 }
205 
206 // ----------------------------------------------------------------------
207 // non-member (in)equality comparison:
208 
209 template <class E>
210 constexpr bool
212 {
213  return x.get() == y.get();
214 }
215 
216 template <class E>
217 constexpr bool
219 {
220  return !operator==(x, y);
221 }
222 
223 template <class E>
224 constexpr bool
225 cet::operator==(exempt_ptr<E> const x, std::nullptr_t const y) noexcept
226 {
227  return x.get() == y;
228 }
229 
230 template <class E>
231 constexpr bool
232 cet::operator!=(exempt_ptr<E> const x, std::nullptr_t const y) noexcept
233 {
234  return !operator==(x, y);
235 }
236 
237 template <class E>
238 constexpr bool
239 cet::operator==(std::nullptr_t const x, exempt_ptr<E> const y) noexcept
240 {
241  return x == y.get();
242 }
243 
244 template <class E>
245 constexpr bool
246 cet::operator!=(std::nullptr_t const x, exempt_ptr<E> const y) noexcept
247 {
248  return !operator==(x, y);
249 }
250 
251 // ----------------------------------------------------------------------
252 // non-member ordering:
253 
254 template <class E>
255 constexpr bool
256 cet::operator<(cet::exempt_ptr<E> const x, cet::exempt_ptr<E> const y)
257 {
258  using CT = std::common_type_t<typename exempt_ptr<E>::pointer,
259  typename exempt_ptr<E>::pointer>;
260  return std::less<CT>{}(x.get(), y.get());
261 }
262 
263 template <class E>
264 constexpr bool
266 {
267  return y < x;
268 }
269 
270 template <class E>
271 constexpr bool
272 cet::operator<=(cet::exempt_ptr<E> const x, cet::exempt_ptr<E> const y)
273 {
274  return !(y < x);
275 }
276 
277 template <class E>
278 constexpr bool
280 {
281  return !(x < y);
282 }
283 
284 // ======================================================================
285 
286 #endif /* cetlib_exempt_ptr_h */
287 
288 // Local Variables:
289 // mode: c++
290 // End:
constexpr exempt_ptr(exempt_ptr< E2 > const other, std::enable_if_t< is_compatible_v< E2 >> *=nullptr) noexcept
Definition: exempt_ptr.h:113
constexpr pointer operator->() const noexcept
Definition: exempt_ptr.h:146
constexpr bool operator>=(exempt_ptr< E >, exempt_ptr< E >)
Definition: exempt_ptr.h:279
constexpr pointer release() noexcept
Definition: exempt_ptr.h:161
STL namespace.
constexpr pointer get() const noexcept
Definition: exempt_ptr.h:148
constexpr void reset(pointer t=nullptr) noexcept
Definition: exempt_ptr.h:168
constexpr bool empty() const noexcept
Definition: exempt_ptr.h:153
constexpr reference operator*() const noexcept
Definition: exempt_ptr.h:145
constexpr exempt_ptr(E2 *other, std::enable_if_t< is_compatible_v< E2 >> *=nullptr) noexcept
Definition: exempt_ptr.h:104
std::add_pointer_t< art::HLTGlobalStatus > pointer
Definition: exempt_ptr.h:84
constexpr exempt_ptr(pointer other) noexcept
Definition: exempt_ptr.h:101
QTextStream & reset(QTextStream &s)
constexpr exempt_ptr< E > make_exempt_ptr(E *) noexcept
constexpr exempt_ptr(std::nullptr_t) noexcept
Definition: exempt_ptr.h:100
p
Definition: test.py:223
constexpr bool operator==(exempt_ptr< E >, exempt_ptr< E >) noexcept
Definition: exempt_ptr.h:211
constexpr bool operator>(exempt_ptr< E >, exempt_ptr< E >)
Definition: exempt_ptr.h:265
void swap(exempt_ptr< E > &, exempt_ptr< E > &) noexcept
Definition: exempt_ptr.h:191
constexpr bool operator!=(exempt_ptr< E >, exempt_ptr< E >) noexcept
Definition: exempt_ptr.h:218
constexpr exempt_ptr & operator=(std::nullptr_t) noexcept
Definition: exempt_ptr.h:120
Definition: 018_def.c:13
constexpr std::enable_if_t< is_compatible_v< E2 >, exempt_ptr & > operator=(E2 *other) noexcept
Definition: exempt_ptr.h:128
list x
Definition: train.py:276
std::add_lvalue_reference_t< art::HLTGlobalStatus > reference
Definition: exempt_ptr.h:85
constexpr std::enable_if_t< is_compatible_v< E2 >, exempt_ptr & > operator=(exempt_ptr< E2 > const other) noexcept
Definition: exempt_ptr.h:138
void swap(exempt_ptr &other) noexcept
Definition: exempt_ptr.h:173
int bool
Definition: qglobal.h:345
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
constexpr exempt_ptr() noexcept
Definition: exempt_ptr.h:97