EventAnalysis  1.0.0
ObserverPtr.h
Go to the documentation of this file.
1 /*
2  * ObserverPtr.h
3  *
4  * Created on: 09 Aug 2017
5  * Author: Nicola Mori
6  */
7 
10 #ifndef OBSERVERPTR_H_
11 #define OBSERVERPTR_H_
12 
13 #include <core/Traits.h>
14 
15 #include <iostream>
16 #include <memory>
17 #include <stdexcept>
18 #include <type_traits>
19 namespace EA {
20 
28 template <typename T> class observer_ptr {
29 public:
30  /* ********* Constructors and assignment operators ********* */
31 
36  observer_ptr() : _ptr(nullptr) {}
37 
44  observer_ptr(std::nullptr_t) { _ptr = nullptr; }
45 
50  template <typename W> observer_ptr(const observer_ptr<W> p) { _ptr = p.get(); }
51 
57  template <typename W> observer_ptr &operator=(const observer_ptr<W> &p) {
58  _ptr = p.get();
59  return *this;
60  }
61 
62  /* ********* Constructors and assignment operators from raw pointers ********* */
63 
72  template <typename W> observer_ptr(W *p) { _ptr = p; }
73 
82  template <typename W> observer_ptr &operator=(W *p) {
83  _ptr = p;
84  return *this;
85  }
86 
87  /* ********* Construction and assignment from other types of smart pointer ********* */
88 
96  template <typename W> observer_ptr(const std::unique_ptr<W> &p) { _ptr = p.get(); }
97 
106  template <typename W> observer_ptr &operator=(const std::unique_ptr<W> &p) {
107  _ptr = p.get();
108  return *this;
109  }
110 
118  template <typename W> observer_ptr(const std::shared_ptr<W> p) { _ptr = p.get(); }
119 
128  template <typename W> observer_ptr &operator=(const std::shared_ptr<W> &p) {
129  _ptr = p.get();
130  return *this;
131  }
132 
133  /* ********* Conversion methods ********* */
134 
138  operator bool() const { return _ptr != nullptr; }
139 
140  operator int() const = delete;
141 
147  template <typename W> operator W *() { return _ptr; }
148 
149  /* ********* Data access methods ********* */
150 
155  T *get() const { return _ptr; }
156 
161  T *operator->() const { return _ptr; }
162 
167  T &operator*() const {
168  if (_ptr == nullptr)
169  throw(std::runtime_error("observer_ptr points to nothing"));
170  return *_ptr;
171  }
172 
173  /* ********* Comparison operators ********* */
174  // /*! @brief Comparison with observer_ptr.
175  // *
176  // * The template argument type W must either exactly match the type T or be a child class of T.
177  // *
178  // * @param p The lhs observer_ptr.
179  // * @return true if lhs and rhs point to the same address.
180  // */
181  // // template <typename W> bool operator==(const observer_ptr<typename std::decay<W>::type> &p) {
182  // // std::cout << "1: " << _ptr << " " << p.get() << std::endl;
183  // // return (_ptr == p._ptr);
184  // // }
185  //
186  // /*! @brief Comparison with raw pointer.
187  // *
188  // * The template argument type W must either exactly match the type T or be a child class of T.
189  // *
190  // * @param p The lhs observer_ptr.
191  // * @return true if lhs and rhs point to the same address.
192  // */
193  // template <typename W> bool operator==(typename std::decay<W>::type *p) {
194  // std::cout << "2: " << _ptr << " " << p << std::endl;
195  // return (_ptr == p);
196  // }
197  //
198  // /*! @brief Comparison with std::unique_ptr.
199  // *
200  // * The template argument type W must either exactly match the type T or be a child class of T.
201  // *
202  // * @param p The lhs std::unique_ptr.
203  // * @return true if lhs and rhs point to the same address.
204  // */
205  // template <typename W> bool operator==(const std::unique_ptr<typename std::decay<W>::type> &p) {
206  // std::cout << "3: " << _ptr << " " << p.get() << std::endl;
207  // return (_ptr == p.get());
208  // }
209  //
210  // /*! @brief Comparison with std::shared_ptr.
211  // *
212  // * The template argument type W must either exactly match the type T or be a child class of T.
213  // *
214  // * @param p The lhs std::shared_ptr.
215  // * @return true if lhs and rhs point to the same address.
216  // */
217  // template <typename W> bool operator==(const std::shared_ptr<typename std::decay<W>::type> &p) {
218  // std::cout << "4: " << _ptr << " " << p.get() << std::endl;
219  // return (_ptr == p.get());
220  // }
221 
222  // template <typename W> bool operator!=(const observer_ptr<typename std::decay<W>::type> &p) {
223  // std::cout << "!1: " << _ptr << " " << p.get() << std::endl;
224  // return !(_ptr == p.get());
225  // }
226  // template <typename W> bool operator!=(typename std::decay<W>::type *p) {
227  // std::cout << "!2: " << _ptr << " " << p << std::endl;
228  // return !(_ptr == p);
229  // }
230  // template <typename W> bool operator!=(const std::unique_ptr<typename std::decay<W>::type> &p) {
231  // std::cout << "!3: " << _ptr << " " << p.get() << std::endl;
232  // return !(_ptr == p.get());
233  // }
234  // template <typename W> bool operator!=(const std::shared_ptr<typename std::decay<W>::type> &p) {
235  // std::cout << "!4: " << _ptr << " " << p.get() << std::endl;
236  // return !(_ptr == p.get());
237  // }
238 
239 private:
240  T *_ptr;
241 };
242 
243 // Some useful metaprogramming tools:
244 // 1. Check if the template type is observer_ptr
245 template <typename T> struct is_observer_ptr : std::false_type {};
246 template <typename T> struct is_observer_ptr<observer_ptr<T>> : std::true_type {};
247 // 2. Check if at least one type is observer_ptr
248 template <typename T, typename W> struct one_observer_ptr : or_<is_observer_ptr<T>, is_observer_ptr<W>> {};
249 // 3. Check if at least one type is observer_ptr and the other one is not a pointer
250 template <typename T, typename W>
252  or_<is_observer_ptr<T>, is_observer_ptr<W>>, //
253  not_< //
254  and_<std::is_pointer<T>, std::is_pointer<W>>> //
255  > {};
256 
257 // Comparison operators
258 // Overloads for one pointer argument
259 template <typename T, typename W>
260 typename std::enable_if_t<std::is_pointer<W>::value, bool> operator==(const observer_ptr<T> &p1, const W &p2) {
261  return (p1.get() == p2);
262 }
263 
264 template <typename T, typename W>
265 typename std::enable_if_t<std::is_pointer<W>::value, bool> operator==(const W &p1, const observer_ptr<T> &p2) {
266  return (p2 == p1);
267 }
268 
269 // Overloads for one observer_ptr and no pointers (i.e. the other argument must be a smart pointer which implements
270 // get())
271 template <typename T, typename W>
272 typename std::enable_if_t<one_observer_ptr_and_no_pointer<T, W>::value, bool> operator==(const T &p1, const W &p2) {
273  return (p1.get() == p2.get());
274 }
275 
276 template <typename T, typename W>
277 typename std::enable_if_t<one_observer_ptr<T, W>::value, bool> operator!=(const T &p1, const W &p2) {
278  return !(p1 == p2);
279 }
280 
281 } // namespace EA
282 
283 #endif /* OBSERVERPTR_H_ */
T * get() const
Getter for pointed address.
Definition: ObserverPtr.h:155
A smart pointer not owning the wrapped object.
Definition: ObserverPtr.h:28
T * operator->() const
Arrow operator.
Definition: ObserverPtr.h:161
observer_ptr()
Default constructor.
Definition: ObserverPtr.h:36
std::enable_if_t< one_observer_ptr< T, W >::value, bool > operator!=(const T &p1, const W &p2)
Definition: ObserverPtr.h:277
observer_ptr & operator=(const observer_ptr< W > &p)
Assignment operator.
Definition: ObserverPtr.h:57
IncludeFileExc.h IncludeFileExc class declaration.
Definition: Algorithm.h:21
observer_ptr(const std::unique_ptr< W > &p)
Constructor from std::unique_ptr.
Definition: ObserverPtr.h:96
Definition: ObserverPtr.h:248
Definition: Traits.h:30
observer_ptr(std::nullptr_t)
Null constructor.
Definition: ObserverPtr.h:44
observer_ptr(W *p)
Constructor from raw pointer.
Definition: ObserverPtr.h:72
std::enable_if_t< std::is_pointer< W >::value, bool > operator==(const observer_ptr< T > &p1, const W &p2)
Definition: ObserverPtr.h:260
T & operator*() const
Indirection operator.
Definition: ObserverPtr.h:167
observer_ptr & operator=(const std::shared_ptr< W > &p)
Assignment operator from std::shared_ptr.
Definition: ObserverPtr.h:128
Definition: Traits.h:26
observer_ptr(const std::shared_ptr< W > p)
Constructor from std::shared_ptr.
Definition: ObserverPtr.h:118
observer_ptr(const observer_ptr< W > p)
Copy constructor.
Definition: ObserverPtr.h:50
observer_ptr & operator=(W *p)
Assignment operator from raw pointer.
Definition: ObserverPtr.h:82
T * _ptr
Comparison with observer_ptr.
Definition: ObserverPtr.h:240
observer_ptr & operator=(const std::unique_ptr< W > &p)
Assignment operator from std::unique_ptr.
Definition: ObserverPtr.h:106
Definition: ObserverPtr.h:251
Definition: ObserverPtr.h:245