root/library/bdm/shared_ptr.h @ 554

Revision 554, 5.5 kB (checked in by vbarta, 15 years ago)

fewer Visual Studio warnings

RevLine 
[419]1/*!
2  \file
[529]3  \brief BDM's own smart pointers.
[419]4  \author Vaclav Barta.
5
6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
13#ifndef shared_ptr_h
14#define shared_ptr_h
15
16#include <limits.h>
17#include <algorithm>
18#include <stdexcept>
19#include <string>
[420]20#include "itpp_ext.h"
[419]21
22namespace bdm {
23
[529]24/*! \brief A naive implementation of roughly a subset of the std::tr1:shared_ptr spec
25
26  Really just roughly - it ignores memory
27  exceptions, for example; also note I didn't read the spec.
28
29  The standard template would naturally be preferable, _if_ it was
30  included in the standard libraries of all supported compilers - but
31  as of 2009, that's still a problem...
32*/
[419]33template <typename T>
34class shared_ptr {
[477]35        template<class U> friend class shared_ptr;
[461]36
[419]37private:
[477]38        T *payload;
39        unsigned *refCnt;
[419]40
41public:
[477]42        //! Creates an empty shared_ptr - one that doesn't point anywhere.
43        shared_ptr() :
44                        payload ( 0 ),
45                        refCnt ( 0 ) {
46        }
[419]47
[529]48        /*!
49          Constructs a shared_ptr that owns the pointer p (unless p
50          is NULL, in which case this constructor creates an empty
51          shared_ptr). When p isn't null, it must have been alllocated
52          by new!
53        */
[477]54        shared_ptr ( T *p ) :
55                        payload ( p ),
56                        refCnt ( p ? new unsigned ( 1 ) : 0 ) {
57        }
[419]58
[477]59        //! If other is empty, constructs an empty shared_ptr; otherwise,
60        //! constructs a shared_ptr that shares ownership with other.
61        shared_ptr ( const shared_ptr<T> &other ) :
62                        payload ( other.payload ),
63                        refCnt ( other.refCnt ) {
64                add_ref();
65        }
[419]66
[477]67        //! If other is empty, constructs an empty shared_ptr; otherwise,
68        //! constructs a shared_ptr that shares ownership with other.
69        template<typename U>
70        shared_ptr ( const shared_ptr<U> &other ) :
71                        payload ( other.payload ),
72                        refCnt ( other.refCnt ) {
73                add_ref();
74        }
[419]75
[477]76        ~shared_ptr() {
77                del_ref();
78        }
[419]79
[529]80        shared_ptr<T> &operator= ( const shared_ptr<T> &other ) {
[477]81                other.add_ref();
82                del_ref();
[419]83
[477]84                payload = other.payload;
85                refCnt = other.refCnt;
[419]86
[477]87                return *this;
88        }
[419]89
[477]90        //! Returns the stored pointer (which remains owned by this
91        //! instance).
92        T *get() {
93                return payload;
94        }
[419]95
[477]96        //! Returns the stored pointer (which remains owned by this
97        //! instance). This method may only be called when the stored
98        //! pointer isn't NULL.
99        T *operator->() {
100                it_assert_debug ( payload, "dereferencing NULL" );
101                return payload;
102        }
[419]103
[477]104        //! Returns a reference to the object pointed to by the stored
105        //! pointer. This method may only be called when the stored pointer
106        //! isn't NULL.
107        T &operator*() {
108                it_assert_debug ( payload, "dereferencing NULL" );
109                return *payload;
110        }
[419]111
[477]112        //! Returns the stored pointer (which remains owned by this
113        //! instance).
114        const T* get() const {
115                return payload;
116        }
[419]117
[477]118        //! Returns the stored pointer (which remains owned by this
119        //! instance). This method may only be called when the stored
120        //! pointer isn't NULL.
121        const T *operator->() const {
122                it_assert_debug ( payload, "dereferencing NULL" );
123                return payload;
124        }
[419]125
[477]126        //! Returns a reference to the object pointed to by the stored
127        //! pointer. This method may only be called when the stored pointer
128        //! isn't NULL.
129        const T &operator*() const {
130                it_assert_debug ( payload, "dereferencing NULL" );
131                return *payload;
132        }
[419]133
[477]134        bool unique() const {
135                return refCnt && ( *refCnt == 1 );
136        }
[419]137
[477]138        long use_count() const {
139                return refCnt ? *refCnt : 0;
140        }
[419]141
[477]142        operator bool() const {
[554]143                return !!payload;
[477]144        }
[419]145
[477]146        void swap ( shared_ptr &other ) {
147                std::swap ( payload, other.payload );
148                std::swap ( refCnt, other.refCnt );
149        }
150
[419]151private:
[477]152        void add_ref() const {
153                if ( refCnt ) {
154                        if ( *refCnt == UINT_MAX ) {
155                                throw std::overflow_error (
156                                    std::string ( "Shared pointer has too many references." ) );
157                        }
[419]158
[477]159                        ++*refCnt;
160                }
[419]161        }
162
[477]163        void del_ref() {
164                if ( refCnt ) {
165                        if ( ! ( --*refCnt ) ) {
166                                delete payload;
167                                delete refCnt;
168                        }
169                }
[419]170        }
171};
172
[536]173//! Compare shared pointers
[419]174template<typename T, typename U>
[477]175bool operator== ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
176        return a.get() == b.get();
[419]177}
178
[536]179//! Compare shared pointers
[419]180template<typename T, typename U>
[477]181bool operator!= ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
182        return a.get() != b.get();
[419]183}
184
[536]185//! Compare shared pointers
[419]186template<typename T, typename U>
[477]187bool operator< ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
188        return a.get() < b.get();
[419]189}
190
[529]191/*! \brief A wrapper of shared_ptr which is never empty.
192
193  T must have a default constructor.
194
195  Note that shared_ptr's destructor isn't virtual - don't call delete
196  on pointers to instances of this class.
197 */
198template <typename T>
199class object_ptr : public shared_ptr<T>
200{
201public:
202        /*!
203          \brief Default constructor
204
205          Calls T's default constructor.
206        */
207        object_ptr() : shared_ptr<T> ( new T() ) { }
208
209        /*!
210          \brief Upcast from shared_ptr<T> to object_ptr<T>
211
212          \param b The shared pointer, which must not be empty.
213        */
214        object_ptr ( const shared_ptr<T> &b ) : shared_ptr<T> ( b ) {
215                it_assert_debug ( this->get(), "object_ptr cannot be empty" );
216        }
217
218        /*!
219          Constructs an object_ptr that owns the pointer p. p must
220          have been alllocated by new!
221        */
222        object_ptr ( T *p ) : shared_ptr<T> ( p ) {
223                it_assert_debug ( p, "object_ptr cannot be empty" );
224        }
225
226        object_ptr<T> &operator= ( const object_ptr<T> &other ) {
227                shared_ptr<T>::operator= ( other );
228                return *this;
229        }
230};
231
232#define SHAREDPTR(class_name) typedef bdm::object_ptr< class_name > class_name##_ptr
233
234#define SHAREDPTR2(template_class_name, template_parameter_name) typedef bdm::object_ptr< template_class_name < template_parameter_name > > template_class_name##_##template_parameter_name##_ptr
235
[419]236}
237
238#endif
Note: See TracBrowser for help on using the browser.