Boost logo

Boost-Commit :

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);
+}


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