$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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)
 {