#ifndef _KOK_SMARTPTR_H_
#define _KOK_SMARTPTR_H_
#pragma once
#include <cstdlib>
#include <assert.h>
#include <algorithm>
namespace KOK
{
template<class P>
class CheckAssert
{
protected:
void OnRef(const P& pointer)
{
assert(pointer !=NULL);
}
void OnDeRef(const P& pointer)
{
assert(pointer !=NULL);
}
void Swap(CheckAssert&){};
CheckAssert(){};
CheckAssert(const CheckAssert&){};
template<class U>
CheckAssert(const CheckAssert<U>&){};
};
template<class T>
class DefaultStorage
{
public:
typedef T* StoredType;
typedef T* PointerType;
typedef T& RefType;
protected:
DefaultStorage():pointee_(Default()){};
DefaultStorage(StoredType pType):pointee_(pType){};
DefaultStorage(const DefaultStorage& pType){};
template<class H>
DefaultStorage(const DefaultStorage<H>& pType){};
void Swap(DefaultStorage& other)
{
std::swap(pointee_, other.pointee_);
};
void Destroy()
{
delete pointee_;
};
static StoredType Default()
{
return 0;
}
public:
RefType operator *() const
{
return *pointee_;
}
PointerType operator ->() const
{
return pointee_;
}
template<class U>
friend typename DefaultStorage<U>::StoredType GetPtrImpl(const DefaultStorage<U>& wrap);
template<class U>
friend typename DefaultStorage<U>::RefType GetRef(const DefaultStorage<U>& wrap);
template<class U>
friend typename DefaultStorage<U>::StoredType& GetPtrRef(DefaultStorage<U>& wrap);
template<class U>
friend typename const DefaultStorage<U>::StoredType& GetPtrRef(const DefaultStorage<U>& wrap);
private:
StoredType pointee_;
};
template<class U>
inline typename DefaultStorage<U>::StoredType GetPtrImpl(const DefaultStorage<U>& wrap)
{
return wrap.pointee_;
};
template<class U>
inline typename DefaultStorage<U>::RefType GetRef(const DefaultStorage<U>& wrap)
{
return *wrap.pointee_;
};
template<class U>
inline typename DefaultStorage<U>::StoredType& GetPtrRef(DefaultStorage<U>& wrap)
{
return wrap.pointee_;
};
template<class U>
inline typename const DefaultStorage<U>::StoredType& GetPtrRef(const DefaultStorage<U>& wrap)
{
return wrap.pointee_;
};
template<class P>
class RefCount
{
private:
unsigned int* count_;
protected:
RefCount(const RefCount& other):count_(other.count_){};
template<class P1>
RefCount(const RefCount<P1>& other):count_(reinterpret_cast<const RefCount&>(other).count_){};
RefCount():count_(new unsigned int(1))
{
assert(count_ != NULL);
};
P Clone(const P& val)
{
++*count_;
return val;
}
bool Release()
{
if(--*count_ == 0)
{
delete count_;
return true;
}
return false;
};
void Reset()
{
*count_ = 1;
};
void Swap(RefCount& other)
{
std::swap(count_, other.count_);
};
enum {destroyCopy = false};
};
template<class T,
template<class> class StoragePolicy = DefaultStorage,
template<class> class OwnershipPolicy = RefCount,
template<class> class CheckErrorPolicy = CheckAssert>
class SmartPtr : public StoragePolicy<T>,
public OwnershipPolicy<typename StoragePolicy<T>::StoredType>,
public CheckErrorPolicy<typename StoragePolicy<T>::StoredType>
{
public:
typedef typename StoragePolicy<T>::StoredType StoredType;
typedef typename StoragePolicy<T>::PointerType PointerType;
typedef typename StoragePolicy<T>::RefType RefType;
template<bool B, class X, class Y>
struct Select
{
};
template<class X, class Y>
struct Select<false, X, Y>
{
typedef Y type;
};
template<class X, class Y>
struct Select<true, X, Y>
{
typedef Y type;
};
private:
typedef StoragePolicy<T> SP;
typedef OwnershipPolicy<StoredType> OP;
typedef CheckErrorPolicy<StoredType> CP;
public:
typedef typename Select<OP::destroyCopy, SmartPtr<T, StoragePolicy, OwnershipPolicy, CheckErrorPolicy>, const SmartPtr<T, StoragePolicy, OwnershipPolicy, CheckErrorPolicy> >::type CpyArg;
SmartPtr(StoredType ptr):SP(ptr)
{
assert(NULL != ptr);
};
SmartPtr()
{
};
SmartPtr(CpyArg& copyPtr):SP(copyPtr), OP(copyPtr), CP(copyPtr)
{
GetPtrRef(*this) = OP::Clone(GetPtrImpl(copyPtr));
};
template<class T1,
template<class> class SP1,
template<class> class OP1,
template<class> class CP1>
SmartPtr(SmartPtr<T1, SP1, OP1, CP1>& copyPtr):SP(copyPtr), OP(copyPtr), CP(copyPtr)
{
GetPtrRef(*this) = OP::Clone(GetPtrImpl(copyPtr));
};
template<class T1,
template<class> class SP1,
template<class> class OP1,
template<class> class CP1>
SmartPtr(const SmartPtr<T1, SP1, OP1, CP1>& copyPtr):SP(copyPtr), OP(copyPtr), CP(copyPtr)
{
GetPtrRef(*this) = OP::Clone(GetPtrImpl(copyPtr));
};
RefType operator *()
{
CP::OnDeRef(GetPtrImpl(*this));
return SP::operator*();
};
PointerType operator ->()
{
CP::OnDeRef(GetPtrImpl(*this));
return SP::operator->();
};
template<class T1,
template<class> class SP1,
template<class> class OP1,
template<class> class CP1>
SmartPtr& operator =(SmartPtr<T1, SP1, OP1, CP1>& rhs)
{
SmartPtr temp(rhs);
temp.Swap(*this);
return *this;
};
template<class T1,
template<class> class SP1,
template<class> class OP1,
template<class> class CP1>
SmartPtr& operator =(const SmartPtr<T1, SP1, OP1, CP1>& rhs)
{
SmartPtr temp(rhs);
temp.Swap(*this);
return *this;
};
SmartPtr& operator =(CpyArg& rhs)
{
SmartPtr temp(rhs);
temp.Swap(*this);
return *this;
};
void Swap(SmartPtr& other)
{
OP::Swap(other);
SP::Swap(other);
CP::Swap(other);
};
~SmartPtr()
{
if(OP::Release())
SP::Destroy();
};
private:
class Tester
{
void operator delete(void*);
};
public:
operator Tester*()
{
if(GetPtrImpl(*this) == 0)
return 0;
static Tester test;
return &test;
};
template<class T1,
template<class> class SP1,
template<class> class OP1,
template<class> class CP1>
friend void Release(SmartPtr<T1, SP1, OP1, CP1>& des, typename SmartPtr<T1, SP1, OP1, CP1>::StoredType& p);
template<class U>
friend inline bool operator ==(const SmartPtr& lhs, const U* rhs)
{
return GetPtrImpl(lhs) == rhs;
};
template<class U>
friend inline bool operator ==(const U* lhs, const SmartPtr& rhs)
{
return rhs == lhs;
};
friend inline bool operator ==(const SmartPtr& lhs, const T* rhs)
{
return GetPtrImpl(lhs) == rhs;
};
friend inline bool operator ==(const T* lhs, const SmartPtr& rhs)
{
return rhs == lhs;
};
template<class U>
friend inline bool operator !=(const SmartPtr& lhs, const U* rhs)
{
return !(lhs == rhs);
};
template<class U>
friend inline bool operator !=(const U* lhs, const SmartPtr& rhs)
{
return rhs != lhs;
};
friend inline bool operator !=(const SmartPtr& lhs, const T* rhs)
{
return !(lhs == rhs);
};
friend inline bool operator !=(const T* lhs, const SmartPtr& rhs)
{
return rhs != lhs;
};
};
template<class T1,
template<class> class SP1,
template<class> class OP1,
template<class> class CP1>
inline void Release(SmartPtr<T1, SP1, OP1, CP1>& des, typename SmartPtr<T1, SP1, OP1, CP1>::StoredType& p)
{
p = GetPtrImpl(des);
GetPtrRef(des) = SP1<T1>::Default();
};
template<class T1,
template<class> class SP1,
template<class> class OP1,
template<class> class CP1,
class T2,
template<class> class SP2,
template<class> class OP2,
template<class> class CP2>
inline bool operator ==(const SmartPtr<T1, SP1, OP1, CP1>& lhs, const SmartPtr<T2, SP2, OP2, CP2>& rhs)
{
return GetPtrImpl(lhs) == GetPtrImpl(rhs);
};
template<class T1,
template<class> class SP1,
template<class> class OP1,
template<class> class CP1,
class T2,
template<class> class SP2,
template<class> class OP2,
template<class> class CP2>
inline bool operator !=(const SmartPtr<T1, SP1, OP1, CP1>& lhs, const SmartPtr<T2, SP2, OP2, CP2>& rhs)
{
return !(lhs == rhs);
};
}
#endif