Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r78460 - in sandbox/type_erasure: boost/type_erasure boost/type_erasure/detail libs/type_erasure/test
From: steven_at_[hidden]
Date: 2012-05-13 15:58:42


Author: steven_watanabe
Date: 2012-05-13 15:58:42 EDT (Sun, 13 May 2012)
New Revision: 78460
URL: http://svn.boost.org/trac/boost/changeset/78460

Log:
Add tests for binding and fix some bugs that this exposed.
Added:
   sandbox/type_erasure/libs/type_erasure/test/test_binding.cpp (contents, props changed)
Text files modified:
   sandbox/type_erasure/boost/type_erasure/binding.hpp | 168 ++++++++++++++++++++-------------------
   sandbox/type_erasure/boost/type_erasure/detail/vtable.hpp | 6 +
   sandbox/type_erasure/libs/type_erasure/test/Jamfile.jam | 1
   3 files changed, 92 insertions(+), 83 deletions(-)

Modified: sandbox/type_erasure/boost/type_erasure/binding.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/binding.hpp (original)
+++ sandbox/type_erasure/boost/type_erasure/binding.hpp 2012-05-13 15:58:42 EDT (Sun, 13 May 2012)
@@ -15,6 +15,13 @@
 #include <boost/shared_ptr.hpp>
 #include <boost/make_shared.hpp>
 #include <boost/mpl/transform.hpp>
+#include <boost/mpl/find_if.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/end.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/type_traits/is_same.hpp>
 #include <boost/type_erasure/static_binding.hpp>
 #include <boost/type_erasure/detail/adapt_to_vtable.hpp>
 #include <boost/type_erasure/detail/rebind_placeholders.hpp>
@@ -24,6 +31,28 @@
 namespace boost {
 namespace type_erasure {
 
+namespace detail {
+
+template<class Source, class Dest, class Map>
+struct can_optimize_conversion : ::boost::mpl::and_<
+ ::boost::is_same<Source, Dest>,
+ ::boost::is_same<
+ typename ::boost::mpl::find_if<
+ Map,
+ ::boost::mpl::not_<
+ ::boost::is_same<
+ ::boost::mpl::first< ::boost::mpl::_1>,
+ ::boost::mpl::second< ::boost::mpl::_1>
+ >
+ >
+ >::type,
+ typename ::boost::mpl::end<Map>::type
+ >
+ >::type
+{};
+
+}
+
 /**
  * Stores the binding of a @c Concept to a set of actual types.
  * @c Concept is interpreted in the same way as with @ref any.
@@ -51,9 +80,8 @@
      */
     template<class Map>
     explicit binding(const Map&)
- {
- set<Map>();
- }
+ : impl(static_binding<Map>())
+ {}
     
     /**
      * \pre @c Map must be an MPL map with an entry for each placeholder
@@ -63,9 +91,8 @@
      */
     template<class Map>
     binding(const static_binding<Map>&)
- {
- set<Map>();
- }
+ : impl(static_binding<Map>())
+ {}
 
     /**
      * Converts from another set of bindings.
@@ -78,17 +105,12 @@
      */
     template<class Concept2, class Map>
     binding(const binding<Concept2>& other, const Map&)
- : manager(new table_type)
- {
- manager->template convert_from<
- typename ::boost::type_erasure::detail::convert_deductions<
- Map,
- placeholder_subs,
- typename binding<Concept2>::placeholder_subs
- >::type
- >(*other.table);
- table = manager.get();
- }
+ : impl(
+ other,
+ static_binding<Map>(),
+ ::boost::type_erasure::detail::can_optimize_conversion<Concept2, Concept, Map>()
+ )
+ {}
 
     /**
      * Converts from another set of bindings.
@@ -101,51 +123,12 @@
      */
     template<class Concept2, class Map>
     binding(const binding<Concept2>& other, const static_binding<Map>&)
- : manager(new table_type)
- {
- manager->template convert_from<
- typename ::boost::type_erasure::detail::convert_deductions<
- Map,
- placeholder_subs,
- typename binding<Concept2>::placeholder_subs
- >::type
- >(*other.table);
- table = manager.get();
- }
-
-#ifndef BOOST_TYPE_ERASURE_DOXYGEN
-
- /** Special case optimization. */
- template<class Map>
- binding(const binding& other, const Map&)
- : table(other.table)
- {
- table_type t;
- t.template convert_from<
- typename ::boost::type_erasure::detail::convert_deductions<
- Map,
- placeholder_subs,
- placeholder_subs
- >::type
- >(*other.table);
- }
-
- /** Special case optimization. */
- template<class Map>
- binding(const binding& other, const static_binding<Map>&)
- : table(other.table)
- {
- table_type t;
- t.template convert_from<
- typename ::boost::type_erasure::detail::convert_deductions<
- Map,
- placeholder_subs,
- placeholder_subs
- >::type
- >(*other.table);
- }
-
-#endif
+ : impl(
+ other,
+ static_binding<Map>(),
+ ::boost::type_erasure::detail::can_optimize_conversion<Concept2, Concept, Map>()
+ )
+ {}
 
     /**
      * \return true iff the sets of types that the placeholders
@@ -154,7 +137,7 @@
      * \throws Nothing.
      */
     friend bool operator==(const binding& lhs, const binding& rhs)
- { return *lhs.table == *rhs.table; }
+ { return *lhs.impl.table == *rhs.impl.table; }
     
     /**
      * \return true iff the arguments do not map to identical
@@ -167,30 +150,51 @@
 
     /** INTERNAL ONLY */
     template<class T>
- typename T::type find() const { return table->lookup((T*)0); }
+ typename T::type find() const { return impl.table->lookup((T*)0); }
 private:
     template<class C2>
     friend class binding;
     /** INTERNAL ONLY */
- template<class Bindings>
- void set()
+ struct impl_type
     {
- table = &::boost::type_erasure::detail::make_vtable_init<
- typename ::boost::mpl::transform<
- actual_concept,
- ::boost::type_erasure::detail::rebind_placeholders<
- ::boost::mpl::_1,
- typename ::boost::type_erasure::detail::add_deductions<
- Bindings,
- placeholder_subs
- >::type
- >
- >::type,
- table_type
- >::type::value;
- }
- const table_type* table;
- ::boost::shared_ptr<table_type> manager;
+ template<class Map>
+ impl_type(const static_binding<Map>&)
+ {
+ table = &::boost::type_erasure::detail::make_vtable_init<
+ typename ::boost::mpl::transform<
+ actual_concept,
+ ::boost::type_erasure::detail::rebind_placeholders<
+ ::boost::mpl::_1,
+ typename ::boost::type_erasure::detail::add_deductions<
+ Map,
+ placeholder_subs
+ >::type
+ >
+ >::type,
+ table_type
+ >::type::value;
+ }
+ template<class Concept2, class Map>
+ impl_type(const binding<Concept2>& other, const static_binding<Map>&, boost::mpl::false_)
+ : manager(new table_type)
+ {
+ manager->template convert_from<
+ typename ::boost::type_erasure::detail::convert_deductions<
+ Map,
+ placeholder_subs,
+ typename binding<Concept2>::placeholder_subs
+ >::type
+ >(*other.impl.table);
+ table = manager.get();
+ }
+ template<class Concept2, class Map>
+ impl_type(const binding<Concept2>& other, const static_binding<Map>&, boost::mpl::true_)
+ : table(other.impl.table),
+ manager(other.impl.manager)
+ {}
+ const table_type* table;
+ ::boost::shared_ptr<table_type> manager;
+ } impl;
 };
 
 }

Modified: sandbox/type_erasure/boost/type_erasure/detail/vtable.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/detail/vtable.hpp (original)
+++ sandbox/type_erasure/boost/type_erasure/detail/vtable.hpp 2012-05-13 15:58:42 EDT (Sun, 13 May 2012)
@@ -187,7 +187,7 @@
 };
 
 #define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/vtable.hpp>
-#define BOOST_PP_ITERATION_LIMITS (1, BOOST_TYPE_ERASURE_MAX_FUNCTIONS)
+#define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_FUNCTIONS)
 #include BOOST_PP_ITERATE()
 
 #endif
@@ -225,7 +225,11 @@
>::type*)0 \
     );
 
+#if N != 0
 template<BOOST_PP_ENUM_PARAMS(N, class T)>
+#else
+template<class D = void>
+#endif
 struct BOOST_PP_CAT(vtable_storage, N)
 {
     BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_VTABLE_ENTRY, ~)

Modified: sandbox/type_erasure/libs/type_erasure/test/Jamfile.jam
==============================================================================
--- sandbox/type_erasure/libs/type_erasure/test/Jamfile.jam (original)
+++ sandbox/type_erasure/libs/type_erasure/test/Jamfile.jam 2012-05-13 15:58:42 EDT (Sun, 13 May 2012)
@@ -8,6 +8,7 @@
 
 import testing ;
 
+run test_binding.cpp /boost//unit_test_framework ;
 run test_increment.cpp /boost//unit_test_framework ;
 run test_add.cpp /boost//unit_test_framework ;
 run test_add_assign.cpp /boost//unit_test_framework ;

Added: sandbox/type_erasure/libs/type_erasure/test/test_binding.cpp
==============================================================================
--- (empty file)
+++ sandbox/type_erasure/libs/type_erasure/test/test_binding.cpp 2012-05-13 15:58:42 EDT (Sun, 13 May 2012)
@@ -0,0 +1,128 @@
+// Boost.TypeErasure library
+//
+// Copyright 2012 Steven Watanabe
+//
+// 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)
+//
+// $Id$
+
+#include <boost/type_erasure/static_binding.hpp>
+#include <boost/type_erasure/binding.hpp>
+#include <boost/type_erasure/placeholder.hpp>
+#include <boost/type_erasure/builtin.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/map.hpp>
+
+#define BOOST_TEST_MAIN
+#include <boost/test/unit_test.hpp>
+
+using namespace boost::type_erasure;
+
+BOOST_AUTO_TEST_CASE(test_empty_binding)
+{
+ boost::mpl::map<> m1;
+ binding<boost::mpl::vector<> > b1(m1);
+ binding<boost::mpl::vector<> > b2(make_binding<boost::mpl::map<> >());
+ BOOST_CHECK(b1 == b2);
+ BOOST_CHECK(!(b1 != b2));
+
+ boost::mpl::map<boost::mpl::pair<_a, int> > m2;
+ binding<boost::mpl::vector<> > b3(m2);
+ BOOST_CHECK(b3 == b1);
+ BOOST_CHECK(!(b3 != b1));
+ binding<boost::mpl::vector<> > b4(make_binding<boost::mpl::map<boost::mpl::pair<_a, int> > >());
+ BOOST_CHECK(b4 == b1);
+ BOOST_CHECK(!(b4 != b1));
+
+ binding<boost::mpl::vector<> > b5(b1, m1);
+ BOOST_CHECK(b5 == b1);
+ BOOST_CHECK(!(b5 != b1));
+ binding<boost::mpl::vector<> > b6(b1, make_binding<boost::mpl::map<> >());
+ BOOST_CHECK(b6 == b1);
+ BOOST_CHECK(!(b6 != b1));
+
+ boost::mpl::map<boost::mpl::pair<_a, _b> > m3;
+ binding<boost::mpl::vector<> > b7(b1, m3);
+ BOOST_CHECK(b7 == b1);
+ BOOST_CHECK(!(b7 != b1));
+ binding<boost::mpl::vector<> > b8(b1, make_binding<boost::mpl::map<boost::mpl::pair<_a, _b> > >());
+ BOOST_CHECK(b8 == b1);
+ BOOST_CHECK(!(b8 != b1));
+}
+
+BOOST_AUTO_TEST_CASE(test_binding_one)
+{
+ boost::mpl::map<boost::mpl::pair<_a, int> > m1;
+ binding<typeid_<_a> > b1(m1);
+ BOOST_CHECK(b1.find<typeid_<_a> >()() == typeid(int));
+ binding<typeid_<_a> > b2(make_binding<boost::mpl::map<boost::mpl::pair<_a, int> > >());
+ BOOST_CHECK(b2.find<typeid_<_a> >()() == typeid(int));
+ BOOST_CHECK(b1 == b2);
+ BOOST_CHECK(!(b1 != b2));
+
+ boost::mpl::map<boost::mpl::pair<_a, _a> > m2;
+ binding<typeid_<_a> > b3(b1, m2);
+ BOOST_CHECK(b3.find<typeid_<_a> >()() == typeid(int));
+ BOOST_CHECK(b3 == b1);
+ BOOST_CHECK(!(b3 != b1));
+ binding<typeid_<_a> > b4(b1, make_binding<boost::mpl::map<boost::mpl::pair<_a, _a> > >());
+ BOOST_CHECK(b4.find<typeid_<_a> >()() == typeid(int));
+ BOOST_CHECK(b4 == b1);
+ BOOST_CHECK(!(b4 != b1));
+
+ boost::mpl::map<boost::mpl::pair<_b, _a> > m3;
+ binding<typeid_<_b> > b5(b1, m3);
+ BOOST_CHECK(b5.find<typeid_<_b> >()() == typeid(int));
+ binding<typeid_<_b> > b6(b1, make_binding<boost::mpl::map<boost::mpl::pair<_b, _a> > >());
+ BOOST_CHECK(b6.find<typeid_<_b> >()() == typeid(int));
+}
+
+BOOST_AUTO_TEST_CASE(test_binding_two)
+{
+ boost::mpl::map<boost::mpl::pair<_a, int>, boost::mpl::pair<_b, char> > m1;
+ binding<boost::mpl::vector<typeid_<_a>, typeid_<_b> > > b1(m1);
+ BOOST_CHECK(b1.find<typeid_<_a> >()() == typeid(int));
+ BOOST_CHECK(b1.find<typeid_<_b> >()() == typeid(char));
+ binding<boost::mpl::vector<typeid_<_a>, typeid_<_b> > > b2(
+ make_binding<boost::mpl::map<boost::mpl::pair<_a, int>, boost::mpl::pair<_b, char> > >());
+ BOOST_CHECK(b2.find<typeid_<_a> >()() == typeid(int));
+ BOOST_CHECK(b2.find<typeid_<_b> >()() == typeid(char));
+ BOOST_CHECK(b1 == b2);
+ BOOST_CHECK(!(b1 != b2));
+
+ // select the first
+ boost::mpl::map<boost::mpl::pair<_a, _a> > m2;
+ binding<typeid_<_a> > b3(b1, m2);
+ BOOST_CHECK(b3.find<typeid_<_a> >()() == typeid(int));
+ binding<typeid_<_a> > b4(b1, make_binding<boost::mpl::map<boost::mpl::pair<_a, _a> > >());
+ BOOST_CHECK(b4.find<typeid_<_a> >()() == typeid(int));
+
+ // select the second
+ boost::mpl::map<boost::mpl::pair<_b, _b> > m3;
+ binding<typeid_<_b> > b5(b1, m3);
+ BOOST_CHECK(b5.find<typeid_<_b> >()() == typeid(char));
+ binding<typeid_<_b> > b6(b1, make_binding<boost::mpl::map<boost::mpl::pair<_b, _b> > >());
+ BOOST_CHECK(b6.find<typeid_<_b> >()() == typeid(char));
+
+ // rename both
+ boost::mpl::map<boost::mpl::pair<_c, _a>, boost::mpl::pair<_d, _b> > m4;
+ binding<boost::mpl::vector<typeid_<_c>, typeid_<_d> > > b7(b1, m4);
+ BOOST_CHECK(b7.find<typeid_<_c> >()() == typeid(int));
+ BOOST_CHECK(b7.find<typeid_<_d> >()() == typeid(char));
+ binding<boost::mpl::vector<typeid_<_c>, typeid_<_d> > > b8(b1,
+ make_binding<boost::mpl::map<boost::mpl::pair<_c, _a>, boost::mpl::pair<_d, _b> > >());
+ BOOST_CHECK(b8.find<typeid_<_c> >()() == typeid(int));
+ BOOST_CHECK(b8.find<typeid_<_d> >()() == typeid(char));
+
+ // switch the placeholders
+ boost::mpl::map<boost::mpl::pair<_a, _b>, boost::mpl::pair<_b, _a> > m5;
+ binding<boost::mpl::vector<typeid_<_a>, typeid_<_b> > > b9(b1, m5);
+ BOOST_CHECK(b9.find<typeid_<_b> >()() == typeid(int));
+ BOOST_CHECK(b9.find<typeid_<_a> >()() == typeid(char));
+ binding<boost::mpl::vector<typeid_<_a>, typeid_<_b> > > b10(b1,
+ make_binding<boost::mpl::map<boost::mpl::pair<_a, _b>, boost::mpl::pair<_b, _a> > >());
+ BOOST_CHECK(b10.find<typeid_<_b> >()() == typeid(int));
+ BOOST_CHECK(b10.find<typeid_<_a> >()() == typeid(char));
+}


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