IpSmartPtr.hpp
Go to the documentation of this file.
1 // Copyright (C) 2004, 2011 International Business Machines and others.
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // $Id: IpSmartPtr.hpp 2005 2011-06-06 12:55:16Z stefan $
6 //
7 // Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
8 
9 #ifndef __IPSMARTPTR_HPP__
10 #define __IPSMARTPTR_HPP__
11 
12 #ifdef HAVE_CSTDDEF
13 # include <cstddef>
14 #else
15 # ifdef HAVE_STDDEF_H
16 # include <stddef.h>
17 # else
18 # error "don't have header file for stddef"
19 # endif
20 #endif
21 
22 #include "IpReferenced.hpp"
23 
24 #include "IpDebug.hpp"
25 #if COIN_IPOPT_CHECKLEVEL > 2
26 # define IP_DEBUG_SMARTPTR
27 #endif
28 
29 namespace Ipopt
30 {
31 
174  template<class T>
175  class SmartPtr : public Referencer
176  {
177  public:
178 #define dbg_smartptr_verbosity 0
179 
183  SmartPtr();
184 
186  SmartPtr(const SmartPtr<T>& copy);
187 
189  SmartPtr(T* ptr);
190 
194  ~SmartPtr();
196 
201  T* operator->() const;
202 
205  T& operator*() const;
206 
209  SmartPtr<T>& operator=(T* rhs);
210 
214  SmartPtr<T>& operator=(const SmartPtr<T>& rhs);
215 
218  template <class U1, class U2>
219  friend
220  bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
221 
224  template <class U1, class U2>
225  friend
226  bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
227 
230  template <class U1, class U2>
231  friend
232  bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
233 
236  template <class U1, class U2>
237  friend
238  bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
239 
242  template <class U1, class U2>
243  friend
244  bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
245 
248  template <class U1, class U2>
249  friend
250  bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
252 
265  template <class U>
266  friend
267  U* GetRawPtr(const SmartPtr<U>& smart_ptr);
268 
270  template <class U>
271  friend
272  SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
273 
278  template <class U>
279  friend
280  bool IsValid(const SmartPtr<U>& smart_ptr);
281 
286  template <class U>
287  friend
288  bool IsNull(const SmartPtr<U>& smart_ptr);
290 
291  private:
295  T* ptr_;
296 
300  SmartPtr<T>& SetFromRawPtr_(T* rhs);
301 
306 
308  void ReleasePointer_();
310  };
311 
314  template <class U>
315  U* GetRawPtr(const SmartPtr<U>& smart_ptr);
316 
317  template <class U>
318  SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
319 
320  template <class U>
321  bool IsNull(const SmartPtr<U>& smart_ptr);
322 
323  template <class U>
324  bool IsValid(const SmartPtr<U>& smart_ptr);
325 
326  template <class U1, class U2>
327  bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
328 
329  template <class U1, class U2>
330  bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
331 
332  template <class U1, class U2>
333  bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
334 
335  template <class U1, class U2>
336  bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
337 
338  template <class U1, class U2>
339  bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
340 
341  template <class U1, class U2>
342  bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
343 
345 
346 
347  template <class T>
349  :
350  ptr_(0)
351  {
352 #ifdef IP_DEBUG_SMARTPTR
353  DBG_START_METH("SmartPtr<T>::SmartPtr()", dbg_smartptr_verbosity);
354 #endif
355 
356 #ifdef CHECK_SMARTPTR
357 
358  const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
359  = ptr_;
360  trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = 0;
361 #endif
362 
363  }
364 
365 
366  template <class T>
368  :
369  ptr_(0)
370  {
371 #ifdef IP_DEBUG_SMARTPTR
372  DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)", dbg_smartptr_verbosity);
373 #endif
374 
375 #ifdef CHECK_SMARTPTR
376 
377  const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
378  = ptr_;
379  trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = 0;
380 #endif
381 
382  (void) SetFromSmartPtr_(copy);
383  }
384 
385 
386  template <class T>
388  :
389  ptr_(0)
390  {
391 #ifdef IP_DEBUG_SMARTPTR
392  DBG_START_METH("SmartPtr<T>::SmartPtr(T* ptr)", dbg_smartptr_verbosity);
393 #endif
394 
395 #ifdef CHECK_SMARTPTR
396 
397  const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
398  = ptr_;
399  trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = 0;
400 #endif
401 
402  (void) SetFromRawPtr_(ptr);
403  }
404 
405  template <class T>
407  {
408 #ifdef IP_DEBUG_SMARTPTR
409  DBG_START_METH("SmartPtr<T>::~SmartPtr(T* ptr)", dbg_smartptr_verbosity);
410 #endif
411 
412  ReleasePointer_();
413  }
414 
415 
416  template <class T>
418  {
419 #ifdef IP_DEBUG_SMARTPTR
420  DBG_START_METH("T* SmartPtr<T>::operator->()", dbg_smartptr_verbosity);
421 #endif
422 
423  // cannot deref a null pointer
424 #if COIN_IPOPT_CHECKLEVEL > 0
425 
426  assert(ptr_);
427 #endif
428 
429  return ptr_;
430  }
431 
432 
433  template <class T>
435  {
436 #ifdef IP_DEBUG_SMARTPTR
437  DBG_START_METH("T& SmartPtr<T>::operator*()", dbg_smartptr_verbosity);
438 #endif
439 
440  // cannot dereference a null pointer
441 #if COIN_IPOPT_CHECKLEVEL > 0
442 
443  assert(ptr_);
444 #endif
445 
446  return *ptr_;
447  }
448 
449 
450  template <class T>
452  {
453 #ifdef IP_DEBUG_SMARTPTR
454  DBG_START_METH("SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)", dbg_smartptr_verbosity);
455 #endif
456 
457  return SetFromRawPtr_(rhs);
458  }
459 
460 
461  template <class T>
463  {
464 #ifdef IP_DEBUG_SMARTPTR
466  "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)",
468 #endif
469 
470  return SetFromSmartPtr_(rhs);
471  }
472 
473 
474  template <class T>
476  {
477 #ifdef IP_DEBUG_SMARTPTR
479  "SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)", dbg_smartptr_verbosity);
480 #endif
481 
482  // Release any old pointer
483  ReleasePointer_();
484 
485  if (rhs != 0) {
486  rhs->AddRef(this);
487  ptr_ = rhs;
488  }
489 
490  return *this;
491  }
492 
493  template <class T>
495  {
496 #ifdef IP_DEBUG_SMARTPTR
498  "SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)",
500 #endif
501 
502  T* ptr = GetRawPtr(rhs);
503  /* AW: I changed this so that NULL is correctly copied from the
504  right hand side */
505  // if (ptr != NULL) {
506  // SetFromRawPtr_(ptr);
507  // }
508  SetFromRawPtr_(ptr);
509 
510  return (*this);
511  }
512 
513 
514  template <class T>
516  {
517 #ifdef IP_DEBUG_SMARTPTR
519  "void SmartPtr<T>::ReleasePointer()",
521 #endif
522 
523  if (ptr_) {
524  ptr_->ReleaseRef(this);
525  if (ptr_->ReferenceCount() == 0) {
526  delete ptr_;
527  }
528  ptr_ = 0;
529  }
530  }
531 
532 
533  template <class U>
534  U* GetRawPtr(const SmartPtr<U>& smart_ptr)
535  {
536 #ifdef IP_DEBUG_SMARTPTR
538  "T* GetRawPtr(const SmartPtr<T>& smart_ptr)",
539  0);
540 #endif
541 
542  return smart_ptr.ptr_;
543  }
544 
545  template <class U>
547  {
548  // compiler should implicitly cast
549  return GetRawPtr(smart_ptr);
550  }
551 
552  template <class U>
553  bool IsValid(const SmartPtr<U>& smart_ptr)
554  {
555  return !IsNull(smart_ptr);
556  }
557 
558  template <class U>
559  bool IsNull(const SmartPtr<U>& smart_ptr)
560  {
561 #ifdef IP_DEBUG_SMARTPTR
563  "bool IsNull(const SmartPtr<T>& smart_ptr)",
564  0);
565 #endif
566 
567  return (smart_ptr.ptr_ == 0);
568  }
569 
570 
571  template <class U1, class U2>
572  bool ComparePointers(const U1* lhs, const U2* rhs)
573  {
574 #ifdef IP_DEBUG_SMARTPTR
576  "bool ComparePtrs(const U1* lhs, const U2* rhs)",
578 #endif
579 
580  if (lhs == rhs) {
581  return true;
582  }
583 
584  // Even if lhs and rhs point to the same object
585  // with different interfaces U1 and U2, we cannot guarantee that
586  // the value of the pointers will be equivalent. We can
587  // guarantee this if we convert to void*
588  const void* v_lhs = static_cast<const void*>(lhs);
589  const void* v_rhs = static_cast<const void*>(rhs);
590  if (v_lhs == v_rhs) {
591  return true;
592  }
593 
594  // They must not be the same
595  return false;
596  }
597 
598  template <class U1, class U2>
599  bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
600  {
601 #ifdef IP_DEBUG_SMARTPTR
603  "bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
605 #endif
606 
607  U1* raw_lhs = GetRawPtr(lhs);
608  U2* raw_rhs = GetRawPtr(rhs);
609  return ComparePointers(raw_lhs, raw_rhs);
610  }
611 
612  template <class U1, class U2>
613  bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs)
614  {
615 #ifdef IP_DEBUG_SMARTPTR
617  "bool operator==(SmartPtr<U1>& lhs, U2* rhs)",
619 #endif
620 
621  U1* raw_lhs = GetRawPtr(lhs);
622  return ComparePointers(raw_lhs, raw_rhs);
623  }
624 
625  template <class U1, class U2>
626  bool operator==(U1* raw_lhs, const SmartPtr<U2>& rhs)
627  {
628 #ifdef IP_DEBUG_SMARTPTR
630  "bool operator==(U1* raw_lhs, SmartPtr<U2>& rhs)",
632 #endif
633 
634  const U2* raw_rhs = GetRawPtr(rhs);
635  return ComparePointers(raw_lhs, raw_rhs);
636  }
637 
638  template <class U1, class U2>
639  bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
640  {
641 #ifdef IP_DEBUG_SMARTPTR
643  "bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
645 #endif
646 
647  bool retValue = operator==(lhs, rhs);
648  return !retValue;
649  }
650 
651  template <class U1, class U2>
652  bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs)
653  {
654 #ifdef IP_DEBUG_SMARTPTR
656  "bool operator!=(SmartPtr<U1>& lhs, U2* rhs)",
658 #endif
659 
660  bool retValue = operator==(lhs, raw_rhs);
661  return !retValue;
662  }
663 
664  template <class U1, class U2>
665  bool operator!=(U1* raw_lhs, const SmartPtr<U2>& rhs)
666  {
667 #ifdef IP_DEBUG_SMARTPTR
669  "bool operator!=(U1* raw_lhs, SmartPtr<U2>& rhs)",
671 #endif
672 
673  bool retValue = operator==(raw_lhs, rhs);
674  return !retValue;
675  }
676 
677 } // namespace Ipopt
678 
679 #endif
680