$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r54527 - in sandbox/monotonic: boost/heterogenous boost/heterogenous/detail libs/monotonic/test/clones
From: christian.schladetsch_at_[hidden]
Date: 2009-06-30 05:05:09
Author: cschladetsch
Date: 2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
New Revision: 54527
URL: http://svn.boost.org/trac/boost/changeset/54527
Log:
made multiple inheritance work
Text files modified: 
   sandbox/monotonic/boost/heterogenous/abstract_cloneable.hpp   |    37 ++++++++++++++++++++------              
   sandbox/monotonic/boost/heterogenous/adaptor.hpp              |     4 +-                                      
   sandbox/monotonic/boost/heterogenous/allocator.hpp            |     4 +-                                      
   sandbox/monotonic/boost/heterogenous/cloneable.hpp            |    33 +++++++++++++----------                 
   sandbox/monotonic/boost/heterogenous/detail/allocation.hpp    |    52 ++++++++++++++++++++++++++++++++-----   
   sandbox/monotonic/boost/heterogenous/forward_declarations.hpp |     8 ++--                                    
   sandbox/monotonic/boost/heterogenous/map.hpp                  |    19 +++++++------                           
   sandbox/monotonic/boost/heterogenous/vector.hpp               |    15 ++++++----                              
   sandbox/monotonic/libs/monotonic/test/clones/tests.cpp        |    55 ++++++++++++++++++++++++++++++++------- 
   9 files changed, 163 insertions(+), 64 deletions(-)
Modified: sandbox/monotonic/boost/heterogenous/abstract_cloneable.hpp
==============================================================================
--- sandbox/monotonic/boost/heterogenous/abstract_cloneable.hpp	(original)
+++ sandbox/monotonic/boost/heterogenous/abstract_cloneable.hpp	2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
@@ -23,35 +23,54 @@
 
                 /// root structure for the heterogenous object system
                 template <class Base>
-		struct abstract_cloneable : Base
+		struct abstract_cloneable : virtual Base
                 {
                         typedef Base base_type;
                         typedef abstract_cloneable<Base> this_type;
 
                         /// make storage for a new instance, but do not invoke any constructor
-			virtual this_type *allocate(abstract_allocator &alloc) const = 0;
+			virtual this_type *allocate(abstract_allocator &) const = 0;
 
                         /// free memory associated with the given instance
-			virtual void deallocate(base_type &, abstract_allocator &alloc) const = 0;
+			virtual void deallocate(abstract_allocator &) = 0;
 
                         /// create a new object of the derived type
-			virtual this_type *create_new(abstract_allocator &alloc) const = 0;
+			virtual this_type *create_new(abstract_allocator &) const = 0;
 
                         /// create a clone using copy-constructor. this is implemented in cloneable<>, but can
                         /// be overriden by the user in the derived type if required.
-			virtual this_type *copy_construct(const base_type &original, abstract_allocator &alloc) const = 0;
+			virtual this_type *copy_construct(abstract_allocator &) const = 0;
 
                         /// optional means to make a clone that does not use copy-construction.
                         /// user can overload this in their derived type to provide custom clone implementation.
-			virtual this_type *clone(const base_type &original, abstract_allocator &alloc) const { return 0; }
+			virtual this_type *make_copy(abstract_allocator &) const { return 0; }
 
                         /// make a copy of the given instance. try the custom clone method first, 
                         /// then default to using the copy-constructor method
-			this_type *make_copy(const base_type &original, abstract_allocator &alloc) const
+			this_type *clone(abstract_allocator &alloc) const
                         {
-				if (this_type *copy = clone(original, alloc))
+				if (this_type *copy = make_copy(alloc))
                                         return copy;
-				return copy_construct(original, alloc);
+				return copy_construct(alloc);
+			}
+
+			/// for use with types that use multiple inheritance - select which sub-object to clone
+			template <class Ty>
+			this_type *clone_as(abstract_allocator &alloc) const
+			{
+				const cloneable<Ty, Base> *ptr = dynamic_cast<const cloneable<Ty, Base> *>(this);
+				if (ptr == 0)
+					throw std::bad_cast();
+				return ptr->clone(alloc);
+			}
+
+			/// make a copy of the given instance using the heap. caller should call delete
+			this_type *clone() const
+			{
+				return 0;
+				//if (this_type *copy = clone(original, alloc))
+				//	return copy;
+				//return copy_construct(original, alloc);
                         }
                 };
 
Modified: sandbox/monotonic/boost/heterogenous/adaptor.hpp
==============================================================================
--- sandbox/monotonic/boost/heterogenous/adaptor.hpp	(original)
+++ sandbox/monotonic/boost/heterogenous/adaptor.hpp	2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
@@ -18,8 +18,8 @@
                 /// this is a type that can be used in an homogenous container
                 ///
                 /// ...this may or may not be a good idea...
-		template <class T, class Base, class AbstractBase>
-		struct adaptor : T, cloneable<adaptor<T, Base, AbstractBase>, Base, AbstractBase>
+		template <class T, class Base>//, class AbstractBase>
+		struct adaptor : T, cloneable<adaptor<T, Base/*, AbstractBase*/>, Base/*, AbstractBase*/>
                 {
                         adaptor() { }
 
Modified: sandbox/monotonic/boost/heterogenous/allocator.hpp
==============================================================================
--- sandbox/monotonic/boost/heterogenous/allocator.hpp	(original)
+++ sandbox/monotonic/boost/heterogenous/allocator.hpp	2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
@@ -30,7 +30,7 @@
                         template <class Base, class Alloc>
                         static Base* allocate_clone(const Base& object, Alloc &alloc )
                         {
-				return object.make_copy(object, alloc);
+				return object.clone(alloc);
                         }
 
                         template <class Base, class Alloc>
@@ -38,7 +38,7 @@
                         {
                                 if (!object)
                                         return;
-				object->deallocate(const_cast<Base &>(*object), alloc);
+				const_cast<Base &>(*object).deallocate(alloc);
                         }
                 };
 
Modified: sandbox/monotonic/boost/heterogenous/cloneable.hpp
==============================================================================
--- sandbox/monotonic/boost/heterogenous/cloneable.hpp	(original)
+++ sandbox/monotonic/boost/heterogenous/cloneable.hpp	2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
@@ -15,15 +15,16 @@
         namespace heterogenous
         {
                 /// base for the given derived type, using the given base class
-		template <class Derived, class Base, class AbstractBase>
-		struct cloneable : AbstractBase
+		template <class Derived, class Base>//, class AbstractBase>
+		struct cloneable : abstract_cloneable<Base>
                 {
                         typedef Derived derived_type;
                         typedef Base base_type;
-			typedef AbstractBase abstract_base_type;
-			typedef cloneable<Derived, Base, AbstractBase> this_type;
+			//typedef AbstractBase abstract_base_type;
+			typedef abstract_cloneable<Base> abstract_base_type;
+			typedef cloneable<Derived, Base/*, AbstractBase*/> this_type;
 
-		private:
+		//private:
                         static size_t alignment;			///< required alignment for allocation
                         mutable derived_type *self_ptr;		///< pointer to derived object in this
 
@@ -38,30 +39,34 @@
                                 return ptr;
                         }
 
-			void deallocate(base_type &object, abstract_allocator &alloc) const
+			void deallocate(abstract_allocator &alloc)
                         {
-				Derived *ptr = static_cast<Derived *>(&object);
+				Derived *ptr = dynamic_cast<Derived *>(this);
                                 alloc.deallocate_bytes(reinterpret_cast<abstract_allocator::pointer>(ptr), alignment);
                         }
 
                         virtual this_type *create_new(abstract_allocator &alloc) const 
                         {
-				this_type *ptr = allocate(alloc);
-				new (ptr->self_ptr) Derived();
+				abstract_allocator::pointer bytes = alloc.allocate_bytes(sizeof(derived_type), alignment);
+				Derived *ptr = reinterpret_cast<Derived *>(bytes);
+				ptr->this_type::self_ptr = ptr;
+				new (ptr->this_type::self_ptr) Derived();
                                 return ptr;
                         }
 
-			virtual this_type *copy_construct(const base_type &original, abstract_allocator &alloc) const 
+			virtual this_type *copy_construct(abstract_allocator &alloc) const 
                         { 
-				this_type *ptr = allocate(alloc);
-				new (ptr->self_ptr) Derived(static_cast<const Derived &>(original));
+				abstract_allocator::pointer bytes = alloc.allocate_bytes(sizeof(derived_type), alignment);
+				Derived *ptr = reinterpret_cast<Derived *>(bytes);
+				ptr->this_type::self_ptr = ptr;
+				new (ptr->this_type::self_ptr) Derived(static_cast<const Derived &>(*this));
                                 return ptr;
                         }
                 };
 
                 /// ensure correct alignment when allocating derived instances
-		template <class Derived, class Base, class AbstractBase>
-		size_t cloneable<Derived, Base, AbstractBase>::alignment = aligned_storage<sizeof(Derived)>::alignment;
+		template <class Derived, class Base/*, class AbstractBase*/>
+		size_t cloneable<Derived, Base/*, AbstractBase*/>::alignment = aligned_storage<sizeof(Derived)>::alignment;
 
         } // namespace heterogenous
 
Modified: sandbox/monotonic/boost/heterogenous/detail/allocation.hpp
==============================================================================
--- sandbox/monotonic/boost/heterogenous/detail/allocation.hpp	(original)
+++ sandbox/monotonic/boost/heterogenous/detail/allocation.hpp	2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
@@ -7,6 +7,7 @@
 #define BOOST_HETEROGENOUS_DETAIL_CONTAINER_BASE_HPP
 
 #include <boost/heterogenous/detail/prefix.hpp>
+#include <boost/heterogenous/cloneable.hpp>
 
 namespace boost
 {
@@ -14,6 +15,40 @@
         {
                 namespace detail
                 {
+			template <class U, class B>
+			struct pointer
+			{
+				typedef U derived_type;
+				typedef B base_type;
+				typedef cloneable<derived_type, base_type> ptr_type;
+				typedef typename cloneable<derived_type, base_type>::this_type cloneable_type;
+				typedef typename cloneable_type::abstract_base_type abstract_base_type;
+
+			private:
+				ptr_type *ptr;
+
+			public:
+				pointer(U *p = 0) : ptr(dynamic_cast<cloneable_type *>(p))
+				{
+				}
+				abstract_base_type *to_abstract() const
+				{
+					return ptr;
+				}
+				base_type *to_base() const
+				{
+					return ptr;
+				}
+				cloneable_type *to_cloneable() const
+				{
+					return ptr;
+				}
+				derived_type *to_derived() const
+				{
+					return ptr->cloneable_type::self_ptr;
+				}
+			};
+
                         template <class U, class Alloc>
                         U *allocate_type(Alloc &al)
                         {
@@ -23,8 +58,8 @@
 
                         // TODO: use variadic template arguments, or BOOST_PP
 
-			template <class U, class Alloc>
-			U *construct_type(Alloc &al)
+			template <class U, class Base, class Alloc>
+			pointer<U,Base> construct_type(Alloc &al)
                         {
                                 typename Alloc::template rebind<U>::other alloc(al);
                                 U *ptr = alloc.allocate(1);
@@ -32,24 +67,25 @@
                                 return ptr;
                         }
 
-			template <class U, class Alloc, class A0>
-			U *construct_type(Alloc &al, A0 a0)
+
+			template <class U, class Base, class Alloc, class A0>
+			pointer<U,Base> construct_type(Alloc &al, A0 a0)
                         {
                                 U *ptr = allocate_type<U>(al);
                                 new (ptr) U(a0);
                                 return ptr;
                         }
 
-			template <class U, class Alloc, class A0, class A1>
-			U *construct_type(Alloc &al, A0 a0, A1 a1)
+			template <class U, class Base, class Alloc, class A0, class A1>
+			pointer<U,Base> construct_type(Alloc &al, A0 a0, A1 a1)
                         {
                                 U *ptr = allocate_type<U>(al);
                                 new (ptr) U(a0, a1);
                                 return ptr;
                         }
 
-			template <class U, class Alloc, class A0, class A1, class A2>
-			U *construct_type(Alloc &al, A0 a0, A1 a1, A2 a2)
+			template <class U, class Base, class Alloc, class A0, class A1, class A2>
+			pointer<U,Base> construct_type(Alloc &al, A0 a0, A1 a1, A2 a2)
                         {
                                 U *ptr = allocate_type<U>(al);
                                 new (ptr) U(a0, a1, a2);
Modified: sandbox/monotonic/boost/heterogenous/forward_declarations.hpp
==============================================================================
--- sandbox/monotonic/boost/heterogenous/forward_declarations.hpp	(original)
+++ sandbox/monotonic/boost/heterogenous/forward_declarations.hpp	2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
@@ -32,7 +32,7 @@
                 template <
                         class Derived
                         , class Base = default_base_type
-			, class AbstractBase = abstract_cloneable<Base> >
+			>// this is too much uncessary customisation:, class AbstractBase = abstract_cloneable<Base> >
                 struct cloneable;
 
                 /// an adaptor for an existing class.
@@ -42,14 +42,14 @@
                 template <
                         class T
                         , class Base = default_base_type
-			, class AbstractBase = abstract_cloneable<Base> >
+			>//, class AbstractBase = abstract_cloneable<Base> >
                 struct adaptor;
 
                 /// a heterogenous vector of objects
                 template <
                         class Base = default_base_type
                         , class Alloc = monotonic::allocator<int>
-			, class AbstractBase = abstract_cloneable<Base> >
+			>//, class AbstractBase = abstract_cloneable<Base> >
                 struct vector;
 
                 /// a mapping of heterogenous objects to heterogenous objects
@@ -57,7 +57,7 @@
                         class Base = default_base_type
                         , class Pred = std::less<Base>
                         , class Alloc = monotonic::allocator<int>
-			, class AbstractBase = abstract_cloneable<Base> >
+			>//, class AbstractBase = abstract_cloneable<Base> >
                 struct map;
 
         } // namespace heterogenous
Modified: sandbox/monotonic/boost/heterogenous/map.hpp
==============================================================================
--- sandbox/monotonic/boost/heterogenous/map.hpp	(original)
+++ sandbox/monotonic/boost/heterogenous/map.hpp	2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
@@ -17,12 +17,13 @@
         namespace heterogenous
         {
                 /// a vector of heterogenous objects
-		template <class Base, class Pred, class Alloc, class AbstractBase>
+		template <class Base, class Pred, class Alloc>//, class AbstractBase>
                 struct map
                 {
                         typedef typename make_clone_allocator<Alloc>::type allocator_type;
                         typedef Base base_type;
                         //typedef ptr_map<Base, Base, Pred, allocator, allocator_type> implementation;
+			typedef abstract_cloneable<Base> abstract_base_type;
 
                         typedef std::map<Base *, Base *, Pred, allocator_type> implementation;
 
@@ -33,7 +34,7 @@
                         typedef typename implementation::const_iterator const_iterator;
                         typedef typename implementation::key_type key_type;
                         typedef typename implementation::mapped_type mapped_type;
-			typedef map<Base, Pred, Alloc, AbstractBase> this_type;
+			typedef map<Base, Pred, Alloc/*, AbstractBase*/> this_type;
 
                 private:
                         implementation impl;
@@ -64,7 +65,7 @@
                                 template <class U>
                                 this_type &value()
                                 {
-					U *val = detail::construct_type<U>(parent->get_allocator());
+					U *val = detail::construct_type<U,base_type>(parent->get_allocator()).to_derived();;
                                         parent->insert(std::make_pair(key_instance, val));
                                         return *parent;
                                 }
@@ -73,14 +74,14 @@
                                 template <class U, class A0>
                                 this_type &value(A0 a0)
                                 {
-					U *val = detail::construct_type<U>(parent->get_allocator(), a0);
+					U *val = detail::construct_type<U,base_type>(parent->get_allocator(), a0).to_derived();;
                                         parent->insert(std::make_pair(key_instance, val));
                                         return *parent;
                                 }
                                 template <class U, class A0, class A1>
                                 this_type &value(A0 a0, A1 a1)
                                 {
-					U *val = detail::construct_type<U>(parent->get_allocator(), a0, a1);
+					U *val = detail::construct_type<U,base_type>(parent->get_allocator(), a0, a1).to_derived();;
                                         parent->insert(std::make_pair(key_instance, val));
                                         return *parent;
                                 }
@@ -90,7 +91,7 @@
                         template <class U>
                         value_adder key()
                         {
-				U *key_instance = detail::construct_type<U>(get_allocator());
+				U *key_instance = detail::construct_type<U,base_type>(get_allocator()).to_derived();
                                 return value_adder(*this, *key_instance);
                         }
 
@@ -98,19 +99,19 @@
                         template <class U, class A0>
                         value_adder key(A0 a0)
                         {
-				U *key_instance = detail::construct_type<U>(get_allocator(), a0);
+				U *key_instance = detail::construct_type<U,base_type>(get_allocator(), a0).to_derived();
                                 return value_adder(*this, *key_instance);
                         }
                         template <class U, class A0, class A1>
                         value_adder key(A0 a0, A1 a1)
                         {
-				U *key_instance = detail::construct_type<U>(get_allocator(), a0, a1);
+				U *key_instance = detail::construct_type<U,base_type>(get_allocator(), a0, a1).to_derived();
                                 return value_adder(*this, *key_instance);
                         }
                         template <class U, class A0, class A1, class A2>
                         value_adder key(A0 a0, A1 a1, A2 a2)
                         {
-				U *key_instance = detail::construct_type<U>(get_allocator(), a0, a1, a2);
+				U *key_instance = detail::construct_type<U,base_type>(get_allocator(), a0, a1, a2).to_derived();
                                 return value_adder(*this, *key_instance);
                         }
 
Modified: sandbox/monotonic/boost/heterogenous/vector.hpp
==============================================================================
--- sandbox/monotonic/boost/heterogenous/vector.hpp	(original)
+++ sandbox/monotonic/boost/heterogenous/vector.hpp	2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
@@ -20,12 +20,15 @@
         namespace heterogenous
         {
                 /// a vector of heterogenous objects
-		template <class Base, class Alloc, class AbstractBase>
+		template <class Base, class Alloc>//, class AbstractBase>
                 struct vector
                 {
                         typedef Base base_type;
+			//typedef AbstractBase abstract_base_type;
+			typedef abstract_cloneable<Base> abstract_base_type;
                         typedef typename make_clone_allocator<Alloc>::type allocator_type;
-			typedef ptr_vector<AbstractBase, allocator, allocator_type> implementation;
+			typedef ptr_vector<abstract_base_type, allocator, allocator_type> implementation;
+			//typedef ptr_vector<Base, allocator, allocator_type> implementation;
                         typedef typename implementation::value_type value_type;
                         typedef typename implementation::reference reference;
                         typedef typename implementation::const_reference const_reference;
@@ -175,22 +178,22 @@
                         template <class U>
                         void emplace_back()
                         {
-				impl.push_back(detail::construct_type<U>(get_allocator()));
+				impl.push_back(detail::construct_type<U,base_type>(get_allocator()).to_abstract());
                         }
                         template <class U, class A0>
                         void emplace_back(A0 a0)
                         {
-				impl.push_back(detail::construct_type<U>(get_allocator(), a0));
+				impl.push_back(detail::construct_type<U,base_type>(get_allocator(), a0).to_abstract());
                         }
                         template <class U, class A0, class A1>
                         void emplace_back(A0 a0, A1 a1)
                         {
-				impl.push_back(detail::construct_type<U>(get_allocator(), a0,a1));
+				impl.push_back(detail::construct_type<U,base_type>(get_allocator(), a0,a1).to_abstract());
                         }
                         template <class U, class A0, class A1, class A2>
                         void emplace_back(A0 a0, A1 a1, A2 a2)
                         {
-				impl.push_back(detail::construct_type<U>(get_allocator(), a0,a1,a2));
+				impl.push_back(detail::construct_type<U,base_type>(get_allocator(), a0,a1,a2).to_abstract());
                         }
 
                         typename implementation::allocator_type get_allocator()
Modified: sandbox/monotonic/libs/monotonic/test/clones/tests.cpp
==============================================================================
--- sandbox/monotonic/libs/monotonic/test/clones/tests.cpp	(original)
+++ sandbox/monotonic/libs/monotonic/test/clones/tests.cpp	2009-06-30 05:05:07 EDT (Tue, 30 Jun 2009)
@@ -54,22 +54,56 @@
         }
 };
 
-// naive way of allowing reuse in derived types: factor out the implementation
-struct derived4_impl
+namespace mi_test
 {
-};
 
-struct derived4 : derived4_impl, cloneable<derived4>
-{
-};
+	struct Q0 : cloneable<Q0>
+	{
+		int num;
+		Q0(int n = 0) : num(n) { }
+	};
+
+	struct Q1 : Q0, cloneable<Q1>
+	{
+		string s;
+		Q1() { }
+		Q1(string t) : s(t) { }
+	};
+
+}
 
-struct derived5 : derived4_impl, cloneable<derived5>
+void test_multiple_inheritance()
 {
-};
+	using namespace mi_test;
+	typedef heterogenous::vector<> vec;
+	vec v;
+
+
+	Q0 *q0 = new Q0;
+	BOOST_ASSERT(typeid(*q0) == typeid(Q0));
+	Q0 *q0_c = dynamic_cast<Q0 *>(q0->clone(v.get_allocator()));
+	BOOST_ASSERT(typeid(*q0_c) == typeid(Q0));
+
+	Q1 *q1 = new Q1();
+	BOOST_ASSERT(typeid(*q1) == typeid(Q1));
+	//Q1 *q1_c  = dynamic_cast<Q1 *>(q1->cloneable<Q1>::clone(v.get_allocator()));
+	
+	Q0 *q1_c0  = dynamic_cast<Q0 *>(q1->cloneable<Q0>::abstract_base_type::clone(v.get_allocator()));
+	BOOST_ASSERT(typeid(*q1_c0) == typeid(Q0));
+
+	//Q1 *q1_c  = dynamic_cast<Q1 *>(q1->cloneable<Q1>::abstract_base_type::clone(v.get_allocator()));
+	Q1 *q1_c  = dynamic_cast<Q1 *>(q1->clone_as<Q1>(v.get_allocator()));
+	BOOST_ASSERT(typeid(*q1_c) == typeid(Q1));
+
+	v.emplace_back<Q0>(42);
+	v.emplace_back<Q1>("foo");
+
+	vec v2 = v;
+	BOOST_ASSERT(v2.ref_at<Q1>(1).s == "foo");
+}
 
 void test_any();
 void test_variant();
-
 void test_map();
 
 
@@ -113,7 +147,8 @@
 
         test_any();
         test_variant();
-	test_map();
+//	test_map();
+	test_multiple_inheritance();
 
         // a 'heterogenous' container of objects of any type that derives from common_base
         typedef heterogenous::vector<my_base> vec;