Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r54418 - sandbox/monotonic/libs/monotonic/test/clones
From: christian.schladetsch_at_[hidden]
Date: 2009-06-27 21:07:41


Author: cschladetsch
Date: 2009-06-27 21:07:40 EDT (Sat, 27 Jun 2009)
New Revision: 54418
URL: http://svn.boost.org/trac/boost/changeset/54418

Log:
udpoated

Text files modified:
   sandbox/monotonic/libs/monotonic/test/clones/main.cpp | 187 +++++++++++++++++++++++++++++----------
   1 files changed, 140 insertions(+), 47 deletions(-)

Modified: sandbox/monotonic/libs/monotonic/test/clones/main.cpp
==============================================================================
--- sandbox/monotonic/libs/monotonic/test/clones/main.cpp (original)
+++ sandbox/monotonic/libs/monotonic/test/clones/main.cpp 2009-06-27 21:07:40 EDT (Sat, 27 Jun 2009)
@@ -1,79 +1,172 @@
+//
+// test cases for ptr_container and clone_allocator issues
+//
 
 #include <iostream>
-#include <vector>
 #include <boost/ptr_container/ptr_vector.hpp>
 #include <boost/monotonic/allocator.hpp>
 
 using namespace std;
 using namespace boost;
 
-struct type_number
-{
- int value;
- enum
+namespace boost
+{
+ //namespace ptr_container {
+
+ namespace cloneable
         {
- None = 0,
- Base = 1,
- Derived = 2,
- };
- type_number(int n = None) : value(n) { }
-};
 
-struct base
-{
- type_number type;
+ // common base for all base types for hierachies
+ struct base_base
+ {
+ virtual ~base_base() { }
+
+ // this can't work because it doesnt have an allocator :/
+ virtual base_base *clone() const = 0;
+ };
+
+ template <class Derived>
+ struct base : base_base
+ {
+ typedef Derived derived_type;
+
+ // idea: pass the allocator to a non-virtual clone_with(alloc) method in the base.
+ // must be disabled at compile-time for types that are not boost::is_convertible<base<D> *, D*>
+ template <class Alloc>
+ static derived_type *clone_with(Alloc &alloc)
+ {
+ derived_type *copy = alloc.allocate(1);
+ // passing ctor args is an outstanding issue; can be helped by:
+ // 1. over-riding clone_with in derived
+ // 2. using super-set allocators with variadic template args for construct method
+ alloc.construct(copy);
+ return copy;
+ }
+ };
+
+ struct allocator
+ {
+ template< class U >
+ static U* allocate_clone( const U& r )
+ {
+ // this is not allocated using the parent containers custom allocator
+ return r.clone();
+ }
+
+ template< class U >
+ static void deallocate_clone( const U* clone )
+ {
+ // this is not de-allocated using the parent containers custom allocator
+ //! ??clone->deallocate();??
+ //! delete clone; // this is not correct either; also calls dtor
+
+ // this is not correct either, but seems the best we can do...?
+ std::allocator<char> alloc;
+ U *ptr = const_cast<U *>(clone);
+ alloc.deallocate(reinterpret_cast<char *>(ptr), 1);
+ }
+
+ // idea: pass allocator to the clone_allocator.
+ // allocator rebind could be done in the ptr_container.
+ template< class U, class Alloc >
+ static U* allocate_clone( const U& r, Alloc &alloc )
+ {
+ typedef typename Alloc::template rebind<U>::other my_alloc(alloc);
+ return r.clone_with(my_alloc);
+ }
+
+ // idea: this is not even needed?
+ // allocator rebind could be done in the ptr_container
+ template< class U, class Alloc >
+ static U* deallocate_clone( const U* r, Alloc &alloc )
+ {
+ typedef typename Alloc::template rebind<U>::other my_alloc(alloc);
+ my_alloc.deallocate(const_cast<U *>(r));
+ }
+ };
 
- explicit base(type_number t) : type(t) { }
- virtual ~base() { }
+ } // namespace cloneable
 
- virtual base *clone() const = 0;
-};
+} // namespace boost
+
+// client code...
 
-struct derived : base
+struct derived : cloneable::base<derived>
 {
         int num;
- explicit derived(int n) : base(type_number::Derived), num(n) { }
 
- base *clone() const
+ derived() : num(0) { }
+ explicit derived(int n) : num(n) { }
+
+ // this can't work
+ cloneable::base_base *clone() const
         {
+ // this is really no good as it doesnt use the correct allocator
                 return new derived(num);
         }
 };
 
-struct clone_allocator
+struct derived2 : cloneable::base<derived2>
 {
- template< class U >
- static U* allocate_clone( const U& r )
- {
- return r.clone();
- }
+ string str;
+
+ derived2() { }
+ explicit derived2(string const &n) : str(n) { }
 
- template< class U >
- static void deallocate_clone( const U* clone )
+ // this can't work
+ cloneable::base_base *clone() const
         {
- if (clone)
- clone->U::~U();
+ // this is really no good as it doesnt use the correct allocator
+ return new derived2(str);
         }
 };
 
+/*
+
+namespace boost { namespace ptr_container {
+
+// idea: switch allocator type ordering, default to cloneable::allcoator
+template <class T, class Al = std::allocator<T>, class CloneAl = cloneable::allocator>
+class ptr_vector;
+
+}}
+
+*/
+
 int main()
 {
- typedef ptr_vector<base, clone_allocator, monotonic::allocator<int> > vec;
- // why ptr_vector<..> p(n) resize the vector to have n default-constructed elements?
- // it only reserves n elements at the moment...
- //vec bases(1);
- //bases[0] = derived(42); // throws out of range error
-
- //vec bases;
- //bases.resize(1); // doesnt work because it cannot instantiate an abstract class
- //bases[0] = derived(42);
-
- vec bases;
- bases.push_back(new derived(42));
-
- vec copy = bases;
- BOOST_ASSERT(copy.size() == 1);
- BOOST_ASSERT(copy.at(0).type.value == type_number::Derived);
+ typedef ptr_vector<cloneable::base_base, cloneable::allocator, monotonic::allocator<int> > vec;
+
+ {
+ vec bases;
+ BOOST_ASSERT(bases.get_allocator().get_storage() == &monotonic::static_storage<>::get_storage());
+
+ //! bases.push_back(new derived(42)); // this doesn't use the custom allocator!
+ //! derived *obj = bases.get_allocator().allocate(1); // this has to be recast
+
+ // do a dance to get the object into the container...
+ typedef vec::allocator_type::template rebind<derived>::other derived_alloc_type;
+ derived_alloc_type derived_alloc(bases.get_allocator());
+ derived *obj = derived_alloc.allocate(1);
+ //! derived_alloc.construct(obj, 42); // can't pass ctor args to a v1 allocator
+ new (obj) derived(42); // bypassing allocator::construct :/
+
+ // finally get the correctly allocated object into the container
+ bases.push_back(obj);
+
+ // idea: use variadic template arguments for push_back etc:
+ // default to use BOOST_PP for C++03
+ //! bases.push_back<derived>(ctor_args...);
+
+ // ...promptly breaks everything by using the heap to make the clones in copy :/
+ vec copy = bases;
+
+ // idea: could be fixed by using base<derived>::clone_with(orig, rebind(alloc)) in the ptr_container...
+
+ // doesn't work because the clones were put on the heap. could work with cloneable:: ?
+ monotonic::static_storage<>::release();
+ }
+
         return 0;
 }
 


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