Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r54656 - in sandbox/cloneable: boost/cloneable boost/cloneable/detail libs/cloneable/test
From: christian.schladetsch_at_[hidden]
Date: 2009-07-04 18:31:37


Author: cschladetsch
Date: 2009-07-04 18:31:36 EDT (Sat, 04 Jul 2009)
New Revision: 54656
URL: http://svn.boost.org/trac/boost/changeset/54656

Log:
added cloneable/base_type.hpp, more free-functions in clone.hpp. some of these do not work.
Added:
   sandbox/cloneable/boost/cloneable/base_type.hpp (contents, props changed)
Text files modified:
   sandbox/cloneable/boost/cloneable/abstract_base.hpp | 67 +++++++++++---------------
   sandbox/cloneable/boost/cloneable/base.hpp | 3
   sandbox/cloneable/boost/cloneable/clone.hpp | 101 ++++++++++++++++++++++++++++++++++++++++
   sandbox/cloneable/boost/cloneable/cloneable.hpp | 1
   sandbox/cloneable/boost/cloneable/detail/mixin.hpp | 52 ++++++++++++++++++++
   sandbox/cloneable/libs/cloneable/test/cloneable.vcproj | 4 +
   sandbox/cloneable/libs/cloneable/test/tests.cpp | 84 ++++++++++++++++++++++++++++++++
   7 files changed, 270 insertions(+), 42 deletions(-)

Modified: sandbox/cloneable/boost/cloneable/abstract_base.hpp
==============================================================================
--- sandbox/cloneable/boost/cloneable/abstract_base.hpp (original)
+++ sandbox/cloneable/boost/cloneable/abstract_base.hpp 2009-07-04 18:31:36 EDT (Sat, 04 Jul 2009)
@@ -17,47 +17,11 @@
 {
         namespace cloneable
         {
- template <class T>
- struct abstract_object
- {
- typedef abstract_object<T> abstract_object_type;
-
- virtual std::string to_string() const { return "abstract_object<T>"; }
- virtual size_t hash_value() const { return 0; }
- virtual bool less(const abstract_object_type& other) const { return false; }
- virtual bool equiv(const abstract_object_type& other) const
- {
- return !less(other) && !other.less(static_cast<const T&>(*this));
- }
- };
-
- template <class T>
- inline bool operator<(const abstract_object<T>& left, const abstract_object<T>& right)
- {
- return left.less(right);
- }
-
- template <class T>
- inline bool operator==(const abstract_object<T>& left, const abstract_object<T>& right)
- {
- return left.equiv(right);
- }
-
- /// default base type used for object hierarchies. the user can supply their own when using
- /// cloneable<Derived, Base>.
- /// this will be used as a base by default.
- struct base_type : abstract_object<base_type>
- {
- virtual ~base_type() { }
-
- std::string to_string() const { return "base_type"; }
- size_t hash_value() const { return 0; }
- bool less(const base_type &other) const { return false; }
- };
-
                 /// root structure for the cloneable object system
                 template <class Base>
- struct abstract_base : virtual Base
+ struct abstract_base
+ : virtual Base
+ , virtual is_cloneable_tag
                 {
                         typedef Base base_type;
                         typedef abstract_base<Base> this_type;
@@ -112,6 +76,13 @@
                                 return create_new(alloc);
                         }
 
+ /// non-virtual method that creates a new instance of derived type using given allocator
+ template <class Alloc>
+ this_type *create(Alloc &alloc) const
+ {
+ return create_new(alloc);
+ }
+
                         /// non-virtual method that creates a new instance of derived type from this instance,
                         /// using copy-constructor and default allocator
                         this_type *copy_construct() const
@@ -127,6 +98,24 @@
                                 return clone(alloc);
                         }
 
+ // these non-virtuals require mixin<D,B> to be defined before they can be
+ // implemented. See detail/mixin.hpp for their definitions
+ template <class Derived>
+ bool can_clone_as() const;
+
+ template <class Derived>
+ Derived *clone_as() const;
+
+ template <class Derived>
+ Derived *clone_as(abstract_allocator &) const;
+
+ template <class Derived>
+ bool can_create_as() const;
+
+ template <class Derived>
+ bool can_default_create_as() const;
+ ///
+
                         /// overridable to-string function, for utility
                         virtual std::string to_string() const { return "cloneable"; }
 

Modified: sandbox/cloneable/boost/cloneable/base.hpp
==============================================================================
--- sandbox/cloneable/boost/cloneable/base.hpp (original)
+++ sandbox/cloneable/boost/cloneable/base.hpp 2009-07-04 18:31:36 EDT (Sat, 04 Jul 2009)
@@ -8,6 +8,8 @@
 
 #include <boost/aligned_storage.hpp>
 #include <boost/cloneable/detail/prefix.hpp>
+#include <boost/cloneable/base_type.hpp>
+#include <boost/cloneable/abstract_base.hpp>
 #include <boost/cloneable/detail/mixin.hpp>
 #include <boost/cloneable/detail/create_new.hpp>
 
@@ -24,7 +26,6 @@
                         template <class Derived, class Base, class DefaultCtorTag>
                         struct base
                                 : detail::mixin<Derived, Base>
- , virtual is_cloneable_tag
                                 , virtual DefaultCtorTag
                         {
                                 typedef Derived derived_type;

Added: sandbox/cloneable/boost/cloneable/base_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/cloneable/boost/cloneable/base_type.hpp 2009-07-04 18:31:36 EDT (Sat, 04 Jul 2009)
@@ -0,0 +1,64 @@
+// Copyright (C) 2009 Christian Schladetsch
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CLONEABLE_BASE_TYPE_HPP
+#define BOOST_CLONEABLE_BASE_TYPE_HPP
+
+#include <boost/aligned_storage.hpp>
+#include <boost/cloneable/detail/prefix.hpp>
+#include <boost/cloneable/detail/mixin.hpp>
+#include <boost/cloneable/detail/create_new.hpp>
+
+namespace boost
+{
+ namespace cloneable
+ {
+ template <class T>
+ struct abstract_object
+ {
+ typedef abstract_object<T> abstract_object_type;
+
+ virtual std::string to_string() const { return "abstract_object<T>"; }
+ virtual size_t hash_value() const { return 0; }
+ virtual bool less(const abstract_object_type& other) const { return false; }
+ virtual bool equiv(const abstract_object_type& other) const
+ {
+ return !less(other) && !other.less(static_cast<const T&>(*this));
+ }
+ };
+
+ template <class T>
+ inline bool operator<(const abstract_object<T>& left, const abstract_object<T>& right)
+ {
+ return left.less(right);
+ }
+
+ template <class T>
+ inline bool operator==(const abstract_object<T>& left, const abstract_object<T>& right)
+ {
+ return left.equiv(right);
+ }
+
+ /// default base type used for object hierarchies. the user can supply their own when using
+ /// cloneable<Derived, Base>.
+ /// this will be used as a base by default.
+ struct base_type : abstract_object<base_type>
+ {
+ virtual ~base_type() { }
+
+ std::string to_string() const { return "base_type"; }
+ size_t hash_value() const { return 0; }
+ bool less(const base_type &other) const { return false; } // to_string() < other.to_string()
+ bool equiv(const base_type &other) const { return true; } // to_string() == other.to_string()
+ };
+
+ } // namespace cloneable
+
+} // namespace boost
+
+#endif // BOOST_CLONEABLE_BASE_TYPE_HPP
+
+//EOF
+

Modified: sandbox/cloneable/boost/cloneable/clone.hpp
==============================================================================
--- sandbox/cloneable/boost/cloneable/clone.hpp (original)
+++ sandbox/cloneable/boost/cloneable/clone.hpp 2009-07-04 18:31:36 EDT (Sat, 04 Jul 2009)
@@ -15,6 +15,7 @@
         {
                 namespace impl
                 {
+ /// implementation of cloning when using non-Cloneable types
                         template <bool>
                         struct clone
                         {
@@ -28,7 +29,23 @@
                                 {
                                         return create<T>(alloc, original);
                                 }
+ template <class Derived, class Base, class Alloc>
+ Derived *from_base(const Base &base, Alloc &alloc)
+ {
+ const Derived *derived = dynamic_cast<const Derived *>(&base);
+ if (mixin == 0)
+ throw std::bad_cast();
+ return create<Derived>(alloc, *derived);
+ }
+ template <class Derived, class Base>
+ static bool can_clone_as(const Base &base)
+ {
+ const Derived *derived = dynamic_cast<const Derived *>(&base);
+ return derived != 0;
+ }
                         };
+
+ /// implementation of cloneing using Cloneable types
                         template <>
                         struct clone<true>
                         {
@@ -42,6 +59,43 @@
                                 {
                                         return original.clone_as<T>(alloc);
                                 }
+ template <class Derived, class Base, class Alloc>
+ static Derived *from_base(const Base &base, Alloc &alloc)
+ {
+ typedef detail::mixin<Derived,Base> mixin_type;
+ const mixin_type *mixin = dynamic_cast<const mixin_type *>(&base);
+ if (mixin == 0)
+ throw std::bad_cast();
+ return mixin->clone_as<Derived>(alloc);
+ }
+ template <class Derived, class Base>
+ static Derived *from_base(const Base &base)
+ {
+ make_clone_allocator<default_allocator>::type alloc;
+ return from_base<Derived>(base, alloc);
+ }
+
+ template <class Derived, class Base>
+ static bool can_clone_as(const Base &base)
+ {
+ typedef is_same<Derived, Base> same;
+ if (same::value)
+ return true;
+ if (clone<false>::can_clone_as<Derived>(base))
+ return true;
+ typedef detail::mixin<Derived,Base> mixin_type;
+ return dynamic_cast<const mixin_type *>(&base) != 0;
+ }
+ template <class Derived, class Base>
+ static bool can_create_as(const Base &base)
+ {
+ typedef is_same<Derived, Base> same;
+ if (same::value)
+ return true;
+ if (clone<false>::can_create_as<Derived>(base))
+ return true;
+ return dynamic_cast<abstract_base<Base> const &>(base).can_create_as<Derived>();
+ }
                         };
 
                 } // namespace impl
@@ -60,6 +114,53 @@
                         return impl::clone<is_cloneable<T>::value>::given(original, alloc);
                 }
 
+ template <class Derived, class Base>
+ bool can_clone_as(const Base &base)
+ {
+ return impl::clone<is_cloneable<Base>::value>::can_clone_as<Derived>(base);
+ }
+
+ template <class Derived, class Base>
+ bool can_create_as(const Base &base)
+ {
+ return impl::clone<is_cloneable<Base>::value>::can_create_as<Derived>(base);
+ }
+
+ /// clone as a specified derived type, from a base type
+ template <class Derived, class Base>
+ Derived *clone_as(const Base &original)
+ {
+ return impl::clone<true>::from_base<Derived>(original);
+ }
+
+ /// clone as a specified derived type, from a base type, given allocator
+ template <class Derived, class Base, class Alloc>
+ Derived *clone_as(const Base &original, Alloc &alloc)
+ {
+ return impl::clone<true>::from_base<Derived>(original, alloc);
+ }
+
+ /// TODO: add to cloneable/exceptions.hpp
+ struct not_cloneable { };
+
+ template <class Base>
+ Base *create_new(const Base &base)
+ {
+ const abstract_base<Base> *abst = dynamic_cast<const abstract_base<Base> *>(&base);
+ if (abst == 0)
+ throw not_cloneable();
+ return abst->create();
+ }
+
+ template <class Base, class Alloc>
+ Base *create_new(const Base &base, Alloc &alloc)
+ {
+ const abstract_base<Base> *abst = dynamic_cast<const abstract_base<Base> *>(&base);
+ if (abst == 0)
+ throw not_cloneable();
+ return abst->create_new(alloc);
+ }
+
         } // namespace cloneable
 
 } // namespace boost

Modified: sandbox/cloneable/boost/cloneable/cloneable.hpp
==============================================================================
--- sandbox/cloneable/boost/cloneable/cloneable.hpp (original)
+++ sandbox/cloneable/boost/cloneable/cloneable.hpp 2009-07-04 18:31:36 EDT (Sat, 04 Jul 2009)
@@ -7,6 +7,7 @@
 #define BOOST_CLONEABLE_CLONEABLE_HPP
 
 #include <boost/cloneable/base.hpp>
+#include <boost/cloneable/clone.hpp>
 
 #endif // BOOST_CLONEABLE_CLONEABLE_HPP
 

Modified: sandbox/cloneable/boost/cloneable/detail/mixin.hpp
==============================================================================
--- sandbox/cloneable/boost/cloneable/detail/mixin.hpp (original)
+++ sandbox/cloneable/boost/cloneable/detail/mixin.hpp 2009-07-04 18:31:36 EDT (Sat, 04 Jul 2009)
@@ -41,6 +41,12 @@
                                         return typeid(derived_type);
                                 }
 
+ template <class T>
+ bool can_clone_as() const
+ {
+ return dynamic_cast<const mixin<T, Base> *>(this) != 0;
+ }
+
                                 virtual this_type *allocate(abstract_allocator &alloc) const
                                 {
                                         abstract_allocator::pointer bytes = alloc.allocate_bytes(sizeof(derived_type), alignment);
@@ -110,6 +116,52 @@
 
                 } // namespace detail
 
+ /// now that we have the mixin<D,B> definition, define the abstract_base<B>::method<D>() implementations
+ template <class Base>
+ template <class Derived>
+ bool abstract_base<Base>::can_clone_as() const
+ {
+ typedef detail::mixin<Derived,Base> mixin_type;
+ return dynamic_cast<const mixin_type *>(this) != 0;
+ }
+
+ template <class Base>
+ template <class Derived>
+ bool abstract_base<Base>::can_create_as() const
+ {
+ typedef detail::mixin<Derived,Base> mixin_type;
+ return dynamic_cast<const mixin_type *>(this) != 0;
+ }
+
+ template <class Base>
+ template <class Derived>
+ bool abstract_base<Base>::can_default_create_as() const
+ {
+ return traits<Derived>::has_default_ctor && can_create_as<Derived>();
+ }
+
+ template <class Base>
+ template <class Derived>
+ Derived *abstract_base<Base>::clone_as(abstract_allocator &alloc) const
+ {
+ typedef detail::mixin<Derived,Base> mixin_type;
+ const mixin_type *mixin = dynamic_cast<const mixin_type *>(this);
+ if (mixin == 0)
+ throw std::bad_cast();
+ return mixin->clone_as<Derived>(alloc);
+ }
+
+ template <class Base>
+ template <class Derived>
+ Derived *abstract_base<Base>::clone_as() const
+ {
+ typedef detail::mixin<Derived,Base> mixin_type;
+ const mixin_type *mixin = dynamic_cast<const mixin_type *>(this);
+ if (mixin == 0)
+ throw std::bad_cast();
+ return mixin->clone_as<Derived>();
+ }
+
         } // namespace cloneable
 
 } // namespace boost

Modified: sandbox/cloneable/libs/cloneable/test/cloneable.vcproj
==============================================================================
--- sandbox/cloneable/libs/cloneable/test/cloneable.vcproj (original)
+++ sandbox/cloneable/libs/cloneable/test/cloneable.vcproj 2009-07-04 18:31:36 EDT (Sat, 04 Jul 2009)
@@ -273,6 +273,10 @@
>
                                 </File>
                                 <File
+ RelativePath="..\..\..\boost\cloneable\base_type.hpp"
+ >
+ </File>
+ <File
                                         RelativePath="..\..\..\boost\cloneable\clone.hpp"
>
                                 </File>

Modified: sandbox/cloneable/libs/cloneable/test/tests.cpp
==============================================================================
--- sandbox/cloneable/libs/cloneable/test/tests.cpp (original)
+++ sandbox/cloneable/libs/cloneable/test/tests.cpp 2009-07-04 18:31:36 EDT (Sat, 04 Jul 2009)
@@ -37,6 +37,8 @@
 using namespace boost;
 using namespace cloneable;
 
+
+
 namespace basic_test
 {
         struct my_base { virtual ~my_base() { } };
@@ -67,10 +69,30 @@
         T0 *t0_clone = dynamic_cast<T0 *>(t0->clone());
         BOOST_ASSERT(typeid(*t0_clone) == typeid(T0));
 
+ // cloning from a raw base type
+ my_base *t0_base = new T0();
+ T0 *t0_base_clone = cloneable::clone_as<T0>(*t0_base);
+ BOOST_ASSERT(t0_base_clone != 0);
+
+ // make a new object from an existing base
+ my_base *t0_new = cloneable::create_new(*t0_base);
+ BOOST_ASSERT(t0_new && typeid(*t0_new) == typeid(T0));
+
+ delete t0_base;
+ delete t0_base_clone;
+ delete t0_new;
+
         // cloning from an abstract_base_type
+ BOOST_STATIC_ASSERT((is_same<my_base, T1::base_type>::value));
+ BOOST_STATIC_ASSERT((is_same<cloneable::abstract_base<my_base>, T1::abstract_base_type>::value));
         T1::abstract_base_type *t1_base = new T1();
- T1 *t1_clone = dynamic_cast<T1 *>(t1_base->clone());
- BOOST_ASSERT(typeid(*t1_clone) == typeid(T1));
+
+ // query for supported clone types
+ BOOST_ASSERT(t1_base->can_clone_as<T1>());
+ BOOST_ASSERT(!t1_base->can_clone_as<T2>());
+
+ T1 *t1_clone = t1_base->clone_as<T1>();
+ BOOST_ASSERT(t1_clone != 0);
 
         // use a free-function from a generalised abstract_base
         T2 *t2 = new T2;
@@ -150,6 +172,64 @@
         BOOST_ASSERT(q2_0 && q2_1 && q2_w);
 }
 
+namespace mi_test_2
+{
+ struct Base { virtual ~Base() { } };
+ struct T0 : base<T0, Base> { };
+ struct T1 : T0, base<T1, Base> { };
+ struct W : base<W, Base> { };
+ struct T2 : W, T1, base<T2, Base> { };
+}
+
+BOOST_AUTO_TEST_CASE(test_mi_2)
+{
+ using namespace mi_test_2;
+ using namespace cloneable;
+
+ T2 *t2 = new T2();
+
+ assert(t2->can_clone_as<T0>());
+ assert(t2->can_clone_as<T1>());
+ assert(t2->can_clone_as<T2>());
+ assert(t2->can_clone_as<W>());
+
+ assert(t2->can_create_as<T0>());
+ assert(t2->can_create_as<T1>());
+ assert(t2->can_create_as<T2>());
+ assert(t2->can_create_as<W>());
+ /* assert(can_clone_as<W>(*t2));
+ assert(can_clone_as<T0>(*t2));
+ assert(can_clone_as<T1>(*t2));
+ assert(can_clone_as<T2>(*t2));
+ */
+ //assert(can_create_as<W>(*t2));
+ // assert(can_create_as<T0>(*t2));
+// assert(can_create_as<T1>(*t2));
+ //assert(can_create_as<T2>(*t2));
+
+ // clone sub-objects
+ W *t2_w = t2->clone_as<W>();
+ T0 *t2_t0 = t2->clone_as<T0>();
+ T1 *t2_t1 = t2->clone_as<T1>();
+ T1 *t2_t2 = t2->clone_as<T2>();
+
+ // create sub-objects
+ W *t2_w_new = t2->create_as<W>();
+ T0 *t2_t0_new = t2->create_as<T0>();
+ T1 *t2_t1_new = t2->create_as<T1>();
+ T2 *t2_t2_new = t2->create_as<T2>();
+
+ delete t2;
+ delete t2_w;
+ delete t2_t0;
+ delete t2_t1;
+ delete t2_t2;
+ delete t2_w_new;
+ delete t2_t0_new;
+ delete t2_t1_new;
+ delete t2_t2_new;
+}
+
 
 BOOST_AUTO_TEST_CASE(test_multiple_inheritance_vector)
 {


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