Click here to Skip to main content
15,886,873 members
Articles / Programming Languages / C++

generic_ptr and Its Generator

Rate me:
Please Sign up or sign in to vote.
4.29/5 (4 votes)
9 Mar 2010CPOL5 min read 17.3K   113   9  
Generic object wrapper for delayed type selection
#ifndef MSH_UTILITY_GENERIC_PTR_H
#define MSH_UTILITY_GENERIC_PTR_H

///	<file name="generic_ptr.h">
///	<purpose>Defines generic_ptr and its generator.</purpose>
///	<author>msh</author>
///	<revisions>
///	<revision name="msh" date="2010/03/01">
///	First proposition.
///	</revision>
///	</revisions>

#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/rest_n.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/enum.hpp>

#include <boost/preprocessor/punctuation/paren.hpp>
#include <boost/preprocessor/comparison/greater.hpp>
#include <boost/preprocessor/enum_params.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/if.hpp>
#include <boost/preprocessor/empty.hpp>
#include <boost/preprocessor/comma_if.hpp>

#include <boost/shared_ptr.hpp>


//////////////////////////////////////////////////////////////////////////
// GENERAL

#define GEN_PARAMS_NONE()()
#define GEN_PARAMS(seq)(seq)
#define GEN_TYPE(type)((0)(type))
#define GEN_DEPEND_TYPE(type)((1)(type))

#define GEN_RET_NONE() ((0)(void))
#define GEN_RET_TYPE(type) ((1)(type))
#define GEN_RET_DEPEND_TYPE() ((1)(boost::any))

#define GEN_NAME(name) (name)

#define GEN_TRAILING_CONST() (const)

#define GEN_THROW_NONE() (throw())
#define GEN_THROW_OF(exc_type) (throw(exc_type))

#define GEN_METHOD_SIG(sig) (sig)

#define GEN_EMPTY_1(x) BOOST_PP_EMPTY()
#define GEN_EMPTY_2(x,y) BOOST_PP_EMPTY()
#define GEN_EMPTY_3(x,y,z) BOOST_PP_EMPTY()
#define GEN_EMPTY_4(x,y,z,t) BOOST_PP_EMPTY()

#define GEN_SELF(r,data,i,elem) elem

//////////////////////////////////////////////////////////////////////////
// CUSTOM

#define GEN_RET_COND_0 
#define GEN_RET_COND_1 return

#define GEN_PARAM_TYPE_0(type) type
#define GEN_PARAM_TYPE_1(type) boost::any

#define GEN_BODY_PARAM_TYPE_0(type,param) param
#define GEN_BODY_PARAM_TYPE_1(type,param) boost::any_cast<type>(param)

//////////////////////////////////////////////////////////////////////////
// INTERFACE

#define GEN_ADD_INTERFACE_PARAM(r,data,i,seq)\
	BOOST_PP_CAT(GEN_PARAM_TYPE_,BOOST_PP_SEQ_ELEM(0,seq))(BOOST_PP_SEQ_ELEM(1,seq))\
	BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(BOOST_PP_DEC(data),i))

#define GEN_CREATE_INTERFACE_PARAMS(seq)\
	BOOST_PP_SEQ_FOR_EACH_I(GEN_ADD_INTERFACE_PARAM,BOOST_PP_SEQ_SIZE(seq),seq)

#define GEN_CREATE_INTERFACE_METHOD(r,data,seq) \
	virtual BOOST_PP_SEQ_ELEM(1,BOOST_PP_SEQ_ELEM(0,seq))BOOST_PP_SEQ_ELEM(1,seq)\
	BOOST_PP_LPAREN()\
	BOOST_PP_IF(BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_ELEM(2,seq)),GEN_CREATE_INTERFACE_PARAMS,GEN_EMPTY_1)(BOOST_PP_SEQ_ELEM(2,seq))\
	BOOST_PP_RPAREN()\
	BOOST_PP_SEQ_FOR_EACH_I(GEN_SELF,~,BOOST_PP_SEQ_REST_N(3,seq))\
	= 0;

#define GEN_CREATE_GENERIC_INTERFACE(seq) \
class BOOST_PP_CAT(i_generic_,BOOST_PP_SEQ_HEAD(seq))\
  {\
  public:\
  virtual ~BOOST_PP_CAT(i_generic_,BOOST_PP_SEQ_HEAD(seq))(){}\
  BOOST_PP_SEQ_FOR_EACH(GEN_CREATE_INTERFACE_METHOD,~,BOOST_PP_SEQ_TAIL(seq)) \
  };

//////////////////////////////////////////////////////////////////////////
// IMPL

#define GEN_ADD_IMPL_PARAM(r,data,i,seq)\
	BOOST_PP_CAT(GEN_PARAM_TYPE_,BOOST_PP_SEQ_ELEM(0,seq))(BOOST_PP_SEQ_ELEM(1,seq))\
	BOOST_PP_CAT(_param_,i)BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(BOOST_PP_DEC(data),i))

#define GEN_CREATE_IMPL_PARAMS(seq)\
	BOOST_PP_SEQ_FOR_EACH_I(GEN_ADD_IMPL_PARAM,BOOST_PP_SEQ_SIZE(seq),seq)

#define GEN_ADD_BODY_PARAM(r,data,i,seq)\
	BOOST_PP_CAT(GEN_BODY_PARAM_TYPE_,BOOST_PP_SEQ_ELEM(0,seq))(BOOST_PP_SEQ_ELEM(1,seq),BOOST_PP_CAT(_param_,i))\
	BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(BOOST_PP_DEC(data),i))

#define GEN_CREATE_BODY_PARAMS(seq)\
	BOOST_PP_SEQ_FOR_EACH_I(GEN_ADD_BODY_PARAM,BOOST_PP_SEQ_SIZE(seq),seq)

#define GEN_CREATE_IMPL_METHOD(r,data,seq)\
	BOOST_PP_SEQ_ELEM(1,BOOST_PP_SEQ_ELEM(0,seq))BOOST_PP_SEQ_ELEM(1,seq)\
	BOOST_PP_LPAREN()\
	GEN_CREATE_IMPL_PARAMS(BOOST_PP_SEQ_ELEM(2,seq))\
	BOOST_PP_RPAREN()\
	BOOST_PP_SEQ_FOR_EACH_I(GEN_SELF,~,BOOST_PP_SEQ_REST_N(3,seq))\
		{\
		BOOST_PP_CAT(GEN_RET_COND_,BOOST_PP_SEQ_ELEM(0,BOOST_PP_SEQ_ELEM(0,seq)))\
		m_obj_sp->BOOST_PP_SEQ_ELEM(1,seq)\
		BOOST_PP_LPAREN()\
		GEN_CREATE_BODY_PARAMS(BOOST_PP_SEQ_ELEM(2,seq))\
		BOOST_PP_RPAREN();\
		}

#define GEN_CREATE_GENERIC_INTERFACE_IMPL(seq)\
	template<typename T>\
class BOOST_PP_CAT(generic_,BOOST_PP_CAT(BOOST_PP_SEQ_HEAD(seq),_impl)) \
	: public BOOST_PP_CAT(i_generic_,BOOST_PP_SEQ_HEAD(seq))\
	{\
	public: \
	BOOST_PP_CAT(generic_,BOOST_PP_CAT(BOOST_PP_SEQ_HEAD(seq),_impl))(boost::shared_ptr<T> _obj_sp): m_obj_sp(_obj_sp){} \
	BOOST_PP_SEQ_FOR_EACH(GEN_CREATE_IMPL_METHOD,~,BOOST_PP_SEQ_TAIL(seq)) \
	private: \
	boost::shared_ptr<T> m_obj_sp; \
	};

namespace msh {namespace utility {

	template<typename interface_t, template <typename> class handler_t>
	class generic_ptr
	{
		typedef boost::shared_ptr<interface_t>interface_sp_t;
	public:
		generic_ptr(){}

		template<typename obj_t>
		generic_ptr(boost::shared_ptr<obj_t> _obj_sp)
		{
			m_obj_sp.reset(new handler_t<obj_t>(_obj_sp));
		}

		template<typename obj_t>
		generic_ptr & operator=( boost::shared_ptr<obj_t> _obj_sp )
		{
			m_obj_sp.reset(new handler_t<obj_t>(_obj_sp));
			return *this;
		}

		template<typename obj_t>
		void reset(boost::shared_ptr<obj_t> _obj_sp)
		{
			m_obj_sp.reset(new handler_t<obj_t>(_obj_sp));
		}

		interface_t* operator->()const{return m_obj_sp.get();}

		void swap( generic_ptr const & r )
		{
			m_obj_sp.swap(r.m_obj_sp);
		}

	private:
		interface_sp_t m_obj_sp;
	};

}}

#define GEN_CREATE_GENERIC_PTR(seq)\
	namespace msh {namespace utility {\
	typedef generic_ptr<BOOST_PP_CAT(i_generic_,BOOST_PP_SEQ_HEAD(seq))BOOST_PP_COMMA()BOOST_PP_CAT(generic_,BOOST_PP_CAT(BOOST_PP_SEQ_HEAD(seq),_impl))>\
	BOOST_PP_CAT(generic_,BOOST_PP_CAT(BOOST_PP_SEQ_HEAD(seq),_ptr_t));\
}}

#define GENERIC_PTR(seq) \
	namespace \
{\
	GEN_CREATE_GENERIC_INTERFACE(seq)\
	GEN_CREATE_GENERIC_INTERFACE_IMPL(seq)\
}\
	GEN_CREATE_GENERIC_PTR(seq)


namespace msh_utils = msh::utility;



#endif // MSH_UTILITY_GENERIC_INTERFACE_H

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 The Code Project Open License (CPOL)


Written By
Software Developer Metus Technology
Turkey Turkey
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions