Boost logo

Boost-Commit :

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;


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk