|
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