Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r54561 - in sandbox/cloneable: boost/cloneable boost/cloneable/detail libs/cloneable/test
From: christian.schladetsch_at_[hidden]
Date: 2009-07-01 06:15:59


Author: cschladetsch
Date: 2009-07-01 06:15:58 EDT (Wed, 01 Jul 2009)
New Revision: 54561
URL: http://svn.boost.org/trac/boost/changeset/54561

Log:
added list.hpp

Added:
   sandbox/cloneable/boost/cloneable/list.hpp (contents, props changed)
Text files modified:
   sandbox/cloneable/boost/cloneable/abstract_base.hpp | 45 +++++++++++++++++++++++++++++++--------
   sandbox/cloneable/boost/cloneable/allocator.hpp | 1
   sandbox/cloneable/boost/cloneable/detail/allocation.hpp | 5 +++
   sandbox/cloneable/boost/cloneable/forward_declarations.hpp | 17 +++++++++++++++
   sandbox/cloneable/boost/cloneable/set.hpp | 25 +++++++++++++++-------
   sandbox/cloneable/libs/cloneable/test/cloneable.vcproj | 4 +++
   sandbox/cloneable/libs/cloneable/test/tests.cpp | 18 ++++++++++++++++
   7 files changed, 95 insertions(+), 20 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-01 06:15:58 EDT (Wed, 01 Jul 2009)
@@ -16,12 +16,42 @@
 {
         namespace cloneable
         {
- /// default base type used for object hierarchies to be stored in a given
- /// container or containers. the user can supply their own when using
- /// cloneable<Derived, Base> this will be used by default.
- struct default_base_type
+ 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 default_base_type : abstract_object<default_base_type>
                 {
                         virtual ~default_base_type() { }
+
+ std::string to_string() const { return "default_base_type"; }
+ size_t hash_value() const { return 0; }
+ bool less(const default_base_type &other) const { return false; }
                 };
 
                 /// root structure for the cloneable object system
@@ -119,15 +149,10 @@
                         /// overridable to-string function, for utility
                         virtual std::string to_string() const { return "cloneable"; }
 
- /// overridable hash function, for utility
- virtual size_t hash_value() const { return 0; }
-
                         /// return a hash value for the object
                         size_t hash() const
                         {
- if (size_t value = hash_value())
- return value;
- return 0;//ptrdiff_t(reinterpret_cast<const char *>(this) - 0);
+ return base_type::hash_value();
                         }
 
                 };

Modified: sandbox/cloneable/boost/cloneable/allocator.hpp
==============================================================================
--- sandbox/cloneable/boost/cloneable/allocator.hpp (original)
+++ sandbox/cloneable/boost/cloneable/allocator.hpp 2009-07-01 06:15:58 EDT (Wed, 01 Jul 2009)
@@ -100,7 +100,6 @@
                         typename Alloc::template rebind<T>::other al(alloc);
                         al.destroy(ptr);
                         al.deallocate(ptr, 1);
- return ptr;
                 }
 
         } // namespace cloneable

Modified: sandbox/cloneable/boost/cloneable/detail/allocation.hpp
==============================================================================
--- sandbox/cloneable/boost/cloneable/detail/allocation.hpp (original)
+++ sandbox/cloneable/boost/cloneable/detail/allocation.hpp 2009-07-01 06:15:58 EDT (Wed, 01 Jul 2009)
@@ -20,7 +20,10 @@
                         U *allocate(Alloc &al)
                         {
                                 typename Alloc::template rebind<U>::other alloc(al);
- return alloc.allocate(1);
+ U *ptr = alloc.allocate(1);
+ if (ptr == 0)
+ throw std::bad_alloc();
+ return ptr;
                         }
 
                         // TODO: use variadic template arguments, or BOOST_PP

Modified: sandbox/cloneable/boost/cloneable/forward_declarations.hpp
==============================================================================
--- sandbox/cloneable/boost/cloneable/forward_declarations.hpp (original)
+++ sandbox/cloneable/boost/cloneable/forward_declarations.hpp 2009-07-01 06:15:58 EDT (Wed, 01 Jul 2009)
@@ -8,10 +8,19 @@
 
 #include <functional>
 #include <memory>
+#include <boost/scope_exit.hpp>
 #include <boost/cloneable/detail/prefix.hpp>
 
+#define BOOST_CLONEABLE_SCOPE_EXIT(locals) \
+ this_type *self = this; \
+ BOOST_SCOPE_EXIT(locals(self))
+
+#define BOOST_CLONEABLE_SCOPE_EXIT_END \
+ BOOST_SCOPE_EXIT_END
+
 namespace boost
 {
+
         namespace cloneable
         {
                 typedef std::allocator<char> default_allocator;
@@ -61,6 +70,14 @@
>
                 struct vector;
 
+ /// a heterogenous list of objects
+ template
+ <
+ class Base = default_base_type
+ , class Alloc = monotonic::allocator<int>
+ >
+ struct list;
+
                 /// a mapping of heterogenous objects to heterogenous objects
                 template
                 <

Added: sandbox/cloneable/boost/cloneable/list.hpp
==============================================================================
--- (empty file)
+++ sandbox/cloneable/boost/cloneable/list.hpp 2009-07-01 06:15:58 EDT (Wed, 01 Jul 2009)
@@ -0,0 +1,224 @@
+// 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_LIST_HPP
+#define BOOST_CLONEABLE_LIST_HPP
+
+#include <boost/ptr_container/ptr_list.hpp>
+#include <boost/foreach.hpp>
+
+#include <boost/cloneable/detail/prefix.hpp>
+#include <boost/cloneable/detail/make_clone_allocator.hpp>
+#include <boost/cloneable/base.hpp>
+#include <boost/cloneable/traits.hpp>
+#include <boost/cloneable/detail/allocation.hpp>
+
+namespace boost
+{
+ namespace cloneable
+ {
+ /// a list of heterogenous objects
+ // TODO: move to boost/heterogenous/list
+ template <class Base, class Alloc>
+ struct list
+ {
+ typedef Base base_type;
+ typedef abstract_base<Base> abstract_base_type;
+ typedef typename detail::make_clone_allocator<Alloc>::type allocator_type;
+ typedef ptr_list<abstract_base_type, allocator, allocator_type> implementation;
+ typedef typename implementation::value_type value_type;
+ typedef typename implementation::reference reference;
+ typedef typename implementation::const_reference const_reference;
+ typedef typename implementation::iterator iterator;
+ typedef typename implementation::const_iterator const_iterator;
+
+ // this provides better information from errors than otherwise
+ template <class T>
+ struct validate
+ {
+ // can only add cloneable things to a heterogenous container
+ BOOST_STATIC_ASSERT(is_cloneable<T>::value);
+
+ typedef is_same<typename traits<T>::abstract_base_type, abstract_base_type> same_type;
+
+ // you must ensure that base-types for objects that you add to a container
+ // is the same base used by the container
+ BOOST_STATIC_ASSERT(same_type::value);
+
+ typedef typename traits<T>::derived_type type;
+ };
+
+ private:
+ implementation impl;
+
+ public:
+ list()
+ {
+ }
+
+ list(allocator_type &a)
+ : impl(a)
+ {
+ }
+
+ //purposefully elided
+ //template <class II>
+ //list(II F, II L, allocator_type a = allocator_type());
+ //list(size_t reserved);
+
+ template <class Ty, class Fun>
+ Fun for_each(Fun fun)
+ {
+ BOOST_FOREACH(base_type &b, *this)
+ {
+ if (Ty *ptr = dynamic_cast<Ty *>(&b))
+ {
+ fun(*ptr);
+ }
+ }
+ return fun;
+ }
+
+ template <class Ty, class Fun>
+ Fun for_each(Fun fun) const
+ {
+ BOOST_FOREACH(const base_type &base, *this)
+ {
+ if (Ty *ptr = dynamic_cast<Ty *>(&base))
+ {
+ fun(*ptr);
+ }
+ }
+ return fun;
+ }
+
+ size_t size() const
+ {
+ return impl.size();
+ }
+ bool empty() const
+ {
+ return impl.empty();
+ }
+
+ iterator begin()
+ {
+ return impl.begin();
+ }
+ iterator end()
+ {
+ return impl.end();
+ }
+ const_iterator begin() const
+ {
+ return impl.begin();
+ }
+ const_iterator end() const
+ {
+ return impl.end();
+ }
+
+ value_type &back()
+ {
+ return impl.back();
+ }
+ const value_type &back() const
+ {
+ return impl.back();
+ }
+ value_type &front()
+ {
+ return impl.front();
+ }
+ const value_type &front() const
+ {
+ return impl.front();
+ }
+
+ template <class Other>
+ Other &ref_back()
+ {
+ BOOST_STATIC_ASSERT(is_cloneable<Other>::value);
+ Other *ptr = dynamic_cast<Other *>(back());
+ if (ptr == 0)
+ throw std::bad_cast();
+ return *ptr;
+ }
+ template <class Other>
+ Other &ref_front()
+ {
+ Other *ptr = dynamic_cast<Other *>(front());
+ if (ptr == 0)
+ throw std::bad_cast();
+ return *ptr;
+ }
+
+ // TODO: use variadic arguments or BOOST_PP to pass ctor args
+ template <class U>
+ void emplace_back()
+ {
+ typedef typename validate<U>::type value;
+ impl.push_back(detail::construct<value,base_type>(get_allocator()).to_abstract());
+ }
+ template <class U, class A0>
+ void emplace_back(A0 a0)
+ {
+ typedef typename validate<U>::type value;
+ impl.push_back(detail::construct<value,base_type>(get_allocator(), a0).to_abstract());
+ }
+ template <class U, class A0, class A1>
+ void emplace_back(A0 a0, A1 a1)
+ {
+ typedef validate<U>::type value;
+ impl.push_back(detail::construct<value,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)
+ {
+ typedef typename validate<U>::type value;
+ impl.push_back(detail::construct<value,base_type>(get_allocator(), a0,a1,a2).to_abstract());
+ }
+
+ template <class U>
+ void emplace_front()
+ {
+ typedef typename validate<U>::type value;
+ impl.push_front(detail::construct<value,base_type>(get_allocator()).to_abstract());
+ }
+ template <class U, class A0>
+ void emplace_front(A0 a0)
+ {
+ typedef validate<U> valid;
+ impl.push_front(detail::construct<U,base_type>(get_allocator(), a0).to_abstract());
+ }
+ template <class U, class A0, class A1>
+ void emplace_front(A0 a0, A1 a1)
+ {
+ typedef validate<U> valid;
+ impl.push_front(detail::construct<U,base_type>(get_allocator(), a0,a1).to_abstract());
+ }
+ template <class U, class A0, class A1, class A2>
+ void emplace_front(A0 a0, A1 a1, A2 a2)
+ {
+ typedef validate<U> valid;
+ impl.push_front(detail::construct<U,base_type>(get_allocator(), a0,a1,a2).to_abstract());
+ }
+
+ typename implementation::allocator_type get_allocator()
+ {
+ return impl.get_allocator();
+ }
+ };
+
+ } // namespace cloneable
+
+} // namespace boost
+
+#include <boost/cloneable/detail/suffix.hpp>
+
+#endif // BOOST_CLONEABLE_LIST_HPP
+
+//EOF
+

Modified: sandbox/cloneable/boost/cloneable/set.hpp
==============================================================================
--- sandbox/cloneable/boost/cloneable/set.hpp (original)
+++ sandbox/cloneable/boost/cloneable/set.hpp 2009-07-01 06:15:58 EDT (Wed, 01 Jul 2009)
@@ -10,13 +10,14 @@
 #include <boost/foreach.hpp>
 
 #include <boost/cloneable/detail/make_clone_allocator.hpp>
+#include <boost/cloneable/allocator.hpp>
 
 namespace boost
 {
         namespace cloneable
         {
                 /// a vector of heterogenous objects
- // TODO: move to boost/heterogenous/map
+ // TODO: move to boost/heterogenous/set.hpp, or boost/cloneable/containers/set.hpp
                 template <class Base, class Pred, class Alloc>
                 struct set
                 {
@@ -32,7 +33,7 @@
                         typedef typename implementation::const_reference const_reference;
                         typedef typename implementation::iterator iterator;
                         typedef typename implementation::const_iterator const_iterator;
- typedef map<Base, Pred, Alloc/*, AbstractBase*/> this_type;
+ typedef set<Base, Pred, Alloc> this_type;
 
                 private:
                         implementation impl;
@@ -55,7 +56,7 @@
                 public:
                         typedef std::pair<iterator, bool> emplace_result;
                         template <class U>
- emplace_result emplace()
+ emplace_result emplace_insert()
                         {
                                 abstract_base_type *instance = detail::construct<U,base_type>(get_allocator()).to_abstract();
                                 return impl.insert(instance);
@@ -63,19 +64,19 @@
 
                         // TODO: use variadic arguments or BOOST_PP to pass ctor args
                         template <class U, class A0>
- emplace_result emplace(A0 a0)
+ emplace_result emplace_insert(A0 a0)
                         {
                                 abstract_base_type *instance = detail::construct<U,base_type>(get_allocator(), a0).to_abstract();
                                 return impl.insert(instance);
                         }
                         template <class U, class A0, class A1>
- emplace_result emplace(A0 a0, A1 a1)
+ emplace_result emplace_insert(A0 a0, A1 a1)
                         {
                                 abstract_base_type *instance = detail::construct<U,base_type>(get_allocator(), a0, a1).to_abstract();
                                 return impl.insert(instance);
                         }
                         template <class U, class A0, class A1, class A2>
- emplace_result emplace(A0 a0, A1 a1, A2 a2)
+ emplace_result emplace_insert(A0 a0, A1 a1, A2 a2)
                         {
                                 abstract_base_type *instance = detail::construct<U,base_type>(get_allocator(), a0, a1, a2).to_abstract();
                                 return impl.insert(instance);
@@ -116,9 +117,17 @@
                                 return impl.end();
                         }
 
- iterator find(value_type const &key)
+ template <class U, class A0>
+ iterator find(A0 a0) // strong
                         {
- return impl.find(key);
+ abstract_base_type *instance = 0;
+ instance = detail::construct<U,base_type>(get_allocator(), a0).to_abstract();
+ BOOST_CLONEABLE_SCOPE_EXIT((instance))
+ {
+ cloneable::release(instance, self->get_allocator());
+ }
+ BOOST_CLONEABLE_SCOPE_EXIT_END
+ return impl.find(*instance);
                         }
 
                         typename implementation::allocator_type get_allocator()

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-01 06:15:58 EDT (Wed, 01 Jul 2009)
@@ -234,6 +234,10 @@
                                         Name="containers"
>
                                         <File
+ RelativePath="..\..\..\boost\cloneable\list.hpp"
+ >
+ </File>
+ <File
                                                 RelativePath="..\..\..\boost\cloneable\map.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-01 06:15:58 EDT (Wed, 01 Jul 2009)
@@ -23,6 +23,7 @@
 
 #include <boost/cloneable/clone.hpp>
 #include <boost/cloneable/vector.hpp>
+#include <boost/cloneable/list.hpp>
 #include <boost/cloneable/map.hpp>
 #include <boost/cloneable/set.hpp>
 
@@ -404,6 +405,22 @@
         }
 }
 
+BOOST_AUTO_TEST_CASE(test_list)
+{
+ typedef cloneable::list<my_base> list;
+ list l0;
+ l0.emplace_back<T0>(42);
+ l0.emplace_back<T1>("foo");
+ l0.emplace_back<T2>(3.14f, -123, "spam");
+ l0.emplace_back<cloneable_external_type>("external");
+ list l1 = l0;
+ list::iterator iter = l1.begin();
+ BOOST_ASSERT(typeid(*iter++) == typeid(T0));
+ BOOST_ASSERT(typeid(*iter++) == typeid(T1));
+ BOOST_ASSERT(typeid(*iter++) == typeid(T2));
+ BOOST_ASSERT(typeid(*iter++) == typeid(cloneable_external_type));
+}
+
 namespace map_test
 {
         struct my_base
@@ -556,5 +573,6 @@
         BOOST_ASSERT(set.find<S0>(1) != set.end());
 }
 
+
 //EOF
  
\ No newline at end of file


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