⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 copy_ptr.hpp

📁 比STL和BOOST更强大的智能指针库!!! 私藏很久的老底与大家一起分享了.
💻 HPP
字号:
#ifndef copy_ptr_H_HEADER_GUARD_
#define copy_ptr_H_HEADER_GUARD_

/*
// copy_ptr class by David Maisonave (Axter) and Kai-Uwe Bux
// Copyright (C) 2005
// David Maisonave (Axter) (609-345-1007) (www.axter.com)
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation.  David Maisonave (Axter) makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
Description:
The copy_ptr class is a smart pointer class that can be used
with an STL container to create a container of smart pointers.
The main purpose of the copy_ptr, is to make it easier to create
a container of abstract based objects.
The copy_ptr does not share it's pointer, nor does it move it's pointer,
and moreover, it's based on the idea of strict pointer ownership logic.
The main difference between copy_ptr and other similar smart pointers
is that the copy_ptr has a clone function pointer, which is used to create
a copy of the derived object.  The clone function pointer is used in
the copy_ptr copy constructor and in the assignment operator.

The copy_ptr can also be used with sorted containers (std::map, std::set).
When used with sorted containers, the base class must have an operator<() function. (See example code.)

****** For more detailed description and example usage see following links: *******
Example Program:
http://code.axter.com/clone_ptr_demo.zip
Detail description:
http://www.codeguru.com/Cpp/Cpp/algorithms/general/article.php/c10407

See example program for example usage.

*/

template < typename T, typename DT> T *  copy_ptr_ConstructAndDestruct_default_allocator_(const T*, bool, DT* , void*);
template < typename T, typename D, class AX_TYPE> T *  copy_ptr_ConstructAndDestruct_(const T* , bool, D* , AX_TYPE*);

/*! @class copy_ptr
@brief copy_ptr is a deep copy (Clone) smart pointer
that does not require the pointee to have clone function
logic.
*/
template<typename T>
class copy_ptr
{
	typedef T * ( *clone_fct_Type ) (const T *, bool, void*, void*);//Last two values are not used (See note#1 at end of file)
	T* m_type;
	clone_fct_Type m_clone_fct;
public:
	template<typename T_obj>
		static	clone_fct_Type get_alloc_func(T_obj*)
	{
		T * ( *tmp ) (const T *, bool, T_obj*, void*) = copy_ptr_ConstructAndDestruct_default_allocator_<T,T_obj>;
		return (clone_fct_Type)tmp;
	}
	//copy_ptr will only clone type that is pass to the constructor
	template<typename T_obj>
	copy_ptr(T_obj* type):m_type(type), m_clone_fct(get_alloc_func(type))
	{
#ifdef BOOST_ASSERT
		BOOST_ASSERT(type != NULL);
		BOOST_ASSERT(typeid(*type) == typeid(T_obj));
#endif //BOOST_ASSERT
	}
	template<typename T_obj, class AX_TYPE>
	copy_ptr(T_obj* type, AX_TYPE&):m_type(type), m_clone_fct(NULL)
	{
#ifdef BOOST_ASSERT
		BOOST_ASSERT(type != NULL);
		BOOST_ASSERT(typeid(*type) == typeid(T_obj));
#endif //BOOST_ASSERT
		T * ( *tmp ) ( const T *, bool, T_obj*, AX_TYPE*) = copy_ptr_ConstructAndDestruct_<T,T_obj, AX_TYPE>;
		m_clone_fct = (clone_fct_Type)tmp;
	}
	//Destructor
	~copy_ptr()throw(){if (m_type) m_type=m_clone_fct(m_type, false, NULL, NULL);}
	//Copy constructor
	copy_ptr(const copy_ptr& Src):m_type((Src.m_type)?Src.m_clone_fct(Src.m_type, true, NULL, NULL):NULL), m_clone_fct(Src.m_clone_fct){}
#if !defined(_MSC_VER) || (_MSC_VER > 1200)
	//Constructor for derived type copy_ptr<deriveT>
	template<class CompatibleDerivedT>	copy_ptr(const copy_ptr<CompatibleDerivedT>& Src):m_type(NULL), m_clone_fct(NULL){assign(Src);}
	//Constructor for cow_ptr or other compatible smart pointers
	template<class CompatibleSmartPtr>	copy_ptr(const CompatibleSmartPtr& Src):m_type(NULL), m_clone_fct(NULL){Src.make_clone(m_type, m_clone_fct);}
#else
#ifdef cow_ptr_H_HEADER_GUARD_
	copy_ptr(const cow_ptr<T>& Src):m_type(NULL), m_clone_fct(NULL){Src.make_clone(m_type, m_clone_fct);}
#endif //cow_ptr_H_HEADER_GUARD_
#endif //_MSC_VER != 1200
	//Assignment operator
	copy_ptr& operator=(const copy_ptr& Src){return assign(Src);}
	enum implement_default_object{eYes, eNo};
	//Default constructor needed for std::map
	copy_ptr(implement_default_object use_default_obj = eYes):m_type(NULL), m_clone_fct(NULL)
	{
		if (use_default_obj == eYes)
		{
			copy_ptr<T> &defaultObj = GetSetDefaultObject();
			if (defaultObj.m_type)
			{
				m_type = defaultObj.m_clone_fct(defaultObj.m_type, true, NULL, NULL);
				m_clone_fct = defaultObj.m_clone_fct;
			}
		}
	}
	//For added safety, call SetDefaultObject to set default object before
	//using this class as the second type in a std::map
	static void SetDefaultObject(const copy_ptr<T>& NewValue){GetSetDefaultObject(&NewValue);}
#if !defined(_MSC_VER) || (_MSC_VER > 1200)
	//Assignment operator for smart pointer derived type copy_ptr<DerivedT>
	template<class CompatibleDerivedT>	copy_ptr& operator=(const copy_ptr<CompatibleDerivedT>& Src){return assign(Src);}
#endif //_MSC_VER != 1200
	typedef T* pointer;
	typedef T& reference;
	bool operator! () const{
		return m_type == 0;
	}
	template<typename T2>
	copy_ptr& equal(const T2& Src){
		(*m_type) = (Src);
		return *this;
	}
	inline T* operator->() const{return m_type;}
	inline T& operator*() const{return *m_type;}

	copy_ptr& operator+=(const copy_ptr& Src){
		m_type->operator+=(*Src.m_type);
		return *this;
	}
	template<typename T2>
	copy_ptr& operator+=(const T2& Src){
		m_type->operator+=(Src);
		return *this;
	}
	copy_ptr& operator+(const copy_ptr& Src){
		m_type->operator+(*Src.m_type);
		return *this;
	}
	copy_ptr& operator-=(const copy_ptr& Src){
		m_type->operator-=(*Src.m_type);
		return *this;
	}
	copy_ptr& operator-(const copy_ptr& Src){
		m_type->operator-(*Src.m_type);
		return *this;
	}
	const T* c_ptr()const{return  m_type;}
	const T& c_ref()const{return  *m_type;}
	T* get_ptr(){return m_type;}
	//Other Misc methods
	void swap(copy_ptr<T> & other)throw(){std::swap(m_type, other.m_type);std::swap(m_clone_fct, other.m_clone_fct);}

	//get_function_ptr needed for operator=(const copy_ptr<CompatibleDerivedT>&
	clone_fct_Type get_function_ptr()const{return m_clone_fct;}
private:
	template<class CompatibleSmartPtr>
		copy_ptr& assign(CompatibleSmartPtr& Src)
	{
		if (m_type != (T*)Src.c_ptr()) //Cast needed for Borland compiler
		{
			if (m_type) m_clone_fct(m_type, false, NULL, NULL);
			if (Src.c_ptr())
				m_type = Src.get_function_ptr()(Src.c_ptr(), true, NULL, NULL);
			else m_type = NULL;
			m_clone_fct = (clone_fct_Type)Src.get_function_ptr();
		}
		return *this;
	}

	static copy_ptr<T>& GetSetDefaultObject(const copy_ptr<T>* NewValue = NULL)
	{
		static copy_ptr<T> DefaultObj(eNo);
		if (NewValue && NewValue->m_type)
			DefaultObj = *NewValue;
		return DefaultObj;
	}
};

template<class T, class U> inline bool operator<(copy_ptr<T> const & a, copy_ptr<U> const & b){return (*a.c_ptr()) < (*b.c_ptr());}
template<class T, class U> inline bool operator>(copy_ptr<T> const & a, copy_ptr<U> const & b){return (*a.c_ptr()) > (*b.c_ptr());}
template<class T, class U> inline bool operator<=(copy_ptr<T> const & a, copy_ptr<U> const & b){return (*a.c_ptr()) <= (*b.c_ptr());}
template<class T, class U> inline bool operator>=(copy_ptr<T> const & a, copy_ptr<U> const & b){return (*a.c_ptr()) >= (*b.c_ptr());}
template<class T, class U> inline bool operator==(copy_ptr<T> const & a, copy_ptr<U> const & b){return (*a.c_ptr()) == (*b.c_ptr());}
template<class T, class U> inline bool operator!=(copy_ptr<T> const & a, copy_ptr<U> const & b){return (*a.c_ptr()) != (*b.c_ptr());}

#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
// Resolve the ambiguity between our op!= and the one in rel_ops
template<class T> inline bool operator!=(copy_ptr<T> const & a, copy_ptr<T> const & b){return (*a.c_ptr()) != (*b.c_ptr());}
#endif

/*
Note#1:
The ConstructAndDestruct functions have two extra arguments that are not used.  These arguments are not required at all in more compliant compilers
like VC++ 7.x and GNU 3.x.  However, for none compliant (pre-standard) compilers like VC++ 6.0 and BCC55, the extra argument declaration is required
so as to be able to fully qualify the function template type.  The argument declarations are needed for these compilers, but the actual argument variables
are not needed.  Anything pass to these last two arguments will be discarded.
*/

// The clone function: (Thanks to Kai-Uwe Bux)
template < typename T, typename DT> T *  copy_ptr_ConstructAndDestruct_default_allocator_(const T *  ptr, bool bConstruct, DT* , void*) {
	if (bConstruct)
	{
		DT* d = new DT(*static_cast<const DT*>(ptr));
#ifdef BOOST_ASSERT
		BOOST_ASSERT(typeid(*static_cast<const DT*>(ptr)) == typeid(*d));
#endif //BOOST_ASSERT
		return d;
	}
#if !defined(_MSC_VER) || (_MSC_VER > 1200)
	delete ptr;
#else
	delete const_cast<T*>(ptr); //For VC++ 6.0 bug which doesn't allow deletion of constant pointer
#endif
	return NULL;
} 

template < typename T, typename D, class AX_TYPE> T *  copy_ptr_ConstructAndDestruct_(const T *  ptr, bool bConstruct, D* , AX_TYPE*) {
	D * Obj = static_cast<D*>( ptr );
	if (bConstruct)
	{
		AX_TYPE alloc;
		D* tmp_ptr = alloc.allocate(1, NULL);
		alloc.construct(tmp_ptr, *(Obj));
#ifdef BOOST_ASSERT
		BOOST_ASSERT(typeid(*tmp_ptr) == typeid(*Obj));
#endif //BOOST_ASSERT
		return tmp_ptr;
	}
	AX_TYPE alloc;
	alloc.destroy(Obj);
	alloc.deallocate(Obj, 1);
	return NULL;
} 


#endif //!copy_ptr_H_HEADER_GUARD_

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -