Squashed 'third_party/boostorg/move/' content from commit d503fbe

Change-Id: I5f8ac37161a1044b02ffb1f59cf15622fc6acd17
git-subtree-dir: third_party/boostorg/move
git-subtree-split: d503fbe1c8334fa8885e67cb83c96aeaf3938555
diff --git a/test/copy_move_optimization.cpp b/test/copy_move_optimization.cpp
new file mode 100644
index 0000000..06d1847
--- /dev/null
+++ b/test/copy_move_optimization.cpp
@@ -0,0 +1,107 @@
+//We need to declare:
+//
+//2 conversions: rv<T> & and const rv<T> &
+//1 rv<T> & constructor: move constructor
+//1 const rv<T> & constructor: copy constructor
+//1 T & constructor: copy constructor
+//
+//Optimization:
+//Since RVO is better than move-construction,
+//avoid copy constructor overloading.
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/utility_core.hpp>
+#include <iostream>
+
+bool moved = false;
+
+class obj
+{
+   BOOST_COPYABLE_AND_MOVABLE(obj)
+   public:
+
+   obj()
+   {
+      std::cout << "constructing obj" << "\n";
+   }
+
+   ~obj()
+   {}
+
+   obj(const obj &)
+   {
+      std::cout << "copy construct from const obj" << "\n";
+   }
+
+   // copy construct from movable object (non-const rvalue, explicitly moved lvalue)
+   obj(BOOST_RV_REF(obj))
+   {
+      std::cout << "move construct from movable rvalue" << "\n";
+   }
+
+   obj& operator =(BOOST_COPY_ASSIGN_REF(obj))
+   {
+      std::cout << "copy assign from const obj" << "\n";
+      return *this;
+   }
+
+   obj& operator =(BOOST_RV_REF(obj))
+   {
+      std::cout << "move assign from movable rvalue" << "\n";
+      return *this;
+   }
+};
+
+
+obj        rvalue_func()       { return obj(); }
+const obj  const_rvalue_func() { return obj();  }
+obj&       lvalue_func()       { static obj o;  return o; }
+const obj& const_lvalue_func() { static obj o; return o; }
+
+obj produce()     { return obj(); }
+
+void consume(obj){}
+
+int main()
+{
+   {  consume(produce());  }
+   {  obj o = produce();   }
+   {  obj o(produce());    }
+   {
+   obj o1(rvalue_func());
+   obj o2 = const_rvalue_func();
+   obj o3 = lvalue_func();
+   obj o4 = const_lvalue_func();
+   // can't explicitly move temporaries
+   //obj o5 = boost::move(rvalue_func());
+   obj o5;
+   //Maybe missed optimization: copied
+   o5 = rvalue_func();
+   //Explicit forward works OK and optimized
+   o5 = boost::forward<obj>(rvalue_func());
+
+   obj o7 = boost::move(lvalue_func());
+   obj o8 = boost::move(const_lvalue_func());
+
+   obj o;
+   o = rvalue_func();
+   o = const_rvalue_func();
+   o = lvalue_func();
+   o = const_lvalue_func();
+   // can't explicitly move temporaries
+   //o = boost::move(rvalue_func());
+   o = boost::forward<obj>(rvalue_func());
+   o = boost::move(const_rvalue_func());
+   o = boost::move(lvalue_func());
+   o = boost::move(const_lvalue_func());
+   }
+   return 0;
+}
+
+//We need to declare:
+//
+//2 conversions: rv<T> & and const rv<T> &
+//1 rv<T> & constructor: move constructor
+//1 const rv<T> & constructor: copy constructor
+//1 T & constructor: copy constructor
+
+#include <boost/move/detail/config_end.hpp>