// ptr_t<T> defines a "smart pointer"--it automatically counts references
// to the memory it manages and deletes the referenced object when the last
// referring ptr_t is destroyed. Usage of the class has a few restrictions:
//
// Do NOT store pointers it manages separately, UNLESS you can guarantee that
// the referenced object won't accidentally be deleted before you finish with
// the external pointer.
//
// Do NOT store pointers allocated by anything other than new. Along those
// lines, do NOT store arrays with this, since it calls delete and not delete[].
// Using the incorrect deallocation function could very well be a Bad Thing(TM)
//
// Also, somewhere your program must define a global map_t called ptr_map. This
// stores the table of pointer addresses and reference counts.
//
// This template is Copyright (C) 2005 Jeremy Pepper, and is released into the
// public domain AS-IS, without warranty of any kind, express or implied. The
// implementation may well contain undiscovered bugs.
#ifndef PTR_H
#define PTR_H
#include <map>
using namespace std;
typedef map<void *, int> map_t;
extern map_t ptr_map;
template <class T>
class ptr_t {
private:
T *ptr;
void cleanup() {
if(ptr) {
ptr_map[ptr]--;
if(!ptr_map[ptr]) {
ptr_map.erase(ptr);
delete ptr;
}
}
}
public:
ptr_t() {
ptr = NULL;
}
ptr_t(const T& o) {
ptr = NULL;
*this = &o;
}
ptr_t(const ptr_t<T> &p) {
if(this != &p) {
ptr = p.ptr;
ptr_map[ptr]++;
}
}
~ptr_t() {
cleanup();
}
T& operator*() const {
return *ptr;
}
T* operator->() const {
return ptr;
}
ptr_t &operator=(const ptr_t &p) {
if(this != &p) {
cleanup();
ptr_map[p.ptr]++;
ptr = p.ptr;
}
return *this;
}
ptr_t &operator=(T* p) {
if(ptr != p) {
cleanup();
ptr = p;
map_t::iterator i = ptr_map.find(ptr);
if(i == ptr_map.end())
ptr_map[ptr] = 1;
else
ptr_map[ptr]++;
}
return *this;
}
};
#endif /* PTR_H */