root/library/bdm/shared_ptr.h @ 419

Revision 419, 2.8 kB (checked in by vbarta, 15 years ago)

added basic smart pointer

Line 
1/*!
2  \file
3  \brief BDM's own smart pointer.
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 <assert.h>
17#include <limits.h>
18#include <algorithm>
19#include <stdexcept>
20#include <string>
21
22namespace bdm {
23
24//! A naive implementation of roughly a subset of the std::tr1:shared_ptr spec (really just roughly - it ignores memory exceptions, for example; also note I didn't read the spec).
25// The standard template would naturally be preferable, _if_ it was
26// included in the standard libraries of all supported compilers - but
27// that's exactly what remains to be seen...
28template <typename T>
29class shared_ptr {
30private:
31    T *payload;
32    unsigned *refCnt;
33
34public:
35    shared_ptr():
36        payload(0),
37        refCnt(0)
38    {
39    }
40
41    shared_ptr(T *p):
42        payload(p),
43        refCnt(p ? new unsigned(1) : 0)
44    {
45    }
46
47    shared_ptr(const shared_ptr &other):
48        payload(other.payload),
49        refCnt(other.refCnt)
50    {
51        add_ref();
52    }
53
54    ~shared_ptr()
55    {
56        del_ref();
57    }
58
59    shared_ptr &operator=(const shared_ptr &other)
60    {
61        other.add_ref();
62        del_ref();
63
64        payload = other.payload;
65        refCnt = other.refCnt;
66
67        return *this;
68    }
69
70    T *get() { return payload; }
71
72    T *operator->()
73    {
74        assert(payload);
75        return payload;
76    }
77
78    T &operator*()
79    {
80        assert(payload);
81        return *payload;
82    }
83
84    const T* get() const { return payload; }
85
86    const T *operator->() const
87    {
88        assert(payload);
89        return payload;
90    }
91
92    const T &operator*() const
93    {
94        assert(payload);
95        return *payload;
96    }
97
98    bool unique() const
99    {
100        return refCnt && (*refCnt == 1);
101    }
102
103    long use_count() const
104    {
105        return refCnt ? *refCnt : 0;
106    }
107
108    operator bool() const
109    {
110      return payload;
111    }
112
113    void swap(shared_ptr &other)
114    {
115        std::swap(payload, other.payload);
116        std::swap(refCnt, other.refCnt);
117    }
118
119private:
120    void add_ref() const
121    {
122        if (refCnt) {
123            if (*refCnt == UINT_MAX) {
124                throw std::overflow_error(
125                    std::string("Shared pointer has too many references."));
126            }
127
128            ++*refCnt;
129        }
130    }
131
132    void del_ref()
133    {
134        if (refCnt) {
135            if (!(--*refCnt)) {
136                delete payload;
137                delete refCnt;
138            }
139        }
140    }
141};
142
143template<typename T, typename U>
144bool operator==(shared_ptr<T> const &a, shared_ptr<U> const &b)
145{
146    return a.get() == b.get();
147}
148
149template<typename T, typename U>
150bool operator!=(shared_ptr<T> const &a, shared_ptr<U> const &b)
151{
152    return a.get() != b.get();
153}
154
155template<typename T, typename U>
156bool operator<(shared_ptr<T> const &a, shared_ptr<U> const &b)
157{
158    return a.get() < b.get();
159}
160
161}
162
163#endif
Note: See TracBrowser for help on using the browser.