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