NptReferences.h

00001 /*****************************************************************
00002 |
00003 |   Neptune - References
00004 |
00005 |   (c) 2001-2006 Gilles Boccon-Gibod
00006 |   Author: Gilles Boccon-Gibod (bok@bok.net)
00007 |
00008 ****************************************************************/
00009 
00010 #ifndef _NPT_REFERENCES_H_
00011 #define _NPT_REFERENCES_H_
00012 
00013 /*----------------------------------------------------------------------
00014 |   includes
00015 +---------------------------------------------------------------------*/
00016 #include "NptConstants.h"
00017 
00018 /*----------------------------------------------------------------------
00019 |   NPT_Reference
00020 +---------------------------------------------------------------------*/
00021 template <typename T>
00022 class NPT_Reference
00023 {
00024 public:
00025     // constructors and destructor
00026     NPT_Reference() : m_Object(NULL), m_Counter(NULL) {}
00027     explicit NPT_Reference(T* object) : 
00028         m_Object(object), m_Counter(object?new NPT_Cardinal(1):NULL) {}
00029 
00030     NPT_Reference(const NPT_Reference<T>& ref) :
00031         m_Object(ref.m_Object), m_Counter(ref.m_Counter) {
00032         if (m_Counter) ++(*m_Counter);
00033     }
00034 
00035     // this methods should be private, but this causes a problem on some
00036     // compilers, because we need this function in order to implement
00037     // the cast operator operator NPT_Reference<U>() below, which would
00038     // have to be marked as a friend, and friend declarations with the 
00039     // same class name confuses some compilers
00040     NPT_Reference(T* object, NPT_Cardinal* counter) : 
00041         m_Object(object), m_Counter(counter) {
00042         if (m_Counter) ++(*m_Counter);
00043     }
00044 
00045     ~NPT_Reference() {
00046         Release();
00047     }
00048 
00049     // overloaded operators
00050     NPT_Reference<T>& operator=(const NPT_Reference<T>& ref) {
00051         if (this != &ref) {
00052             Release();
00053             m_Object = ref.m_Object;
00054             m_Counter = ref.m_Counter;
00055             if (m_Counter) ++(*m_Counter);
00056         }
00057         return *this;
00058     }
00059     NPT_Reference<T>& operator=(T* object) {
00060         Release();
00061         m_Object = object;
00062         m_Counter = object?new NPT_Cardinal(1):NULL;
00063         return *this;
00064     }
00065     T& operator*() const { return *m_Object; }
00066     T* operator->() const { return m_Object; }
00067 
00068     bool operator==(const NPT_Reference<T>& ref) {
00069         return m_Object == ref.m_Object;
00070     } 
00071     bool operator!=(const NPT_Reference<T>& ref) {
00072         return m_Object != ref.m_Object;
00073     }
00074 
00075     // overloaded cast operators
00076     template <typename U> operator NPT_Reference<U>() {
00077         return NPT_Reference<U>(m_Object, m_Counter);
00078     }
00079 
00080     // methods
00081     T* AsPointer() const { return m_Object; }
00082     bool IsNull() const { return m_Object == 0; }
00083 
00084 private:
00085     // methods
00086     void Release() {
00087         if (m_Counter && --(*m_Counter) == 0) {
00088             delete m_Counter;
00089             delete m_Object;
00090         }
00091     }
00092 
00093     // members
00094     T*            m_Object;
00095     NPT_Cardinal* m_Counter;
00096 };
00097 
00098 #endif // _NPT_REFERENCES_H_