Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

Clone Smart Pointer (clone_ptr)

, 22 Aug 2005
A non-sharing smart pointer class that can be used with STL containers like std::map, vector, list, set, and deque. The smart pointer has assignment operator and greater than operator that call the target object's equal operator.
clone_ptr.zip
clone_ptr_demo.zip
ClonePointerDemo
VC60
ClonePointerDemo.dsp.src
ClonePointerDemo.dsw
res
ClonePointerDemo.ico
ClonePointerDemo.dsp
VC71
res
ClonePointerDemo.ico
ClonePointerDemo.dsp
ClonePointerDemo.dsp.src
ClonePointerDemo.dsw
#ifndef clone_ptr_H_HEADER_GUARD_
#define clone_ptr_H_HEADER_GUARD_

/*
// clone_ptr class by David Maisonave (Axter)
// 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 clone_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 clone_ptr, is to make it easier to create
	a container of abstract based objects.
	The clone_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 clone_ptr and other similar smart pointers
	is that the clone_ptr has a clone interface, which is used to create
	a copy of the derived object.  The clone interface is used in
	the clone_ptr copy constructor and in the assignment operator.

	The clone_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://axter.com/lib/

	See example program for example usage.

*/
#include <memory>

template<typename T>
class clone_ptr
{
private:
	class func_ptr_interface
	{
	public:
		typedef T* TP;
		virtual T* construct() = 0;
		virtual void destroy() = 0;
		virtual ~func_ptr_interface(){}
		virtual func_ptr_interface* clone_func_ptr_interface(T* Obj)=0;
	};
	template<typename T_obj, class AX_TYPE = std::allocator<T_obj> >
		class func_ptr_interface_default : public func_ptr_interface
	{
	public:
		func_ptr_interface_default(T_obj* Obj): m_Obj(Obj){}
		T* construct()
		{
			AX_TYPE alloc;
			T_obj* tmp_ptr = alloc.allocate(1, NULL);
			alloc.construct(tmp_ptr, *m_Obj);
			return tmp_ptr;
		}
		func_ptr_interface* clone_func_ptr_interface(T* Obj)
		{
			return new func_ptr_interface_default((T_obj*)Obj);
		}
		void destroy()
		{
			AX_TYPE alloc;
			alloc.destroy(m_Obj);
			alloc.deallocate(m_Obj, 1);
		}
	private:
		T_obj* m_Obj;
	};
	public:
	typedef T* pointer;
	typedef T& reference;
	//Constructor for types having clone() named method
	template<typename T_obj>
		clone_ptr(T_obj* type):m_type(type), m_func_ptr_interface(new func_ptr_interface_default<T_obj, std::allocator<T_obj> >(type)){}
	//Constructor for types having clone() named method
	template<typename T_obj, class AX_TYPE>
		clone_ptr(T_obj* type, const AX_TYPE&):m_type(type), m_func_ptr_interface(new func_ptr_interface_default<T_obj, AX_TYPE>(type)){}
	//Destructor
	~clone_ptr(){m_func_ptr_interface->destroy();m_type=NULL;delete m_func_ptr_interface;}
	//Copy constructor
	clone_ptr(const clone_ptr& Src):m_type(Src.m_func_ptr_interface->construct()), m_func_ptr_interface(Src.m_func_ptr_interface->clone_func_ptr_interface(m_type)){}
	//Assignment operator
	clone_ptr& operator=(const clone_ptr& Src)
	{
		if (&Src != this)
		{
			m_func_ptr_interface->destroy();
			delete m_func_ptr_interface;
			m_type = Src.m_func_ptr_interface->construct();
			m_func_ptr_interface = Src.m_func_ptr_interface->clone_func_ptr_interface(m_type);
		}
		return *this;
	}
#if !defined(_MSC_VER) || (_MSC_VER > 1200)
	template<typename CompatibleT>
		clone_ptr& operator=(const clone_ptr<CompatibleT>& Src)
	{
		if (Src.get_ptr() != m_type)
		{
			m_func_ptr_interface->destroy();
			delete m_func_ptr_interface;
			CompatibleT* Tmp_ptr = Src.m_func_ptr_interface->construct();
			m_type = Tmp_ptr;
			m_func_ptr_interface = new func_ptr_interface_default<CompatibleT>(Tmp_ptr);
		}
		return *this;
	}
#endif //_MSC_VER != 1200
	bool operator! () const
	{
		return m_type == 0;
	}
	template<typename T2>
		clone_ptr& equal(const T2& Src){
		(*m_type) = (Src);
		return *this;
	}
	T* operator->() const{return m_type;}
	T& operator*() const{return *m_type;}
	//Consider changing the follow operators to template methods
	clone_ptr& operator+=(const clone_ptr& Src){
		m_type->operator+=(*Src.m_type);
		return *this;
	}
	template<typename T2>
		clone_ptr& operator+=(const T2& Src){
		m_type->operator+=(Src);
		return *this;
	}
	clone_ptr& operator+(const clone_ptr& Src){
		m_type->operator+(*Src.m_type);
		return *this;
	}
	clone_ptr& operator-=(const clone_ptr& Src){
		m_type->operator-=(*Src.m_type);
		return *this;
	}
	clone_ptr& operator-(const clone_ptr& Src){
		m_type->operator-(*Src.m_type);
		return *this;
	}
	T* get_ptr()const{return m_type;}
	//Other Misc methods
    void swap(clone_ptr<T> & other){std::swap(m_type, other.m_type);std::swap(m_func_ptr_interface, other.m_func_ptr_interface);}
private:
	T* m_type;
public:
	func_ptr_interface *m_func_ptr_interface;
};

template<class T, class U> inline bool operator<(clone_ptr<T> const & a, clone_ptr<U> const & b){return (*a.get_ptr()) < (*b.get_ptr());}
template<class T, class U> inline bool operator>(clone_ptr<T> const & a, clone_ptr<U> const & b){return (*a.get_ptr()) > (*b.get_ptr());}
template<class T, class U> inline bool operator<=(clone_ptr<T> const & a, clone_ptr<U> const & b){return (*a.get_ptr()) <= (*b.get_ptr());}
template<class T, class U> inline bool operator>=(clone_ptr<T> const & a, clone_ptr<U> const & b){return (*a.get_ptr()) >= (*b.get_ptr());}
template<class T, class U> inline bool operator==(clone_ptr<T> const & a, clone_ptr<U> const & b){return (*a.get_ptr()) == (*b.get_ptr());}
template<class T, class U> inline bool operator!=(clone_ptr<T> const & a, clone_ptr<U> const & b){return (*a.get_ptr()) != (*b.get_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!=(clone_ptr<T> const & a, clone_ptr<T> const & b){return (*a.get_ptr()) != (*b.get_ptr());}
#endif

#endif //!clone_ptr_H_HEADER_GUARD_

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

Share

About the Author

Axter
Software Developer (Senior)
United States United States
I started programming as a hobby in 1985 on my 8-bit Atari computer. I programmed in BASIC and in assembly language until I upgraded to a 16-bit IBM compatible in 1988.
In 1989, I started programming in C using Turbo C++. IMHO, Turbo C/C++ was the best compiler available to the market for many years, until VC++ 4.0 came out.
I started using MFC with VC++ 4.0 in 1996, and I developed and sold an application called GameMenu95. It had limited success, and I retired the program in 1999.
 
I now perform contract work in a variety of operating systems mostly using C/C++.
I occasionally have contract work for Java applications and MS Access development.
 
My favorite language of choice is C++. I believe it has the best combination of flexibility, speed, and type safety.
I’ve used many compilers and IDE, to include (VC++7.0, 7.1, 6.0, GCC 2.x, 3.x, Turbo C/C++, Borland 5.x, Watcom, MinGW, DevC++, Eclipse….)
However, by far, my most favorite IDE is VC++6.0. Although this compiler has poor C++ compliance, it more then makes up for it by its outstanding interface and tools.
 
Coding is still my hobby, and I’m very fortunate in that I get paid good money to engage in my hobby!
 
Life is good!!! Smile | :)
 

If I really helped you save some bucks, I would like to ask you for something: Please donate some of these saved bucks (you decide) to the charity organization of your choice - or just help out somebody who is needier than you are......
Pass it on....... Smile | :)

| Advertise | Privacy | Mobile
Web04 | 2.8.140926.1 | Last Updated 23 Aug 2005
Article Copyright 2005 by Axter
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid