$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r78465 - in sandbox/type_erasure: boost/type_erasure libs/type_erasure/test
From: steven_at_[hidden]
Date: 2012-05-13 23:44:21
Author: steven_watanabe
Date: 2012-05-13 23:44:19 EDT (Sun, 13 May 2012)
New Revision: 78465
URL: http://svn.boost.org/trac/boost/changeset/78465
Log:
Handle assignment of any references.
Added:
   sandbox/type_erasure/libs/type_erasure/test/fail_cref_assign.cpp   (contents, props changed)
   sandbox/type_erasure/libs/type_erasure/test/fail_ref_assign.cpp   (contents, props changed)
Text files modified: 
   sandbox/type_erasure/boost/type_erasure/any.hpp             |   160 +++++++++++++++++++++++++++++++++++++++-
   sandbox/type_erasure/libs/type_erasure/test/Jamfile.jam     |     3                                         
   sandbox/type_erasure/libs/type_erasure/test/test_assign.cpp |    44 +++++++++++                             
   3 files changed, 203 insertions(+), 4 deletions(-)
Modified: sandbox/type_erasure/boost/type_erasure/any.hpp
==============================================================================
--- sandbox/type_erasure/boost/type_erasure/any.hpp	(original)
+++ sandbox/type_erasure/boost/type_erasure/any.hpp	2012-05-13 23:44:19 EDT (Sun, 13 May 2012)
@@ -1034,19 +1034,133 @@
       : data(::boost::type_erasure::detail::access::data(other)),
         table(binding_arg)
     {}
-
+    
+    /**
+     * Assigns to an @ref any.
+     *
+     * If an appropriate overload of @ref assignable is not available
+     * and @ref relaxed_match is in @c Concept, falls back on
+     * constructing from @c other.
+     *
+     * \throws Whatever the assignment operator of the contained
+     *         type throws.  When falling back on construction,
+     *         throws @c std::bad_alloc.  In this case assignment
+     *         provides the strong exception guarantee.  When
+     *         calling the assignment operator of the contained type,
+     *         the exception guarantee is whatever the contained type provides.
+     */
     any& operator=(const any& other)
     {
-        ::boost::type_erasure::call(assignable<T, T>(), *this, other);
+        _boost_type_erasure_resolve_assign(other);
         return *this;
     }
+    
+    /**
+     * Assigns to an @ref any.
+     *
+     * If an appropriate overload of @ref assignable is not available
+     * and @ref relaxed_match is in @c Concept, falls back on
+     * constructing from @c other.
+     *
+     * \throws Whatever the assignment operator of the contained
+     *         type throws.  When falling back on construction,
+     *         throws @c std::bad_alloc.  In this case assignment
+     *         provides the strong exception guarantee.  When
+     *         calling the assignment operator of the contained type,
+     *         the exception guarantee is whatever the contained type provides.
+     */
     template<class U>
-    any& operator=(const any<Concept, U>& other)
+    any& operator=(U& other)
     {
-        ::boost::type_erasure::call(assignable<T, U>(), *this, other);
+        _boost_type_erasure_resolve_assign(other);
         return *this;
     }
+    
+    /**
+     * Assigns to an @ref any.
+     *
+     * If an appropriate overload of @ref assignable is not available
+     * and @ref relaxed_match is in @c Concept, falls back on
+     * constructing from @c other.
+     *
+     * \throws Whatever the assignment operator of the contained
+     *         type throws.  When falling back on construction,
+     *         throws @c std::bad_alloc.  In this case assignment
+     *         provides the strong exception guarantee.  When
+     *         calling the assignment operator of the contained type,
+     *         the exception guarantee is whatever the contained type provides.
+     */
+    template<class U>
+    any& operator=(const U& other)
+    {
+        _boost_type_erasure_resolve_assign(other);
+        return *this;
+    }
+
 private:
+
+    /** INTERNAL ONLY */
+    void _boost_type_erasure_swap(any& other)
+    {
+        ::std::swap(data, other.data);
+        ::std::swap(table, other.table);
+    }
+    /** INTERNAL ONLY */
+    template<class Other>
+    void _boost_type_erasure_resolve_assign(Other& other)
+    {
+        _boost_type_erasure_assign_impl(
+            other,
+            false? this->_boost_type_erasure_deduce_assign(
+                ::boost::type_erasure::detail::make_fallback(
+                    other,
+                    ::boost::mpl::bool_<
+                        sizeof(
+                            ::boost::type_erasure::detail::check_overload(
+                                ::boost::declval<any&>().
+                                    _boost_type_erasure_deduce_assign(other)
+                            )
+                        ) == sizeof(::boost::type_erasure::detail::yes)
+                    >()
+                )
+            ) : 0,
+            ::boost::type_erasure::is_relaxed<Concept>()
+        );
+    }
+    /** INTERNAL ONLY */
+    template<class Other, class U>
+    void _boost_type_erasure_assign_impl(
+        Other& other,
+        const assignable<T, U>*,
+        ::boost::mpl::false_)
+    {
+        ::boost::type_erasure::call(assignable<T, U>(), *this, other);
+    }
+    /** INTERNAL ONLY */
+    template<class Other, class U>
+    void _boost_type_erasure_assign_impl(
+        Other& other,
+        const assignable<T, U>*,
+        ::boost::mpl::true_)
+    {
+        if(::boost::type_erasure::check_match(assignable<T, U>(), *this, other)) {
+            ::boost::type_erasure::unchecked_call(assignable<T, U>(), *this, other);
+        } else {
+            any temp(other);
+            _boost_type_erasure_swap(temp);
+        }
+    }
+    /** INTERNAL ONLY */
+    template<class Other>
+    void _boost_type_erasure_assign_impl(
+        Other& other,
+        const void*,
+        ::boost::mpl::true_)
+    {
+        any temp(other);
+        _boost_type_erasure_swap(temp);
+    }
+
     friend struct ::boost::type_erasure::detail::access;
     ::boost::type_erasure::detail::storage data;
     table_type table;
@@ -1214,7 +1328,45 @@
       : data(::boost::type_erasure::detail::access::data(other)),
         table(binding_arg)
     {}
+    
+    
+    /**
+     * Assigns to an @ref any.
+     *
+     * \pre @ref relaxed_match is in @c Concept.
+     *
+     * \throws @c Nothing.
+     */
+    any& operator=(const any& other)
+    {
+        BOOST_MPL_ASSERT((::boost::type_erasure::is_relaxed<Concept>));
+        any temp(other);
+        _boost_type_erasure_swap(temp);
+        return *this;
+    }
+    /**
+     * Assigns to an @ref any.
+     *
+     * \pre @ref relaxed_match is in @c Concept.
+     *
+     * \throws @c std::bad_alloc.  Provides the strong exception guarantee.
+     */
+    template<class U>
+    any& operator=(const U& other)
+    {
+        BOOST_MPL_ASSERT((::boost::type_erasure::is_relaxed<Concept>));
+        any temp(other);
+        _boost_type_erasure_swap(temp);
+        return *this;
+    }
+
 private:
+    /** INTERNAL ONLY */
+    void _boost_type_erasure_swap(any& other)
+    {
+        ::std::swap(data, other.data);
+        ::std::swap(table, other.table);
+    }
     friend struct ::boost::type_erasure::detail::access;
     ::boost::type_erasure::detail::storage data;
     table_type table;
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 23:44:19 EDT (Sun, 13 May 2012)
@@ -37,6 +37,9 @@
 compile-fail fail_binding_convert_no_mapping.cpp ;
 compile-fail fail_increment_discard_const.cpp ;
 
+compile-fail fail_ref_assign.cpp ;
+compile-fail fail_cref_assign.cpp ;
+
 compile-fail fail_ref_discard_const.cpp ;
 compile-fail fail_ref_discard_const_convert.cpp ;
 compile-fail fail_ref_discard_const_convert_ref.cpp ;
Added: sandbox/type_erasure/libs/type_erasure/test/fail_cref_assign.cpp
==============================================================================
--- (empty file)
+++ sandbox/type_erasure/libs/type_erasure/test/fail_cref_assign.cpp	2012-05-13 23:44:19 EDT (Sun, 13 May 2012)
@@ -0,0 +1,22 @@
+// Boost.TypeErasure library
+//
+// Copyright 2011 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/any.hpp>
+#include <boost/type_erasure/builtin.hpp>
+#include <boost/mpl/vector.hpp>
+
+using namespace boost::type_erasure;
+
+int main()
+{
+    int i;
+    any<typeid_<>, const _self&> x(i);
+    x = x;
+}
Added: sandbox/type_erasure/libs/type_erasure/test/fail_ref_assign.cpp
==============================================================================
--- (empty file)
+++ sandbox/type_erasure/libs/type_erasure/test/fail_ref_assign.cpp	2012-05-13 23:44:19 EDT (Sun, 13 May 2012)
@@ -0,0 +1,22 @@
+// Boost.TypeErasure library
+//
+// Copyright 2011 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/any.hpp>
+#include <boost/type_erasure/builtin.hpp>
+#include <boost/mpl/vector.hpp>
+
+using namespace boost::type_erasure;
+
+int main()
+{
+    int i;
+    any<typeid_<>, _self&> x(i);
+    x = x;
+}
Modified: sandbox/type_erasure/libs/type_erasure/test/test_assign.cpp
==============================================================================
--- sandbox/type_erasure/libs/type_erasure/test/test_assign.cpp	(original)
+++ sandbox/type_erasure/libs/type_erasure/test/test_assign.cpp	2012-05-13 23:44:19 EDT (Sun, 13 May 2012)
@@ -151,3 +151,47 @@
     x = 2;
     BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
 }
+
+BOOST_AUTO_TEST_CASE(test_basic_ref)
+{
+    typedef ::boost::mpl::vector<common<>, assignable<> > test_concept;
+    int i = 1;
+    any<test_concept, _self&> x(i);
+    any<test_concept> y(2);
+    x = y;
+    BOOST_CHECK_EQUAL(i, 2);
+}
+
+BOOST_AUTO_TEST_CASE(test_basic_relaxed_ref)
+{
+    typedef ::boost::mpl::vector<common<>, assignable<>, relaxed_match > test_concept;
+    int i = 1;
+    any<test_concept, _self&> x(i);
+    any<test_concept> y(2);
+    x = y;
+    BOOST_CHECK_EQUAL(i, 2);
+}
+
+BOOST_AUTO_TEST_CASE(test_relaxed_no_assign_ref)
+{
+    typedef ::boost::mpl::vector<
+        common<>,
+        relaxed_match
+    > test_concept;
+    int i = 1;
+    any<test_concept, _self&> x(i);
+    any<test_concept> y(2);
+    x = y;
+    BOOST_CHECK_EQUAL(i, 1);
+    BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&y));
+}
+
+BOOST_AUTO_TEST_CASE(test_dynamic_fallback_ref)
+{
+    typedef ::boost::mpl::vector<common<>, assignable<>, relaxed_match> test_concept;
+    int i = 1;
+    any<test_concept, _self&> x(i);
+    any<test_concept> y(2.0);
+    x = y;
+    BOOST_CHECK_EQUAL(any_cast<double>(x), 2.0);
+}