Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80552 - in trunk: boost/function libs/function/test
From: antoshkka_at_[hidden]
Date: 2012-09-17 00:08:19


Author: apolukhin
Date: 2012-09-17 00:08:18 EDT (Mon, 17 Sep 2012)
New Revision: 80552
URL: http://svn.boost.org/trac/boost/changeset/80552

Log:
Add move assignment and move constructors to Boost.Function (refs #7330)
Text files modified:
   trunk/boost/function/function_template.hpp | 51 +++++++++++++++++++++
   trunk/libs/function/test/function_test.cpp | 91 ++++++++++++++++++++++++++++++++++++++++
   2 files changed, 141 insertions(+), 1 deletions(-)

Modified: trunk/boost/function/function_template.hpp
==============================================================================
--- trunk/boost/function/function_template.hpp (original)
+++ trunk/boost/function/function_template.hpp 2012-09-17 00:08:18 EDT (Mon, 17 Sep 2012)
@@ -748,7 +748,14 @@
     {
       this->assign_to_own(f);
     }
-
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
+ {
+ this->move_assign(f);
+ }
+#endif
+
     ~BOOST_FUNCTION_FUNCTION() { clear(); }
 
     result_type operator()(BOOST_FUNCTION_PARMS) const
@@ -830,6 +837,26 @@
       BOOST_CATCH_END
       return *this;
     }
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ // Move assignment from another BOOST_FUNCTION_FUNCTION
+ BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
+ {
+
+ if (&f == this)
+ return *this;
+
+ this->clear();
+ BOOST_TRY {
+ this->move_assign(f);
+ } BOOST_CATCH (...) {
+ vtable = 0;
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return *this;
+ }
+#endif
 
     void swap(BOOST_FUNCTION_FUNCTION& other)
     {
@@ -1063,12 +1090,26 @@
 
   function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
 
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ // Move constructors
+ function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
+ function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
+#endif
+
   self_type& operator=(const self_type& f)
   {
     self_type(f).swap(*this);
     return *this;
   }
 
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ self_type& operator=(self_type&& f)
+ {
+ self_type(static_cast<self_type&&>(f)).swap(*this);
+ return *this;
+ }
+#endif
+
   template<typename Functor>
 #ifndef BOOST_NO_SFINAE
   typename enable_if_c<
@@ -1097,6 +1138,14 @@
     self_type(f).swap(*this);
     return *this;
   }
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ self_type& operator=(base_type&& f)
+ {
+ self_type(static_cast<base_type&&>(f)).swap(*this);
+ return *this;
+ }
+#endif
 };
 
 #undef BOOST_FUNCTION_PARTIAL_SPEC

Modified: trunk/libs/function/test/function_test.cpp
==============================================================================
--- trunk/libs/function/test/function_test.cpp (original)
+++ trunk/libs/function/test/function_test.cpp 2012-09-17 00:08:18 EDT (Mon, 17 Sep 2012)
@@ -690,6 +690,95 @@
   test_call_cref(std::plus<int>());
 }
 
+struct big_aggregating_structure {
+ int disable_small_objects_optimizations[32];
+
+ big_aggregating_structure()
+ {
+ ++ global_int;
+ }
+
+ big_aggregating_structure(const big_aggregating_structure&)
+ {
+ ++ global_int;
+ }
+
+ ~big_aggregating_structure()
+ {
+ -- global_int;
+ }
+
+ void operator()()
+ {
+ ++ global_int;
+ }
+
+ void operator()(int)
+ {
+ ++ global_int;
+ }
+};
+
+template <class FunctionT>
+static void test_move_semantics()
+{
+ typedef FunctionT f1_type;
+
+ big_aggregating_structure obj;
+
+ f1_type f1 = obj;
+ global_int = 0;
+ f1();
+
+ BOOST_CHECK(!f1.empty());
+ BOOST_CHECK(global_int == 1);
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ // Testing rvalue constructors
+ f1_type f2(static_cast<f1_type&&>(f1));
+ BOOST_CHECK(f1.empty());
+ BOOST_CHECK(!f2.empty());
+ BOOST_CHECK(global_int == 1);
+ f2();
+ BOOST_CHECK(global_int == 2);
+
+ f1_type f3(static_cast<f1_type&&>(f2));
+ BOOST_CHECK(f1.empty());
+ BOOST_CHECK(f2.empty());
+ BOOST_CHECK(!f3.empty());
+ BOOST_CHECK(global_int == 2);
+ f3();
+ BOOST_CHECK(global_int == 3);
+
+ // Testing move assignment
+ f1_type f4;
+ BOOST_CHECK(f4.empty());
+ f4 = static_cast<f1_type&&>(f3);
+ BOOST_CHECK(f1.empty());
+ BOOST_CHECK(f2.empty());
+ BOOST_CHECK(f3.empty());
+ BOOST_CHECK(!f4.empty());
+ BOOST_CHECK(global_int == 3);
+ f4();
+ BOOST_CHECK(global_int == 4);
+
+ // Testing self move assignment
+ f4 = static_cast<f1_type&&>(f4);
+ BOOST_CHECK(!f4.empty());
+ BOOST_CHECK(global_int == 4);
+
+ // Testing, that no memory leaked when assigning to nonempty function
+ f4 = obj;
+ BOOST_CHECK(!f4.empty());
+ BOOST_CHECK(global_int == 4);
+ f1_type f5 = obj;
+ BOOST_CHECK(global_int == 5);
+ f4 = static_cast<f1_type&&>(f5);
+ BOOST_CHECK(global_int == 4);
+
+#endif
+}
+
 int test_main(int, char* [])
 {
   test_zero_args();
@@ -702,6 +791,8 @@
   test_exception();
   test_implicit();
   test_call();
+ test_move_semantics<function<void()> >();
+ test_move_semantics<boost::function0<void> >();
 
   return 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