/*/////////////////////////////////////////////////////////////////////
License....: LGPL 2.1 - http://www.gnu.org/copyleft/lesser.html
                        http://www.opensource.org/licenses/lgpl-license.php
Name.......: anything 0.1
Description: A generic or variant ( as opposed to templated ) data type.
             A anyimpl<castTrait> is a type that can hold any other type including itself.
			 It is optimized for two special cases, one beeing char arrays that
			 form string iterals in C++ that are beeing interpreted as std::strings
			 and the other beeing map<anyimpl<castTrait>,anyimpl<castTrait>>, for which the [] operator
			 is supported from the anyimpl<castTrait>.
  Copyright (C) 2003 Florian Bösch, http://www.codeweld.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
  This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
  You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  ////////////////////////////////////////////////////////////////////////
Sucessfull Compilerlist for version 0.1.1:
-gcc version 2.95.3 20010315 (release)
-gcc version 2.95.3-5 (cygwin special)
-Microsoft (R) 32-Bit C/C++-Standardcompiler Version 13.00.9466 für 80x86
 ( with one expetions, templated casts don't work )
  Caveats:
-Beware that anythings use references internaly unless you clone one explicitly
-No testing whatsoever has been made for threaded envoirments
-There are surely many cases where using anythings isn't apropriate
 I consider the advantages/disadvantages as the following
 +flexibilty
 +type testing
 -speed
 -safety
-type mismatches produced with as<type>() are resolved depending on the cast traits of the anyimpl.
-anythings are very strict and non converting
  Latest fixes:
-Fixed an internal reference copy issue ( one instance too many )
  ///////////////////////////////////////////////////////////////////////*/
#ifndef ANYTHING_H
#define ANYTHING_H
  #include <map>
#include <string>
#include <vector>
#include <assert.h>
#include <exception>
#include <typeinfo>
namespace nAnything
{
	using namespace std;
	template <class _T> class shared_ptr
	{
	public:
		shared_ptr():_valPtr(new _value()){}
		shared_ptr( _T* t ):_valPtr( new _value(t) ){}
		shared_ptr( const shared_ptr<_T>& sPtr ):_valPtr(sPtr.ref()){}
		~shared_ptr(){ unref(); }
  		_T& operator*() const { return (*_valPtr->get()); }
		_T* operator->() const { return _valPtr->get(); }
		shared_ptr<_T>& operator=( _T* t ){ unref(); _valPtr = new _value(t); return *this; }
		shared_ptr<_T>& operator=( const shared_ptr<_T>& b ){ unref(); _valPtr=b.ref(); return *this;}
		_T* ptr() const { if( _valPtr )return _valPtr->get(); return 0; }
	private:
		class _value
		{
		public:
			_value():references(1),__dataPtr(0){}
			_value( _T* t ):references(1),__dataPtr(t){}
			~_value(){ delete __dataPtr; }
			
			_T* get()
			{
				if( __dataPtr )
					return __dataPtr;
				return (__dataPtr = new _T());
			}
			_value* ref(){ ++references; return this; }
			int unref(){ return --references; }
		private:
			int references;
			_T* __dataPtr;
		};
		void unref(){ if( _valPtr && !_valPtr->unref() ) delete _valPtr; }
		_value* ref() const { if( _valPtr ) return _valPtr->ref(); return 0; }
		_value* _valPtr;
	};
  	template <class _T>
	class anytype;
  	template <class castTrait>
	class anyimpl;
  	class anyinter
	{
	public:
		virtual anyinter* clone() const{ return new anyinter; }
		virtual int type() const { return 0; }
		virtual anyinter& operator=( const anyinter& b ){ return *this; }
		virtual ~anyinter(){}
		virtual bool operator==( const anyinter& b ){ return true; }
		virtual bool operator<( const anyinter& b ){ return true; }
	};
  	template <class _T>
	class anytype: public anyinter
	{
		typedef anytype<_T> _myType;
	public:
		anytype():data(_T()){}
		anytype( const _T& d ):data(d){}
		virtual anyinter* clone() const{ return new anytype<_T>( data ); }
		virtual int type() const{ return _myType::id; }
		virtual bool operator==( const anyinter& b )
		{
			return data==reinterpret_cast<const _myType&>(b).data;
		}
		virtual bool operator<( const anyinter& b )
		{
			return data < reinterpret_cast<const _myType&>(b).data;
		}
		virtual anyinter& operator=( const anyinter& b )
		{
			data = reinterpret_cast<const _myType&>(b).data;
			return *this;
		}
		_T data;
		static const int id;
	};
  	template <class _T>
	const int anytype<_T>::id = reinterpret_cast<const int>(&anytype<_T>::id);
  	struct replace_cast_traits
	{
		template <class T>
		T& as( shared_ptr<anyinter>& any )
		{
			if( any.ptr() )
			{
				if( any->type() != anytype<T>::id )
				{
					any = new anytype<T>();
				}
			}
			else
			{
				any = new anytype<T>();
			}
			return reinterpret_cast<anytype<T>*>(any.ptr())->data;
		}
  		template <class T>
		T& as( shared_ptr<anyinter>& any, const T& arg )
		{
			if( any.ptr() )
			{
				if( any->type() != anytype<T>::id )
				{
					any = new anytype<T>(arg);
				}
			}
			else
			{
				any = new anytype<T>(arg);
			}
			return reinterpret_cast<anytype<T>*>(any.ptr())->data;
		}
	};
  	/*   // what's the compiler switch to turn gcc exeptions on???
	struct any_bad_cast
	{
	};
	
	struct throw_cast_traits
	{
		template <class T>
		T& as( shared_ptr<anyinter>& any )
		{
			if( any.ptr() )
			{
				if( any->type() != anytype<T>::id )
				{
					throw( any_bad_cast() );
				}
			}
			else
			{
				any = new anytype<T>();
			}
			return reinterpret_cast<anytype<T>*>(any.ptr())->data;
		}
  		template <class T>
		T& as( shared_ptr<anyinter>& any, const T& arg )
		{
			if( any.ptr() )
			{
				if( any->type() != anytype<T>::id )
				{
					throw( any_bad_cast() );
				}
			}
			else
			{
				any = new anytype<T>(arg);
			}
			return reinterpret_cast<anytype<T>*>(any.ptr())->data;
		}
	};
	*/
	struct assert_cast_traits
	{
		template <class T>
		T& as( shared_ptr<anyinter>& any )
		{
			if( any.ptr() )
			{
				if( any->type() != anytype<T>::id )
				{
					assert(0);
				}
			}
			else
			{
				any = new anytype<T>();
			}
			return reinterpret_cast<anytype<T>*>(any.ptr())->data;
		}
  		template <class T>
		T& as( shared_ptr<anyinter>& any, const T& arg )
		{
			if( any.ptr() )
			{
				if( any->type() != anytype<T>::id )
				{
					assert(0);
				}
			}
			else
			{
				any = new anytype<T>(arg);
			}
			return reinterpret_cast<anytype<T>*>(any.ptr())->data;
		}
	};
  	template <class castTrait>
	class anyimpl
	{
		typedef map<anyimpl<castTrait>,anyimpl<castTrait> > anymap;
		typedef vector<anyimpl<castTrait> > anyvec;
	public:
		anyimpl(){}
		anyimpl( const anyimpl<castTrait>& b ):any(b.any){}
		template <class T>
		anyimpl( const T& arg ):any( new anytype<T>(arg) ){}
		anyimpl( const char* arg):any( new anytype<string>(arg) ){}
		anyimpl( anyinter* a ):any(a){}
  		anyimpl<castTrait>& operator=( anyimpl<castTrait> arg )
		{
			if( type() == arg.type() )
				*any=*arg.any;
			else
				any = arg.any;
			return *this;
		}
  		// doesn't work on M$C
		template <class T>
		operator T(){ return as<T>(); }
  		template <class T>
		T& as( const T& arg )
		{
			return cast.as<T>(any,arg);
		}
  		template <class T>
		T& as()
		{
			return cast.as<T>( any );
		}
		 
		template <class T>
		bool get( T& t )
		{
			if( is<T>() )
			{
				t = as<T>();
				return true;
			}
			return false;
		}
  		template <class T>
		T* get()
		{
			if( is<T>() )
			{
				return &as<T>();
			}
			return 0;
		}
		 
		anyimpl<castTrait>& operator[]( anyimpl<castTrait> i )
		{
			return as<anymap>()[i];
		}
	
  		int type() const { if( any.ptr() ) return any->type(); return 0; }
		
		template <class T>
		bool is() const
		{
			if( any.ptr() )
				return anytype<T>::id == any->type();
			return false;
		}
  		anyimpl<castTrait> clone(){ return anyimpl<castTrait>( any->clone() ); }
  
		bool operator<( const anyimpl<castTrait>& b ) const
		{
			if( !any.ptr() && b.any.ptr() ) return true;
			if( any.ptr() && !b.any.ptr() ) return false;
			if( !any.ptr() || !b.any.ptr() ) return false;
			if( any->type() != b.any->type() ) return any->type() < b.any->type();
			return *any<*b.any;
		}
		
		bool operator==( const anyimpl<castTrait>& b ) const
		{
			if( !any.ptr() && !b.any.ptr() )return true;
			if( !any.ptr() || !b.any.ptr() ) return false;
			if( any->type() != b.any->type() ) return false;
			return *any==*b.any;
		}
		
	protected:
		shared_ptr<anyinter> any;
		castTrait cast;
	};
		
	template <class castTrait>
	bool operator==( const anyimpl<castTrait>& a, const anyimpl<castTrait>& b )
	{
		return a.operator==(b);
	}
  	template <class castTrait>
	bool operator!=( const anyimpl<castTrait>& a, const anyimpl<castTrait>& b )
	{
		return !(a.operator==(b));
	}
	template <class castTrait>
	bool operator<( const anyimpl<castTrait>& a, const anyimpl<castTrait>& b )
	{
		return a.operator<(b);
	}
  	template <class _T>
	class anyis
	{
	public:
  		template <class castTrait>
		bool operator()( const anyimpl<castTrait>& a )
		{
			return a.type() == anytype<_T>::id;
		}
	};
  	template <class _T>
	class anyisnot
	{
	public:
  		template <class castTrait>
		bool operator()( const anyimpl<castTrait>& a )
		{
			return a.type() != anytype<_T>::id;
		}
	};
  	typedef anyimpl<replace_cast_traits> anything;
//	typedef anyimpl<throw_cast_traits> throwany; // what's the compiler switch to turn gcc exeptions on???
	typedef anyimpl<assert_cast_traits> assertany;
  }//nAnything
#endif // ANYTHING_H  |