Sign in to follow this  

generic composite

This topic is 4838 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i'm mostly done writting a generic composite that i'll be using quite soon, basically you give it a component type and it generates a composite, its customizable on STL sequence containers where the container will hold boost::shared_ptrs and uses a custom allocator boost::pool_allocator for the container because smart pointers will always be the same size & there small objects it should be faster & more efficent to use a pooled allocator for them, also its parameterized by cloner type with a default cloner that uses boost::object_pool internally but there is another cloner that uses the general memory operators new/delete you can use. There is a add_child method that is templated so every sub-type of component (including composites) will be added, the cloner gets the type parameter from this method and if not already generates a new cloner for a particular sub-type. When pooled_cloner is used it should create an object pool of each sub-type once. Then a smart pointer gets the address & its push'ed into the container. i was wondering if anyone can see an issues with this. There is two i can think of first being is if the component has any pure virtual then the generic composite can't be instantiated directly but its fine just derive from it and define the methods needed. Second issue if pooled_cloner is used and a composite is added as a child it might be better to not use the default behaviour (that is have a template instance of object_pool for actual composites) and use new instead for them.
#include <boost\pool\pool_alloc.hpp>
#include <boost\pool\object_pool.hpp>
#include <boost\smart_ptr.hpp>
#include <list>

template < typename Cloneable >
struct default_cloner {
	
	static Cloneable* create();
	static Cloneable* clone(const Cloneable& c = Cloneable());
	static void destroy(Cloneable* c);

};

template < typename Cloneable >
inline Cloneable* default_cloner<Cloneable>::create() {
	return new Cloneable;
}

template < typename Cloneable >
inline Cloneable* default_cloner<Cloneable>::clone(const Cloneable& c) {
	return new Cloneable(c);
}

template < typename Cloneable >
inline void default_cloner<Cloneable>::destroy(Cloneable* c) {
	delete c;
}

template < typename Cloneable >
class pooled_cloner {
public:

    typedef boost::object_pool<Cloneable> derived_pool_t;

private:
    
	static derived_pool_t derived_pool;

public:

	static Cloneable* create();
	static Cloneable* clone(const Cloneable& c = Cloneable());
	static void destroy(Cloneable* c);

};

template < typename Cloneable >
typename pooled_cloner<Cloneable>::derived_pool_t pooled_cloner<Cloneable>::derived_pool;

template < typename Cloneable >
inline Cloneable* pooled_cloner<Cloneable>::create() {
	return derived_pool.construct();
}

template < typename Cloneable >
inline Cloneable* pooled_cloner<Cloneable>::clone(const Cloneable& c) {
	return derived_pool.construct(c);
}

template < typename Cloneable >
inline void pooled_cloner<Cloneable>::destroy(Cloneable* c) {
	derived_pool.destroy(c);
}

template <

    typename Component,
    template < typename V, typename W > class Container = std::list,
    template < typename Cloneable > class Cloner = pooled_cloner
>
class Composite : public Component {

public:

   typedef Component								value_type;
   typedef value_type&								reference;
   typedef const value_type&						const_reference;
   typedef boost::shared_ptr<Component>				pointer;
   typedef const boost::shared_ptr<Component>		const_pointer;
   typedef boost::pool_allocator<pointer>			allocator;

   typedef Container< pointer, allocator >			container_type;
   typedef typename container_type::iterator		iterator;
   typedef typename container_type::const_iterator	const_iterator;

private:

	template < typename DerviedType >
	struct special_deleter {
		void operator()(DerviedType* p) const {
			Cloner<DerviedType>::destroy(p);
		}
	};

	container_type  _container;

public:
	
	template < typename DerviedType >
	void add_child(const DerviedType& c) {
		pointer p(Cloner<DerviedType>::clone(c), special_deleter<DerviedType>());
		_container.push_back(p);
	};

	void remove_child(iterator pos) {
		_container.erase(pos);
	}

	void remove_child(iterator first, iterator last) {
		_container.erase(beg, end);
	}

	const_iterator get_child(typename container_type::size_type i) const {
		const_iterator itr = begin();
		std::advance(itr, i);
		return itr;
	}

	iterator get_child(typename container_type::size_type i) {
		iterator itr = begin();
		std::advance(itr, i);
		return itr;
	}

	const_iterator begin() const { return _container.begin(); }
	iterator begin() { return _container.begin(); }
	
	const_iterator end() const { return _container.end(); }
	iterator end() { return _container.end(); }

	typename container_type::size_type size() const { return _container.size(); }

	bool empty() const { return _container.empty(); }
};

EDIT: i'll be doing more to it later on, iterator types, reference to parents etc. [Edited by - snk_kid on September 12, 2004 2:35:17 PM]

Share this post


Link to post
Share on other sites

This topic is 4838 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this