#ifndef _REFOBJ_H
#define _REFOBJ_H
# include <utility>
# include <vector>
# include <map>
using namespace std;
template<class T>
class mngarg: public pair<T *, int>{
public:
typedef pair<T *, int> base_t;
using base_t::second;
using base_t::first;
mngarg(T *ptr, int managed=0): pair<T*,int>(ptr,managed){}
template<class A>
mngarg(const mngarg<A> &arg): pair<T*,int>(arg.first,arg.second){}
};
template<class T>
mngarg<T> make_mngarg(T *ptr, int managed=1){
return mngarg<T>(ptr,managed);
}
template<class T>
class mngptr: public pair<T *, int>{
public:
typedef pair<T *, int> base_t;
typedef T *pointer;
using base_t::second;
using base_t::first;
mngptr(T* ptr=NULL, int managed=0): pair<T*,int>(ptr,managed){
}
mngptr(const mngarg<T> &arg): pair<T*,int>(arg.first,arg.second){}
const mngptr &operator=(const mngarg<T> &arg){
reset(arg.first,arg.second);
return *this;
}
void reset(T* ptr=NULL, int managed=0){
if(second && first && first!=ptr){
if(second&0x8)delete [] first;
else delete first;
}
first=ptr;
second=managed;
}
void reset(const mngarg<T> &arg){
reset(arg.first,arg.second);
}
T* ptr() const {
return first;
}
T* operator->() const {
return first;
}
T& operator*() const{
return *first;
}
T& operator[] (int i) const{
return *(first+i);
}
int managed() const {
return second;
}
~mngptr(){
reset();
}
};
# if 0
template <template<class _type> class cont_tt, class T>
class refcontainer: public cont_tt< T * >{
protected:
int man;
public:
typedef cont_tt< T * > base_t;
typedef typename base_t::iterator iterator;
typedef typename base_t::const_iterator const_iterator;
refcontainer(int smanaged=0):man(smanaged){}
refcontainer(size_t n, int smanaged=0):base_t(n),man(smanaged){}
void set_managed(int sman){
man=sman;
}
~refcontainer(){
if(man){
size_t i, n=base_t::size();
for(i=0;i<n;i++)
if((*this)[i]) delete (*this)[i];
}
}
};
# endif
template < class T >
class refvector: public std::vector< T * >{
protected:
int man;
public:
typedef vector<T*> base_t;
typedef typename base_t::iterator iterator;
typedef typename base_t::const_iterator const_iterator;
refvector(int smanaged=0):man(smanaged){}
refvector(size_t n, int smanaged):base_t(n),man(smanaged){}
void set_managed(int sman){
man=sman;
}
~refvector(){
clear();
}
void clear() {
if(man){
iterator it=base_t::begin();
for(;it!=base_t::end();++it)
if(*it)
delete (*it);
}
base_t::clear();
}
iterator erase(iterator it){
if(man && *it)
delete (*it);
return base_t::erase(it);
}
};
template <class key_tt, class T >
class refmap: public std::map<key_tt, T * >{
protected:
int man;
public:
typedef std::map<key_tt, T * > base_t;
typedef typename base_t::iterator iterator;
typedef typename base_t::const_iterator const_iterator;
refmap(int smanaged=0):man(smanaged){}
refmap(size_t n, int smanaged=0):base_t(n),man(smanaged){}
void set_managed(int sman){
man=sman;
}
~refmap(){
clear();
}
void clear() {
if(man){
for(typename base_t::iterator i=base_t::begin();i!=base_t::end();++i)
if(i->second) delete i->second;
}
base_t::clear();
}
iterator erase(iterator it){
if(man && it->second)
delete it->second;
return base_t::erase(it);
}
};
template<class T>
class delete_ptr{
public:
void operator()(T *ptr){
delete ptr;
}
};
template<class T, class delete_t=delete_ptr<T> >
class shptr{
template<class Y, class Z> friend class shptr;
T *p;
int *num;
void set(T *p_, int managed){
p=p_;
if(p&&managed){
num=new int;
*num=1;
}
else num=NULL;
}
template<class Y>
void set(const Y &other){
p=other.p;
if(p){
num=other.num;
if(num)(*num)++;
}
else num=NULL;
}
void set(const shptr &other){
p=other.p;
if(p){
num=other.num;
if(num)(*num)++;
}
else num=NULL;
}
public:
shptr(T* p=NULL, int managed=1){
set(p,managed);
}
shptr(const mngarg<T> &arg){
set(arg.first,arg.second);
}
template<class Y>
shptr(const Y &other){
set(other);
}
shptr(const shptr &other){
set(other);
}
void reset(T *p_, int managed=1) {
if(p!=p_){
free();
set(p_,managed);
}
}
void reset(const shptr &other) {
if(this!=&other){
free();
set(other);
}
}
const shptr &operator=(T *p) {
reset(p,0);
return *this;
}
const shptr &operator=(const mngarg<T> &arg) {
reset(arg.first,arg.second);
return *this;
}
template<class Y>
const shptr &operator=(const Y &other){
reset(other);
return *this;
}
const shptr &operator=(const shptr &other) {
reset(other);
return *this;
}
virtual ~shptr(){
free();
}
void free(){
if(p){
if(num){
(*num)--;
if((*num)==0){
delete_t()(p);
delete num;
}
num=NULL;
}
p=NULL;
}
}
bool valid() const {
return p!=NULL;
}
T* ptr() const {
return p;
}
T* operator->() const {
return p;
}
T& operator*() const{
return *p;
}
};
#endif