Click here to Skip to main content
12,626,216 members (35,339 online)
Click here to Skip to main content

Stats

57.2K views
576 downloads
14 bookmarked
Posted

Clone Smart Pointer (clone_ptr)

, 23 Aug 2005 Public Domain
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.
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) Commvault
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 | :)

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161205.3 | Last Updated 23 Aug 2005
Article Copyright 2005 by Axter
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid