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/Jamfile.v2 b/test/Jamfile.v2
new file mode 100644
index 0000000..472517b
--- /dev/null
+++ b/test/Jamfile.v2
@@ -0,0 +1,29 @@
+##############################################################################
+##
+## (C) Copyright Ion Gaztanaga 2008-2009 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)
+##
+##
+##############################################################################
+
+import testing ;
+
+rule test_all
+{
+   local all_rules = ;
+
+   for local fileb in [ glob *.cpp ]
+   {
+      all_rules += [ run $(fileb) /boost/timer//boost_timer
+      :  # additional args
+      :  # test-files
+      :  # requirements
+      ] ;
+   }
+
+   return $(all_rules) ;
+}
+
+test-suite move_test : [ test_all r ] ;
+ 
diff --git a/test/adaptive_merge_test.cpp b/test/adaptive_merge_test.cpp
new file mode 100644
index 0000000..9522625
--- /dev/null
+++ b/test/adaptive_merge_test.cpp
@@ -0,0 +1,80 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <cstdlib>   //std::srand
+#include <iostream>  //std::cout
+
+#include <boost/config.hpp>
+
+#include <boost/move/unique_ptr.hpp>
+#include <boost/move/algo/detail/merge_sort.hpp>
+
+#include "order_type.hpp"
+#include "random_shuffle.hpp"
+
+#include <boost/move/algo/adaptive_merge.hpp>
+#include <boost/move/core.hpp>
+
+
+template<class T>
+bool test_random_shuffled(std::size_t const element_count, std::size_t const num_keys, std::size_t const num_iter)
+{
+   boost::movelib::unique_ptr<T[]> elements(new T[element_count]);
+   boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[num_keys ? num_keys : element_count]);
+   std::cout << "- - N: " << element_count << ", Keys: " << num_keys << ", It: " << num_iter << " \n";
+
+   //Initialize keys
+   for(std::size_t  i=0; i < element_count; ++i){
+      std::size_t  key = num_keys ? (i % num_keys) : i;
+      elements[i].key=key;
+   }
+
+   std::srand(0);
+
+   for (std::size_t i = 0; i != num_iter; ++i)
+   {
+      ::random_shuffle(elements.get(), elements.get() + element_count);
+      for(std::size_t i = 0; i < (num_keys ? num_keys : element_count); ++i){
+         key_reps[i]=0;
+      }
+      for(std::size_t i = 0; i < element_count; ++i){
+         elements[i].val = key_reps[elements[i].key]++;
+      }
+
+      boost::movelib::unique_ptr<char[]> buf(new char [sizeof(T)*(element_count-element_count/2)]);
+
+      std::size_t const split = std::size_t(std::rand()) % element_count;
+      boost::movelib::merge_sort(elements.get(), elements.get()+split, order_type_less(), (T*)buf.get());
+      boost::movelib::merge_sort(elements.get()+split, elements.get()+element_count, order_type_less(), (T*)buf.get());
+      
+      boost::movelib::adaptive_merge(elements.get(), elements.get()+split, elements.get()+element_count, order_type_less());
+
+      if (!is_order_type_ordered(elements.get(), element_count))
+      {
+         std::cout <<  "\n ERROR\n";
+         throw int(0);
+      }
+   }
+   return true;
+}
+
+int main()
+{
+   const std::size_t NIter = 100;
+   test_random_shuffled<order_move_type>(10001, 3,    NIter);
+   test_random_shuffled<order_move_type>(10001, 65,   NIter);
+   test_random_shuffled<order_move_type>(10001, 101,  NIter);
+   test_random_shuffled<order_move_type>(10001, 1023, NIter);
+   test_random_shuffled<order_move_type>(10001, 4095, NIter);
+   test_random_shuffled<order_move_type>(10001, 0,    NIter);
+
+   return 0;
+}
diff --git a/test/adaptive_sort_test.cpp b/test/adaptive_sort_test.cpp
new file mode 100644
index 0000000..686b4bd
--- /dev/null
+++ b/test/adaptive_sort_test.cpp
@@ -0,0 +1,73 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <cstdlib>   //std::srand
+#include <iostream>  //std::cout
+
+#include <boost/config.hpp>
+
+#include <boost/move/unique_ptr.hpp>
+#include <boost/container/vector.hpp>
+
+#include "order_type.hpp"
+#include "random_shuffle.hpp"
+
+#include <boost/move/algo/adaptive_sort.hpp>
+#include <boost/move/core.hpp>
+
+template<class T>
+bool test_random_shuffled(std::size_t const element_count, std::size_t const num_keys, std::size_t const num_iter)
+{
+   boost::movelib::unique_ptr<T[]> elements(new T[element_count]);
+   boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[num_keys ? num_keys : element_count]);
+   std::cout << "- - N: " << element_count << ", Keys: " << num_keys << ", It: " << num_iter << " \n";
+
+   //Initialize keys
+   for(std::size_t  i=0; i < element_count; ++i){
+      std::size_t  key = num_keys ? (i % num_keys) : i;
+      elements[i].key=key;
+   }
+
+   std::srand(0);
+
+   for (std::size_t i = 0; i != num_iter; ++i)
+   {
+      ::random_shuffle(elements.get(), elements.get() + element_count);
+      for(std::size_t i = 0; i < (num_keys ? num_keys : element_count); ++i){
+         key_reps[i]=0;
+      }
+      for(std::size_t i = 0; i < element_count; ++i){
+         elements[i].val = key_reps[elements[i].key]++;
+      }
+
+      boost::movelib::adaptive_sort(elements.get(), elements.get()+element_count, order_type_less());
+
+      if (!is_order_type_ordered(elements.get(), element_count))
+      {
+         std::cout <<  "\n ERROR\n";
+         throw int(0);
+      }
+   }
+   return true;
+}
+
+int main()
+{
+   const std::size_t NIter = 100;
+   test_random_shuffled<order_move_type>(10001, 3,   NIter);
+   test_random_shuffled<order_move_type>(10001, 65,   NIter);
+   test_random_shuffled<order_move_type>(10001, 101,  NIter);
+   test_random_shuffled<order_move_type>(10001, 1023, NIter);
+   test_random_shuffled<order_move_type>(10001, 4095, NIter);
+   test_random_shuffled<order_move_type>(10001, 0,    NIter);
+
+   return 0;
+}
diff --git a/test/adl_move_swap.cpp b/test/adl_move_swap.cpp
new file mode 100644
index 0000000..200c6cb
--- /dev/null
+++ b/test/adl_move_swap.cpp
@@ -0,0 +1,169 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2014.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/core.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+class swap_stats
+{
+   public:
+   static void reset_stats()
+   {
+      member_swap_calls = 0;
+      friend_swap_calls = 0;
+      move_cnstor_calls = 0;
+      move_assign_calls = 0;
+      copy_cnstor_calls = 0;
+      copy_assign_calls = 0;
+   }
+
+   static unsigned int member_swap_calls;
+   static unsigned int friend_swap_calls;
+   static unsigned int move_cnstor_calls;
+   static unsigned int move_assign_calls;
+   static unsigned int copy_cnstor_calls;
+   static unsigned int copy_assign_calls;
+};
+
+unsigned int swap_stats::member_swap_calls = 0;
+unsigned int swap_stats::friend_swap_calls = 0;
+unsigned int swap_stats::move_cnstor_calls = 0;
+unsigned int swap_stats::move_assign_calls = 0;
+unsigned int swap_stats::copy_cnstor_calls = 0;
+unsigned int swap_stats::copy_assign_calls = 0;
+
+class movable : public swap_stats
+{
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(movable)
+   public:
+   movable()                                 {}
+   movable(BOOST_RV_REF(movable))            { ++move_cnstor_calls; }
+   movable & operator=(BOOST_RV_REF(movable)){ ++move_assign_calls; return *this; }
+   friend void swap(movable &, movable &)    { ++friend_swap_calls; }
+};
+
+class movable_swap_member : public swap_stats
+{
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_swap_member)
+   public:
+   movable_swap_member()                                             {}
+   movable_swap_member(BOOST_RV_REF(movable_swap_member))            { ++move_cnstor_calls; }
+   movable_swap_member & operator=(BOOST_RV_REF(movable_swap_member)){ ++move_assign_calls; return *this; }
+   void swap(movable_swap_member &)                                  { ++member_swap_calls; }
+   friend void swap(movable_swap_member &, movable_swap_member &)    { ++friend_swap_calls; }
+};
+
+class copyable : public swap_stats
+{
+   public:
+   copyable()                                {}
+   copyable(const copyable &)                { ++copy_cnstor_calls; }
+   copyable & operator=(const copyable&)     { ++copy_assign_calls; return *this; }
+   void swap(copyable &)                     { ++member_swap_calls; }
+   friend void swap(copyable &, copyable &)  { ++friend_swap_calls; }
+};
+
+class no_swap : public swap_stats
+{
+   private: unsigned m_state;
+   public:
+   explicit no_swap(unsigned i): m_state(i){}
+   no_swap(const no_swap &x)               { m_state = x.m_state; ++copy_cnstor_calls; }
+   no_swap & operator=(const no_swap& x)   { m_state = x.m_state; ++copy_assign_calls; return *this; }
+   void swap(no_swap &)                    { ++member_swap_calls; }
+   friend bool operator==(const no_swap &x, const no_swap &y) {  return x.m_state == y.m_state; }
+   friend bool operator!=(const no_swap &x, const no_swap &y) {  return !(x==y); }
+};
+
+
+int main()
+{
+   {  //movable
+      movable x, y;
+      swap_stats::reset_stats();
+      ::boost::adl_move_swap(x, y);
+      #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+      //In non rvalue reference compilers,
+      //movable classes with no swap() member uses
+      //boost::move() to implement swap.
+      BOOST_TEST(swap_stats::friend_swap_calls == 0);
+      BOOST_TEST(swap_stats::member_swap_calls == 0);
+      BOOST_TEST(swap_stats::member_swap_calls == 0);
+      BOOST_TEST(swap_stats::move_cnstor_calls == 1);
+      BOOST_TEST(swap_stats::move_assign_calls == 2);
+      BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::copy_assign_calls == 0);
+      #else
+      //In compilers with rvalue references, this should call friend swap via ADL
+      BOOST_TEST(swap_stats::friend_swap_calls == 1);
+      BOOST_TEST(swap_stats::member_swap_calls == 0);
+      BOOST_TEST(swap_stats::member_swap_calls == 0);
+      BOOST_TEST(swap_stats::move_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::move_assign_calls == 0);
+      BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::copy_assign_calls == 0);
+      #endif
+   }
+   {  //movable_swap_member
+      movable_swap_member x, y;
+      swap_stats::reset_stats();
+      ::boost::adl_move_swap(x, y);
+      #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+      //In non rvalue reference compilers,
+      //movable classes with no swap() member uses
+      //boost::move() to implement swap.
+      BOOST_TEST(swap_stats::friend_swap_calls == 0);
+      BOOST_TEST(swap_stats::member_swap_calls == 1);
+      BOOST_TEST(swap_stats::move_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::move_assign_calls == 0);
+      BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::copy_assign_calls == 0);
+      #else
+      //In compilers with rvalue references, this should call friend swap via ADL
+      BOOST_TEST(swap_stats::friend_swap_calls == 1);
+      BOOST_TEST(swap_stats::member_swap_calls == 0);
+      BOOST_TEST(swap_stats::move_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::move_assign_calls == 0);
+      BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::copy_assign_calls == 0);
+      #endif
+   }
+   {  //copyable
+      copyable x, y;
+      swap_stats::reset_stats();
+      ::boost::adl_move_swap(x, y);
+      //This should call friend swap via ADL
+      BOOST_TEST(swap_stats::friend_swap_calls == 1);
+      BOOST_TEST(swap_stats::member_swap_calls == 0);
+      BOOST_TEST(swap_stats::move_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::move_assign_calls == 0);
+      BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::copy_assign_calls == 0);
+   }
+   {  //no_swap
+      no_swap x(1), y(2), x_back(x), y_back(y);
+      swap_stats::reset_stats();
+      ::boost::adl_move_swap(x, y);
+      //This should call std::swap which uses copies
+      BOOST_TEST(swap_stats::friend_swap_calls == 0);
+      BOOST_TEST(swap_stats::member_swap_calls == 0);
+      BOOST_TEST(swap_stats::move_cnstor_calls == 0);
+      BOOST_TEST(swap_stats::move_assign_calls == 0);
+      BOOST_TEST(swap_stats::copy_cnstor_calls == 1);
+      BOOST_TEST(swap_stats::copy_assign_calls == 2);
+      BOOST_TEST(x == y_back);
+      BOOST_TEST(y == x_back);
+      BOOST_TEST(x != y);
+   }
+   return ::boost::report_errors();
+}
+#include <boost/move/detail/config_end.hpp>
diff --git a/test/algo_test.cpp b/test/algo_test.cpp
new file mode 100644
index 0000000..d4652e2
--- /dev/null
+++ b/test/algo_test.cpp
@@ -0,0 +1,953 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2017.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/algo/detail/set_difference.hpp>
+#include "order_type.hpp"
+#include <boost/core/lightweight_test.hpp>
+#include <cstddef>
+/*
+///////////////////////////////////
+//
+//      set_difference
+//
+///////////////////////////////////
+void test_set_difference_normal()
+{
+   order_perf_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_perf_type range1[4];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 1u;
+   range1[1].val = 1u;
+   range1[2].key = 3u;
+   range1[2].val = 1u;
+   range1[3].key = 4u;
+   range1[3].val = 1u;
+
+   order_perf_type out[20];
+   out[2].key = 998;
+   out[2].val = 999;
+   boost::movelib::set_difference(range1, range1+4, range2, range2+10, out, order_type_less());
+   BOOST_TEST(out[0].key == 1u);
+   BOOST_TEST(out[0].val == 1u);
+   BOOST_TEST(out[1].key == 3u);
+   BOOST_TEST(out[1].val == 1u);
+   BOOST_TEST(out[2].key == 998);
+   BOOST_TEST(out[2].val == 999);
+}
+
+void test_set_difference_range1_repeated()
+{
+   order_perf_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_perf_type range1[4];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 2u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 6u;
+   range1[3].val = 1u;
+
+   order_perf_type out[20];
+   out[0].key = 998;
+   out[0].val = 999;
+   boost::movelib::set_difference(range1, range1+4, range2, range2+10, out, order_type_less());
+   BOOST_TEST(out[0].key == 998);
+   BOOST_TEST(out[0].val == 999);
+}
+
+void test_set_difference_range1_unique()
+{
+   order_perf_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_perf_type range1[4];
+   range1[0].key = 1u;
+   range1[0].val = 1u;
+   range1[1].key = 3u;
+   range1[1].val = 1u;
+   range1[2].key = 5u;
+   range1[2].val = 1u;
+   range1[3].key = 7u;
+   range1[3].val = 1u;
+
+   order_perf_type out[20];
+   out[4].key = 998;
+   out[4].val = 999;
+   boost::movelib::set_difference(range1, range1+4, range2, range2+10, out, order_type_less());
+   BOOST_TEST(out[0].key == 1u);
+   BOOST_TEST(out[0].val == 1u);
+   BOOST_TEST(out[1].key == 3u);
+   BOOST_TEST(out[1].val == 1u);
+   BOOST_TEST(out[2].key == 5u);
+   BOOST_TEST(out[3].val == 1u);
+   BOOST_TEST(out[3].key == 7u);
+   BOOST_TEST(out[3].val == 1u);
+   BOOST_TEST(out[4].key == 998);
+   BOOST_TEST(out[4].val == 999);
+}
+*/
+
+///////////////////////////////////
+//
+//      set_difference
+//
+///////////////////////////////////
+void test_set_difference_normal()
+{
+   order_perf_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_perf_type range1[5];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 1u;
+   range1[1].val = 1u;
+   range1[2].key = 1u;
+   range1[2].val = 2u;
+   range1[3].key = 3u;
+   range1[3].val = 1u;
+   range1[4].key = 4u;
+   range1[4].val = 1u;
+
+   order_perf_type out[20];
+   out[3].key = 998;
+   out[3].val = 999;
+   order_perf_type *r =
+      boost::movelib::set_difference(range1, range1+5, range2, range2+10, out, order_type_less());
+   BOOST_TEST(&out[3] == r);
+   BOOST_TEST(out[0].key == 1u);
+   BOOST_TEST(out[0].val == 1u);
+   BOOST_TEST(out[1].key == 1u);
+   BOOST_TEST(out[1].val == 2u);
+   BOOST_TEST(out[2].key == 3u);
+   BOOST_TEST(out[2].val == 1u);
+   BOOST_TEST(out[3].key == 998);
+   BOOST_TEST(out[3].val == 999);
+}
+
+void test_set_difference_range1_repeated()
+{
+   order_perf_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_perf_type range1[5];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 2u;
+   range1[1].val = 1u;
+   range1[2].key = 2u;
+   range1[2].val = 2u;
+   range1[3].key = 4u;
+   range1[3].val = 1u;
+   range1[4].key = 6u;
+   range1[4].val = 1u;
+
+   order_perf_type out[20];
+   out[0].key = 998;
+   out[0].val = 999;
+   order_perf_type *r =
+      boost::movelib::set_difference(range1, range1+5, range2, range2+10, out, order_type_less());
+   BOOST_TEST(&out[1] == r);
+   BOOST_TEST(out[0].key == 2);
+   BOOST_TEST(out[0].val == 2);
+}
+
+void test_set_difference_range1_unique()
+{
+   order_perf_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_perf_type range1[5];
+   range1[0].key = 1u;
+   range1[0].val = 1u;
+   range1[1].key = 3u;
+   range1[1].val = 1u;
+   range1[2].key = 5u;
+   range1[2].val = 1u;
+   range1[3].key = 7u;
+   range1[3].val = 1u;
+   range1[4].key = 7u;
+   range1[4].val = 2u;
+
+   order_perf_type out[20];
+   out[5].key = 998;
+   out[5].val = 999;
+   order_perf_type *r =
+      boost::movelib::set_difference(range1, range1+5, range2, range2+10, out, order_type_less());
+   BOOST_TEST(&out[5] == r);
+   BOOST_TEST(out[0].key == 1u);
+   BOOST_TEST(out[0].val == 1u);
+   BOOST_TEST(out[1].key == 3u);
+   BOOST_TEST(out[1].val == 1u);
+   BOOST_TEST(out[2].key == 5u);
+   BOOST_TEST(out[2].val == 1u);
+   BOOST_TEST(out[3].key == 7u);
+   BOOST_TEST(out[3].val == 1u);
+   BOOST_TEST(out[4].key == 7u);
+   BOOST_TEST(out[4].val == 2u);
+   BOOST_TEST(out[5].key == 998);
+   BOOST_TEST(out[5].val == 999);
+}
+
+/*
+///////////////////////////////////
+//
+//      inplace_set_difference
+//
+///////////////////////////////////
+void test_inplace_set_difference_normal()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[4];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 1u;
+   range1[1].val = 1u;
+   range1[2].key = 3u;
+   range1[2].val = 1u;
+   range1[3].key = 4u;
+   range1[3].val = 1u;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+2);
+   BOOST_TEST(range1[0].key == 1u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 3u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == order_move_type::moved_assign_mark);
+   BOOST_TEST(range1[2].val == order_move_type::moved_assign_mark);
+}
+
+void test_inplace_set_difference_range1_repeated()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[5];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 2u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 6u;
+   range1[3].val = 1u;
+   range1[4].key = order_move_type::moved_assign_mark;
+   range1[4].val = order_move_type::moved_assign_mark;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+0);
+   BOOST_TEST(range1[0].key == 0u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 2u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == 4u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[3].key == 6u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
+   BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
+}
+
+void test_inplace_set_difference_range1_unique()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[5];
+   range1[0].key = 1u;
+   range1[0].val = 1u;
+   range1[1].key = 3u;
+   range1[1].val = 1u;
+   range1[2].key = 5u;
+   range1[2].val = 1u;
+   range1[3].key = 7u;
+   range1[3].val = 1u;
+   range1[4].key = order_move_type::moved_assign_mark;
+   range1[4].val = order_move_type::moved_assign_mark;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+4);
+   BOOST_TEST(range1[0].key == 1u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 3u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == 5u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[3].key == 7u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
+   BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
+}
+
+void test_inplace_set_difference_range1_unique_long()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[11];
+   for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
+      range1[i].key = i*2+1;
+      range1[i].val = 1u;
+   }
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+11, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+11);
+   for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
+      BOOST_TEST(range1[i].key == i*2+1);
+      BOOST_TEST(range1[i].val == 1u);
+   }
+}
+
+void test_inplace_set_difference_range1_same_start()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[5];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 2u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 5u;
+   range1[3].val = 1u;
+   range1[4].key = 7u;
+   range1[4].val = 1u;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+2);
+   BOOST_TEST(range1[0].key == 5u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 7u);
+   BOOST_TEST(range1[1].val == 1u);
+}
+
+void test_inplace_set_difference_range1_same_end()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[5];
+   range1[0].key = 1u;
+   range1[0].val = 1u;
+   range1[1].key = 3u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 6u;
+   range1[3].val = 1u;
+   range1[4].key = 8u;
+   range1[4].val = 1u;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+2);
+   BOOST_TEST(range1[0].key == 1u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 3u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == 4u);
+   BOOST_TEST(range1[2].val == 1u);
+   BOOST_TEST(range1[3].key == 6u);
+   BOOST_TEST(range1[3].val == 1u);
+}
+*/
+
+///////////////////////////////////
+//
+//      inplace_set_difference
+//
+///////////////////////////////////
+void test_inplace_set_difference_normal()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[4];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 1u;
+   range1[1].val = 1u;
+   range1[2].key = 3u;
+   range1[2].val = 1u;
+   range1[3].key = 4u;
+   range1[3].val = 1u;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+2);
+   BOOST_TEST(range1[0].key == 1u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 3u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == order_move_type::moved_assign_mark);
+   BOOST_TEST(range1[2].val == order_move_type::moved_assign_mark);
+}
+
+void test_inplace_set_difference_range1_repeated()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[5];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 2u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 6u;
+   range1[3].val = 1u;
+   range1[4].key = order_move_type::moved_assign_mark;
+   range1[4].val = order_move_type::moved_assign_mark;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+0);
+   BOOST_TEST(range1[0].key == 0u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 2u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == 4u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[3].key == 6u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
+   BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
+}
+
+void test_inplace_set_difference_range1_unique()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[5];
+   range1[0].key = 1u;
+   range1[0].val = 1u;
+   range1[1].key = 3u;
+   range1[1].val = 1u;
+   range1[2].key = 5u;
+   range1[2].val = 1u;
+   range1[3].key = 7u;
+   range1[3].val = 1u;
+   range1[4].key = order_move_type::moved_assign_mark;
+   range1[4].val = order_move_type::moved_assign_mark;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+4);
+   BOOST_TEST(range1[0].key == 1u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 3u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == 5u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[3].key == 7u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
+   BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
+}
+
+void test_inplace_set_difference_range1_unique_long()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[11];
+   for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
+      range1[i].key = i*2+1;
+      range1[i].val = 1u;
+   }
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+11, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+11);
+   for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
+      BOOST_TEST(range1[i].key == i*2+1);
+      BOOST_TEST(range1[i].val == 1u);
+   }
+}
+
+void test_inplace_set_difference_range1_same_start()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[5];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 2u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 5u;
+   range1[3].val = 1u;
+   range1[4].key = 7u;
+   range1[4].val = 1u;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+2);
+   BOOST_TEST(range1[0].key == 5u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 7u);
+   BOOST_TEST(range1[1].val == 1u);
+}
+
+void test_inplace_set_difference_range1_same_end()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[5];
+   range1[0].key = 1u;
+   range1[0].val = 1u;
+   range1[1].key = 3u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 6u;
+   range1[3].val = 1u;
+   range1[4].key = 8u;
+   range1[4].val = 1u;
+
+   order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+2);
+   BOOST_TEST(range1[0].key == 1u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 3u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == 4u);
+   BOOST_TEST(range1[2].val == 1u);
+   BOOST_TEST(range1[3].key == 6u);
+   BOOST_TEST(range1[3].val == 1u);
+}
+
+
+///////////////////////////////////
+//
+//      set_unique_difference
+//
+///////////////////////////////////
+void test_set_unique_difference_normal()
+{
+   order_perf_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_perf_type range1[10];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 1u;
+   range1[1].val = 1u;
+   range1[2].key = 1u;
+   range1[2].val = 2u;
+   range1[3].key = 3u;
+   range1[3].val = 1u;
+   range1[4].key = 4u;
+   range1[4].val = 1u;
+   range1[5].key = 4u;
+   range1[5].val = 2u;
+   range1[6].key = 21u;
+   range1[6].val = 1u;
+   range1[7].key = 21u;
+   range1[7].val = 2u;
+   range1[8].key = 23u;
+   range1[8].val = 1u;
+   range1[9].key = 23u;
+   range1[9].val = 2u;
+
+   order_perf_type out[20];
+   out[4].key = 998;
+   out[4].val = 999;
+   order_perf_type * r =
+      boost::movelib::set_unique_difference(range1, range1+10, range2, range2+10, out, order_type_less());
+   BOOST_TEST(&out[4] == r);
+   BOOST_TEST(out[0].key == 1u);
+   BOOST_TEST(out[0].val == 1u);
+   BOOST_TEST(out[1].key == 3u);
+   BOOST_TEST(out[1].val == 1u);
+   BOOST_TEST(out[2].key == 21u);
+   BOOST_TEST(out[2].val == 1u);
+   BOOST_TEST(out[3].key == 23u);
+   BOOST_TEST(out[3].val == 1u);
+   BOOST_TEST(out[4].key == 998);
+   BOOST_TEST(out[4].val == 999);
+}
+
+void test_set_unique_difference_range1_repeated()
+{
+   order_perf_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_perf_type range1[11];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 0u;
+   range1[1].val = 2u;
+   range1[2].key = 0u;
+   range1[2].val = 2u;
+   range1[3].key = 2u;
+   range1[3].val = 1u;
+   range1[4].key = 2u;
+   range1[4].val = 2u;
+   range1[5].key = 4u;
+   range1[5].val = 1u;
+   range1[6].key = 6u;
+   range1[6].val = 1u;
+   range1[7].key = 6u;
+   range1[7].val = 2u;
+   range1[8].key = 6u;
+   range1[8].val = 3u;
+   range1[9].key = 6u;
+   range1[9].val = 4u;
+   range1[10].key = 6u;
+   range1[10].val = 5u;
+
+   order_perf_type out[20];
+   out[0].key = 998;
+   out[0].val = 999;
+   order_perf_type * r =
+      boost::movelib::set_unique_difference(range1, range1+11, range2, range2+10, out, order_type_less());
+   BOOST_TEST(&out[0] == r);
+   BOOST_TEST(out[0].key == 998);
+   BOOST_TEST(out[0].val == 999);
+}
+
+void test_set_unique_difference_range1_unique()
+{
+   order_perf_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_perf_type range1[7];
+   range1[0].key = 1u;
+   range1[0].val = 1u;
+   range1[1].key = 3u;
+   range1[1].val = 1u;
+   range1[2].key = 3u;
+   range1[2].val = 2u;
+   range1[3].key = 5u;
+   range1[3].val = 1u;
+   range1[4].key = 7u;
+   range1[4].val = 1u;
+   range1[5].key = 7u;
+   range1[5].val = 2u;
+   range1[6].key = 7u;
+   range1[6].val = 3u;
+
+   order_perf_type out[20];
+   out[4].key = 998;
+   out[4].val = 999;
+   order_perf_type * r =
+      boost::movelib::set_unique_difference(range1, range1+7, range2, range2+10, out, order_type_less());
+   BOOST_TEST(&out[4] == r);
+   BOOST_TEST(out[0].key == 1u);
+   BOOST_TEST(out[0].val == 1u);
+   BOOST_TEST(out[1].key == 3u);
+   BOOST_TEST(out[1].val == 1u);
+   BOOST_TEST(out[2].key == 5u);
+   BOOST_TEST(out[2].val == 1u);
+   BOOST_TEST(out[3].key == 7u);
+   BOOST_TEST(out[3].val == 1u);
+   BOOST_TEST(out[4].key == 998);
+   BOOST_TEST(out[4].val == 999);
+}
+
+///////////////////////////////////
+//
+//      inplace_set_unique_difference
+//
+///////////////////////////////////
+void test_inplace_set_unique_difference_normal()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[4];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 1u;
+   range1[1].val = 1u;
+   range1[2].key = 3u;
+   range1[2].val = 1u;
+   range1[3].key = 4u;
+   range1[3].val = 1u;
+
+   order_move_type *ret = boost::movelib::inplace_set_unique_difference(range1, range1+4, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+2);
+   BOOST_TEST(range1[0].key == 1u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 3u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == order_move_type::moved_assign_mark);
+   BOOST_TEST(range1[2].val == order_move_type::moved_assign_mark);
+}
+
+void test_inplace_set_unique_difference_range1_repeated()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[5];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 2u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 6u;
+   range1[3].val = 1u;
+   range1[4].key = order_move_type::moved_assign_mark;
+   range1[4].val = order_move_type::moved_assign_mark;
+
+   order_move_type *ret = boost::movelib::inplace_set_unique_difference(range1, range1+4, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+0);
+   BOOST_TEST(range1[0].key == 0u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 2u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == 4u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[3].key == 6u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
+   BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
+}
+
+void test_inplace_set_unique_difference_range1_unique()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[9];
+   range1[0].key = 1u;
+   range1[0].val = 1u;
+   range1[1].key = 1u;
+   range1[1].val = 2u;
+   range1[2].key = 3u;
+   range1[2].val = 1u;
+   range1[3].key = 3u;
+   range1[3].val = 2u;
+   range1[4].key = 5u;
+   range1[4].val = 1u;
+   range1[5].key = 7u;
+   range1[5].val = 1u;
+   range1[6].key = 7u;
+   range1[6].val = 2u;
+   range1[7].key = 7u;
+   range1[7].val = 3u;
+   range1[8].val = 3u;
+   range1[8].key = order_move_type::moved_assign_mark;
+   range1[8].val = order_move_type::moved_assign_mark;
+
+   order_move_type *ret =
+      boost::movelib::inplace_set_unique_difference(range1, range1+8, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+4);
+   BOOST_TEST(range1[0].key == 1u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 3u);
+   BOOST_TEST(range1[1].val == 1u);
+   BOOST_TEST(range1[2].key == 5u);
+   BOOST_TEST(range1[3].val == 1u);
+   BOOST_TEST(range1[3].key == 7u);
+   BOOST_TEST(range1[3].val == 1u);
+}
+
+void test_inplace_set_unique_difference_range1_unique_long()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[22];
+   for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
+      range1[i].key = (i/2)*2+1;
+      range1[i].val = i%2;
+   }
+
+   order_move_type *ret =
+      boost::movelib::inplace_set_unique_difference(range1, range1+22, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+11);
+   for(std::size_t i = 0; i != 11; ++i){
+      BOOST_TEST(range1[i].key == i*2+1);
+      BOOST_TEST(range1[i].val == 0u);
+   }
+}
+
+void test_inplace_set_unique_difference_range1_same_start()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[6];
+   range1[0].key = 0u;
+   range1[0].val = 1u;
+   range1[1].key = 2u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 4u;
+   range1[3].val = 2u;
+   range1[4].key = 5u;
+   range1[4].val = 1u;
+   range1[5].key = 7u;
+   range1[5].val = 1u;
+
+   order_move_type *ret =
+      boost::movelib::inplace_set_unique_difference(range1, range1+6, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+2);
+   BOOST_TEST(range1[0].key == 5u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 7u);
+   BOOST_TEST(range1[1].val == 1u);
+}
+
+void test_inplace_set_unique_difference_range1_same_end()
+{
+   order_move_type range2[10];
+   for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
+      range2[i].key = i*2;
+      range2[i].val = 0u;
+   }
+
+   order_move_type range1[8];
+   range1[0].key = 1u;
+   range1[0].val = 1u;
+   range1[1].key = 3u;
+   range1[1].val = 1u;
+   range1[2].key = 4u;
+   range1[2].val = 1u;
+   range1[3].key = 4u;
+   range1[3].val = 2u;
+   range1[4].key = 6u;
+   range1[4].val = 1u;
+   range1[5].key = 8u;
+   range1[5].val = 1u;
+   range1[6].key = 8u;
+   range1[6].val = 2u;
+   range1[7].key = 8u;
+   range1[7].val = 3u;
+
+   order_move_type *ret =
+      boost::movelib::inplace_set_unique_difference(range1, range1+8, range2, range2+10, order_type_less());
+   BOOST_TEST(ret == range1+2);
+   BOOST_TEST(range1[0].key == 1u);
+   BOOST_TEST(range1[0].val == 1u);
+   BOOST_TEST(range1[1].key == 3u);
+   BOOST_TEST(range1[1].val == 1u);
+}
+
+int main()
+{
+   //set_difference
+   test_set_difference_normal();
+   test_set_difference_range1_repeated();
+   test_set_difference_range1_unique();
+   //inplace_set_difference
+   test_inplace_set_difference_normal();
+   test_inplace_set_difference_range1_repeated();
+   test_inplace_set_difference_range1_unique();
+   test_inplace_set_difference_range1_unique_long();
+   test_inplace_set_difference_range1_same_start();
+   test_inplace_set_difference_range1_same_end();
+   //set_unique_difference
+   test_set_unique_difference_normal();
+   test_set_unique_difference_range1_repeated();
+   test_set_unique_difference_range1_unique();
+   //inplace_set_unique_difference
+   test_inplace_set_unique_difference_normal();
+   test_inplace_set_unique_difference_range1_repeated();
+   test_inplace_set_unique_difference_range1_unique();
+   test_inplace_set_unique_difference_range1_unique_long();
+   test_inplace_set_unique_difference_range1_same_start();
+   test_inplace_set_unique_difference_range1_same_end();
+
+   return boost::report_errors();
+}
diff --git a/test/back_move_inserter.cpp b/test/back_move_inserter.cpp
new file mode 100644
index 0000000..6fc4829
--- /dev/null
+++ b/test/back_move_inserter.cpp
@@ -0,0 +1,80 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/detail/config_begin.hpp>
+// move
+#include <boost/move/algorithm.hpp>
+#include <boost/move/iterator.hpp>
+// container
+#include <boost/container/deque.hpp>
+#include <boost/container/list.hpp>
+#include <boost/container/stable_vector.hpp>
+#include "../example/movable.hpp"
+
+template<class Container>
+int move_test()
+{
+   bool use_move_iterator = false;
+   bool done = false;
+   while(!done){
+      //Default construct 10 movable objects
+      Container v(10);
+
+      //Test default constructed value
+      if(v.begin()->moved()){
+         return 1;
+      }
+
+      //Move values
+      Container v2;
+      if(use_move_iterator){
+         ::boost::copy_or_move( boost::make_move_iterator(v.begin())
+                              , boost::make_move_iterator(v.end())
+                              , boost::back_move_inserter(v2));
+      }
+      else{
+         std::copy(v.begin(), v.end(), boost::back_move_inserter(v2));
+      }
+
+      //Test values have been moved
+      if(!v.begin()->moved()){
+         return 1;
+      }
+
+      if(v2.size() != 10){
+         return 1;
+      }
+
+      if(v2.begin()->moved()){
+         return 1;
+      }
+      done = use_move_iterator;
+      use_move_iterator = true;
+   }
+   return 0;
+}
+
+int main()
+{
+   namespace bc = ::boost::container;
+
+   if(move_test< bc::vector<movable> >()){
+      return 1;
+   }
+   if(move_test< bc::list<movable> >()){
+      return 1;
+   }
+   if(move_test< bc::stable_vector<movable> >()){
+      return 1;
+   }
+   return 0;
+}
+
+#include <boost/move/detail/config_end.hpp>
diff --git a/test/bench_merge.cpp b/test/bench_merge.cpp
new file mode 100644
index 0000000..5f69018
--- /dev/null
+++ b/test/bench_merge.cpp
@@ -0,0 +1,274 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <algorithm> //std::inplace_merge
+#include <cstdio>    //std::printf
+#include <iostream>  //std::cout
+
+#include <boost/config.hpp>
+
+#include <boost/move/unique_ptr.hpp>
+#include <boost/timer/timer.hpp>
+
+#include "order_type.hpp"
+#include "random_shuffle.hpp"
+
+using boost::timer::cpu_timer;
+using boost::timer::cpu_times;
+using boost::timer::nanosecond_type;
+
+//#define BOOST_MOVE_ADAPTIVE_SORT_STATS
+//#define BOOST_MOVE_ADAPTIVE_SORT_STATS_LEVEL 2
+void print_stats(const char *str, boost::ulong_long_type element_count)
+{
+   std::printf("%sCmp:%8.04f Cpy:%9.04f\n", str, double(order_perf_type::num_compare)/element_count, double(order_perf_type::num_copy)/element_count );
+}
+
+#include <boost/move/algo/adaptive_merge.hpp>
+#include <boost/move/algo/detail/merge.hpp>
+#include <boost/move/core.hpp>
+
+template<class T, class Compare>
+std::size_t generate_elements(T elements[], std::size_t element_count, std::size_t key_reps[], std::size_t key_len, Compare comp)
+{
+   std::srand(0);
+   for(std::size_t i = 0; i < (key_len ? key_len : element_count); ++i){
+      key_reps[i]=0;
+   }
+   for(std::size_t  i=0; i < element_count; ++i){
+      std::size_t  key = key_len ? (i % key_len) : i;
+      elements[i].key=key;
+   }
+   ::random_shuffle(elements, elements + element_count);
+   ::random_shuffle(elements, elements + element_count);
+   ::random_shuffle(elements, elements + element_count);
+   for(std::size_t i = 0; i < element_count; ++i){
+      elements[i].val = key_reps[elements[i].key]++;
+   }
+   std::size_t split_count = element_count/2;
+   std::stable_sort(elements, elements+split_count, comp);
+   std::stable_sort(elements+split_count, elements+element_count, comp);
+   return split_count;
+}
+
+
+
+template<class T, class Compare>
+void adaptive_merge_buffered(T *elements, T *mid, T *last, Compare comp, std::size_t BufLen)
+{
+   boost::movelib::unique_ptr<char[]> mem(new char[sizeof(T)*BufLen]);
+   boost::movelib::adaptive_merge(elements, mid, last, comp, reinterpret_cast<T*>(mem.get()), BufLen);
+}
+
+enum AlgoType
+{
+   StdMerge,
+   AdaptiveMerge,
+   SqrtHAdaptiveMerge,
+   SqrtAdaptiveMerge,
+   Sqrt2AdaptiveMerge,
+   QuartAdaptiveMerge,
+   StdInplaceMerge,
+   MaxMerge
+};
+
+const char *AlgoNames [] = { "StdMerge        "
+                           , "AdaptMerge      "
+                           , "SqrtHAdaptMerge "
+                           , "SqrtAdaptMerge  "
+                           , "Sqrt2AdaptMerge "
+                           , "QuartAdaptMerge "
+                           , "StdInplaceMerge "
+                           };
+
+BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxMerge);
+
+template<class T>
+bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count, std::size_t key_len, unsigned alg, nanosecond_type &prev_clock)
+{
+   std::size_t const split_pos = generate_elements(elements, element_count, key_reps, key_len, order_type_less());
+
+   std::printf("%s ", AlgoNames[alg]);
+   order_perf_type::num_compare=0;
+   order_perf_type::num_copy=0;
+   order_perf_type::num_elements = element_count;
+   cpu_timer timer;
+   timer.resume();
+   switch(alg)
+   {
+      case StdMerge:
+         std::inplace_merge(elements, elements+split_pos, elements+element_count, order_type_less());
+      break;
+      case AdaptiveMerge:
+         boost::movelib::adaptive_merge(elements, elements+split_pos, elements+element_count, order_type_less());
+      break;
+      case SqrtHAdaptiveMerge:
+         adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
+                            , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
+      break;
+      case SqrtAdaptiveMerge:
+         adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
+                            , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
+      break;
+      case Sqrt2AdaptiveMerge:
+         adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
+                            , 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
+      break;
+      case QuartAdaptiveMerge:
+         adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
+                            , (element_count-1)/4+1);
+      break;
+      case StdInplaceMerge:
+         boost::movelib::merge_bufferless_ONlogN(elements, elements+split_pos, elements+element_count, order_type_less());
+      break;
+   }
+   timer.stop();
+
+   if(order_perf_type::num_elements == element_count){
+      std::printf(" Tmp Ok ");
+   } else{
+      std::printf(" Tmp KO ");
+   }
+   nanosecond_type new_clock = timer.elapsed().wall;
+
+   //std::cout << "Cmp:" << order_perf_type::num_compare << " Cpy:" << order_perf_type::num_copy;   //for old compilers without ll size argument
+   std::printf("Cmp:%8.04f Cpy:%9.04f", double(order_perf_type::num_compare)/element_count, double(order_perf_type::num_copy)/element_count );
+
+   double time = double(new_clock);
+
+   const char *units = "ns";
+   if(time >= 1000000000.0){
+      time /= 1000000000.0;
+      units = " s";
+   }
+   else if(time >= 1000000.0){
+      time /= 1000000.0;
+      units = "ms";
+   }
+   else if(time >= 1000.0){
+      time /= 1000.0;
+      units = "us";
+   }
+
+   std::printf(" %6.02f%s (%6.02f)\n"
+              , time
+              , units
+              , prev_clock ? double(new_clock)/double(prev_clock): 1.0);
+   prev_clock = new_clock;
+   bool res = is_order_type_ordered(elements, element_count, true);
+   return res;
+}
+
+template<class T>
+bool measure_all(std::size_t L, std::size_t NK)
+{
+   boost::movelib::unique_ptr<T[]> pdata(new T[L]);
+   boost::movelib::unique_ptr<std::size_t[]> pkeys(new std::size_t[NK ? NK : L]);
+   T *A              = pdata.get();
+   std::size_t *Keys = pkeys.get();
+   std::printf("\n - - N: %u, NK: %u - -\n", (unsigned)L, (unsigned)NK);
+
+   nanosecond_type prev_clock = 0;
+   nanosecond_type back_clock;
+   bool res = true;
+   res = res && measure_algo(A,Keys,L,NK,StdMerge, prev_clock);
+   back_clock = prev_clock;
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,QuartAdaptiveMerge, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,Sqrt2AdaptiveMerge, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,SqrtAdaptiveMerge, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,SqrtHAdaptiveMerge, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,AdaptiveMerge, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,StdInplaceMerge, prev_clock);
+   //
+   if(!res)
+      throw int(0);
+   return res;
+}
+
+//Undef it to run the long test
+#define BENCH_MERGE_SHORT
+#define BENCH_SORT_UNIQUE_VALUES
+
+int main()
+{
+   try{
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(101,1);
+   measure_all<order_perf_type>(101,7);
+   measure_all<order_perf_type>(101,31);
+   #endif
+   measure_all<order_perf_type>(101,0);
+
+   //
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(1101,1);
+   measure_all<order_perf_type>(1001,7);
+   measure_all<order_perf_type>(1001,31);
+   measure_all<order_perf_type>(1001,127);
+   measure_all<order_perf_type>(1001,511);
+   #endif
+   measure_all<order_perf_type>(1001,0);
+   //
+   #ifndef BENCH_MERGE_SHORT
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(10001,65);
+   measure_all<order_perf_type>(10001,255);
+   measure_all<order_perf_type>(10001,1023);
+   measure_all<order_perf_type>(10001,4095);
+   #endif
+   measure_all<order_perf_type>(10001,0);
+
+   //
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(100001,511);
+   measure_all<order_perf_type>(100001,2047);
+   measure_all<order_perf_type>(100001,8191);
+   measure_all<order_perf_type>(100001,32767);
+   #endif
+   measure_all<order_perf_type>(100001,0);
+
+   //
+   #ifdef NDEBUG
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(1000001,1);
+   measure_all<order_perf_type>(1000001,1024);
+   measure_all<order_perf_type>(1000001,32768);
+   measure_all<order_perf_type>(1000001,524287);
+   #endif
+   measure_all<order_perf_type>(1000001,0);
+   measure_all<order_perf_type>(3000001,0);
+   measure_all<order_perf_type>(5000001,0);
+   #endif   //NDEBUG
+
+   #endif   //#ifndef BENCH_MERGE_SHORT
+
+   //measure_all<order_perf_type>(100000001,0);
+   }
+   catch(...)
+   {
+      return 1;
+   }
+
+   return 0;
+}
+
diff --git a/test/bench_sort.cpp b/test/bench_sort.cpp
new file mode 100644
index 0000000..6544976
--- /dev/null
+++ b/test/bench_sort.cpp
@@ -0,0 +1,313 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <cstdlib>   //std::srand
+#include <algorithm> //std::stable_sort, std::make|sort_heap, std::random_shuffle
+#include <cstdio>    //std::printf
+#include <iostream>  //std::cout
+
+#include <boost/config.hpp>
+
+#include <boost/move/unique_ptr.hpp>
+#include <boost/timer/timer.hpp>
+
+using boost::timer::cpu_timer;
+using boost::timer::cpu_times;
+using boost::timer::nanosecond_type;
+
+#include "order_type.hpp"
+#include "random_shuffle.hpp"
+
+//#define BOOST_MOVE_ADAPTIVE_SORT_STATS
+//#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
+void print_stats(const char *str, boost::ulong_long_type element_count)
+{
+   std::printf("%sCmp:%7.03f Cpy:%8.03f\n", str, double(order_perf_type::num_compare)/element_count, double(order_perf_type::num_copy)/element_count );
+}
+
+
+#include <boost/move/algo/adaptive_sort.hpp>
+#include <boost/move/algo/detail/merge_sort.hpp>
+#include <boost/move/algo/detail/pdqsort.hpp>
+#include <boost/move/algo/detail/heap_sort.hpp>
+#include <boost/move/core.hpp>
+
+template<class T>
+void generate_elements(T elements[], std::size_t element_count, std::size_t key_reps[], std::size_t key_len)
+{
+   std::srand(0);
+   for(std::size_t i = 0; i < (key_len ? key_len : element_count); ++i){
+      key_reps[i]=0;
+   }
+   for(std::size_t  i=0; i < element_count; ++i){
+      std::size_t  key = key_len ? (i % key_len) : i;
+      elements[i].key=key;
+   }
+   ::random_shuffle(elements, elements + element_count);
+   ::random_shuffle(elements, elements + element_count);
+   ::random_shuffle(elements, elements + element_count);
+   for(std::size_t i = 0; i < element_count; ++i){
+      elements[i].val = key_reps[elements[i].key]++;
+   }
+}
+
+template<class T, class Compare>
+void adaptive_sort_buffered(T *elements, std::size_t element_count, Compare comp, std::size_t BufLen)
+{
+   boost::movelib::unique_ptr<char[]> mem(new char[sizeof(T)*BufLen]);
+   boost::movelib::adaptive_sort(elements, elements + element_count, comp, reinterpret_cast<T*>(mem.get()), BufLen);
+}
+
+template<class T, class Compare>
+void merge_sort_buffered(T *elements, std::size_t element_count, Compare comp)
+{
+   boost::movelib::unique_ptr<char[]> mem(new char[sizeof(T)*((element_count+1)/2)]);
+   boost::movelib::merge_sort(elements, elements + element_count, comp, reinterpret_cast<T*>(mem.get()));
+}
+
+enum AlgoType
+{
+   MergeSort,
+   StableSort,
+   PdQsort,
+   StdSort,
+   AdaptiveSort,
+   SqrtHAdaptiveSort,
+   SqrtAdaptiveSort,
+   Sqrt2AdaptiveSort,
+   QuartAdaptiveSort,
+   InplaceStableSort,
+   SlowStableSort,
+   HeapSort,
+   MaxSort
+};
+
+const char *AlgoNames [] = { "MergeSort      "
+                           , "StableSort     "
+                           , "PdQsort        "
+                           , "StdSort        "
+                           , "AdaptSort      "
+                           , "SqrtHAdaptSort "
+                           , "SqrtAdaptSort  "
+                           , "Sqrt2AdaptSort "
+                           , "QuartAdaptSort "
+                           , "InplStableSort "
+                           , "SlowSort       "
+                           , "HeapSort       "
+                           };
+
+BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxSort);
+
+template<class T>
+bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count, std::size_t key_len, unsigned alg, nanosecond_type &prev_clock)
+{
+   generate_elements(elements, element_count, key_reps, key_len);
+
+   std::printf("%s ", AlgoNames[alg]);
+   order_perf_type::num_compare=0;
+   order_perf_type::num_copy=0;
+   order_perf_type::num_elements = element_count;
+   cpu_timer timer;
+   timer.resume();
+   switch(alg)
+   {
+      case MergeSort:
+         merge_sort_buffered(elements, element_count, order_type_less());
+      break;
+      case StableSort:
+         std::stable_sort(elements,elements+element_count,order_type_less());
+      break;
+      case PdQsort:
+         boost::movelib::pdqsort(elements,elements+element_count,order_type_less());
+      break;
+      case StdSort:
+         std::sort(elements,elements+element_count,order_type_less());
+      break;
+      case AdaptiveSort:
+         boost::movelib::adaptive_sort(elements, elements+element_count, order_type_less());
+      break;
+      case SqrtHAdaptiveSort:
+         adaptive_sort_buffered( elements, element_count, order_type_less()
+                            , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
+      break;
+      case SqrtAdaptiveSort:
+         adaptive_sort_buffered( elements, element_count, order_type_less()
+                            , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
+      break;
+      case Sqrt2AdaptiveSort:
+         adaptive_sort_buffered( elements, element_count, order_type_less()
+                            , 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
+      break;
+      case QuartAdaptiveSort:
+         adaptive_sort_buffered( elements, element_count, order_type_less()
+                            , (element_count-1)/4+1);
+      break;
+      case InplaceStableSort:
+         boost::movelib::inplace_stable_sort(elements, elements+element_count, order_type_less());
+      break;
+      case SlowStableSort:
+         boost::movelib::detail_adaptive::slow_stable_sort(elements, elements+element_count, order_type_less());
+      break;
+      case HeapSort:
+         boost::movelib::heap_sort(elements, elements+element_count, order_type_less());
+         boost::movelib::heap_sort((order_move_type*)0, (order_move_type*)0, order_type_less());
+
+      break;
+   }
+   timer.stop();
+
+   if(order_perf_type::num_elements == element_count){
+      std::printf(" Tmp Ok ");
+   } else{
+      std::printf(" Tmp KO ");
+   }
+   nanosecond_type new_clock = timer.elapsed().wall;
+
+   //std::cout << "Cmp:" << order_perf_type::num_compare << " Cpy:" << order_perf_type::num_copy;   //for old compilers without ll size argument
+   std::printf("Cmp:%7.03f Cpy:%8.03f", double(order_perf_type::num_compare)/element_count, double(order_perf_type::num_copy)/element_count );
+
+   double time = double(new_clock);
+
+   const char *units = "ns";
+   if(time >= 1000000000.0){
+      time /= 1000000000.0;
+      units = " s";
+   }
+   else if(time >= 1000000.0){
+      time /= 1000000.0;
+      units = "ms";
+   }
+   else if(time >= 1000.0){
+      time /= 1000.0;
+      units = "us";
+   }
+
+   std::printf(" %6.02f%s (%6.02f)\n"
+              , time
+              , units
+              , prev_clock ? double(new_clock)/double(prev_clock): 1.0);
+   prev_clock = new_clock;
+   bool res = is_order_type_ordered(elements, element_count, alg != HeapSort && alg != PdQsort && alg != StdSort);
+   return res;
+}
+
+template<class T>
+bool measure_all(std::size_t L, std::size_t NK)
+{
+   boost::movelib::unique_ptr<T[]> pdata(new T[L]);
+   boost::movelib::unique_ptr<std::size_t[]> pkeys(new std::size_t[NK ? NK : L]);
+   T *A              = pdata.get();
+   std::size_t *Keys = pkeys.get();
+   std::printf("\n - - N: %u, NK: %u - -\n", (unsigned)L, (unsigned)NK);
+
+   nanosecond_type prev_clock = 0;
+   nanosecond_type back_clock;
+   bool res = true;
+   res = res && measure_algo(A,Keys,L,NK,MergeSort, prev_clock);
+   back_clock = prev_clock;
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,StableSort, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,PdQsort, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,StdSort, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,HeapSort, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,QuartAdaptiveSort, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,Sqrt2AdaptiveSort, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,SqrtAdaptiveSort, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,SqrtHAdaptiveSort, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,AdaptiveSort, prev_clock);
+   //
+   prev_clock = back_clock;
+   res = res && measure_algo(A,Keys,L,NK,InplaceStableSort, prev_clock);
+   //
+   //prev_clock = back_clock;
+   //res = res && measure_algo(A,Keys,L,NK,SlowStableSort, prev_clock);
+   //
+   if(!res)
+      throw int(0);
+   return res;
+}
+
+//Undef it to run the long test
+#define BENCH_SORT_SHORT
+#define BENCH_SORT_UNIQUE_VALUES
+
+int main()
+{
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(101,1);
+   measure_all<order_perf_type>(101,7);
+   measure_all<order_perf_type>(101,31);
+   #endif
+   measure_all<order_perf_type>(101,0);
+
+   //
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(1101,1);
+   measure_all<order_perf_type>(1001,7);
+   measure_all<order_perf_type>(1001,31);
+   measure_all<order_perf_type>(1001,127);
+   measure_all<order_perf_type>(1001,511);
+   #endif
+   measure_all<order_perf_type>(1001,0);
+   //
+   #ifndef BENCH_SORT_SHORT
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(10001,65);
+   measure_all<order_perf_type>(10001,255);
+   measure_all<order_perf_type>(10001,1023);
+   measure_all<order_perf_type>(10001,4095);
+   #endif
+   measure_all<order_perf_type>(10001,0);
+
+   //
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(100001,511);
+   measure_all<order_perf_type>(100001,2047);
+   measure_all<order_perf_type>(100001,8191);
+   measure_all<order_perf_type>(100001,32767);
+   #endif
+   measure_all<order_perf_type>(100001,0);
+
+   //
+   #ifdef NDEBUG
+   #ifndef BENCH_SORT_UNIQUE_VALUES
+   measure_all<order_perf_type>(1000001,1);
+   measure_all<order_perf_type>(1000001,1024);
+   measure_all<order_perf_type>(1000001,32768);
+   measure_all<order_perf_type>(1000001,524287);
+   #endif
+   measure_all<order_perf_type>(1000001,0);
+   measure_all<order_perf_type>(1500001,0);
+   #endif   //NDEBUG
+
+   #endif   //#ifndef BENCH_SORT_SHORT
+
+   //measure_all<order_perf_type>(100000001,0);
+
+   return 0;
+}
diff --git a/test/construct_forward.cpp b/test/construct_forward.cpp
new file mode 100644
index 0000000..87c9a80
--- /dev/null
+++ b/test/construct_forward.cpp
@@ -0,0 +1,117 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009-2012.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/utility/enable_if.hpp>
+#include "../example/movable.hpp"
+#include "../example/copymovable.hpp"
+#include <cstdio>
+
+class non_movable
+{
+   public:
+   non_movable()
+   {}
+};
+
+template<class MaybeRvalue>
+void catch_test(BOOST_RV_REF(MaybeRvalue) x
+               #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+               ,typename ::boost::enable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0
+               #endif   //BOOST_NO_CXX11_RVALUE_REFERENCES
+               )
+{  (void)x;}
+
+template<class MaybeRvalue>
+void catch_test(BOOST_COPY_ASSIGN_REF(MaybeRvalue) x
+               #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+               ,typename ::boost::enable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0
+               #endif   //BOOST_NO_CXX11_RVALUE_REFERENCES
+               )
+
+{  (void)x;}
+
+template<class MaybeRvalue>
+void catch_test(MaybeRvalue &x
+               #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+               ,typename ::boost::enable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0
+               #endif   //BOOST_NO_CXX11_RVALUE_REFERENCES
+               )
+{  (void)x;}
+
+               #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+template<class MaybeRvalue>
+void catch_test(const MaybeRvalue& x
+               ,typename ::boost::disable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0
+               )
+{  (void)x;}
+               #endif   //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+movable create_movable()
+{  return movable(); }
+
+copy_movable create_copy_movable()
+{  return copy_movable(); }
+
+non_movable create_non_movable()
+{  return non_movable(); }
+
+
+void catch_test()
+{
+   movable m;
+   const movable constm;
+   catch_test<movable>(boost::move(m));
+   #ifdef BOOST_CATCH_CONST_RLVALUE
+   catch_test<movable>(create_movable());
+   #endif
+   catch_test<movable>(m);
+   catch_test<movable>(constm);
+   copy_movable cm;
+   const copy_movable constcm;
+   catch_test<copy_movable>(boost::move(cm));
+   catch_test<copy_movable>(create_copy_movable());
+   catch_test<copy_movable>(cm);
+   catch_test<copy_movable>(constcm);
+   non_movable nm;
+   const non_movable constnm;
+   catch_test<non_movable>(boost::move(nm));
+   catch_test<non_movable>(create_non_movable());
+   catch_test<non_movable>(nm);
+   catch_test<non_movable>(constnm);
+}
+
+template<class MaybeMovableOnly, class MaybeRvalue>
+void function_construct(BOOST_FWD_REF(MaybeRvalue) x)
+{
+   //Moves in case Convertible is boost::rv<movable> copies otherwise
+   //For C++0x perfect forwarding
+   MaybeMovableOnly m(boost::forward<MaybeRvalue>(x));
+}
+
+void forward_test()
+{
+   movable m;
+   function_construct<movable>(boost::move(m));
+//   non_movable nm;
+//   function_construct<non_movable>(boost::move(nm));
+//   const non_movable cnm;
+//   function_construct<non_movable>(cnm);
+}
+
+int main()
+{
+   catch_test();
+   forward_test();
+   return 0;
+}
+
+#include <boost/move/detail/config_end.hpp>
diff --git a/test/conversion_test.cpp b/test/conversion_test.cpp
new file mode 100644
index 0000000..8e901f8
--- /dev/null
+++ b/test/conversion_test.cpp
@@ -0,0 +1,414 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2010-2012.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/meta_utils.hpp>
+#include <cassert>
+#include <new>
+#include <boost/move/detail/move_helpers.hpp>
+
+
+enum ConstructionType { Copied, Moved, Other };
+
+class conversion_source
+{
+   public:
+   conversion_source(){}
+   operator int() const { return 0; }
+};
+
+class conversion_target
+{
+   ConstructionType c_type_;
+   public:
+   conversion_target(conversion_source)
+      { c_type_ = Other; }
+   conversion_target()
+      { c_type_ = Other; }
+   conversion_target(const conversion_target &)
+      { c_type_ = Copied; }
+   ConstructionType construction_type() const
+      { return c_type_; }
+};
+
+
+class conversion_target_copymovable
+{
+   ConstructionType c_type_;
+   BOOST_COPYABLE_AND_MOVABLE(conversion_target_copymovable)
+   public:
+   conversion_target_copymovable()
+      { c_type_ = Other; }
+   conversion_target_copymovable(conversion_source)
+      { c_type_ = Other; }
+   conversion_target_copymovable(const conversion_target_copymovable &)
+      { c_type_ = Copied; }
+   conversion_target_copymovable(BOOST_RV_REF(conversion_target_copymovable) )
+      { c_type_ = Moved; }
+   conversion_target_copymovable &operator=(BOOST_RV_REF(conversion_target_copymovable) )
+      { c_type_ = Moved; return *this; }
+   conversion_target_copymovable &operator=(BOOST_COPY_ASSIGN_REF(conversion_target_copymovable) )
+      { c_type_ = Copied; return *this; }
+   ConstructionType construction_type() const
+      {  return c_type_; }
+};
+
+class conversion_target_movable
+{
+   ConstructionType c_type_;
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(conversion_target_movable)
+   public:
+   conversion_target_movable()
+      { c_type_ = Other; }
+   conversion_target_movable(conversion_source)
+      { c_type_ = Other; }
+   conversion_target_movable(BOOST_RV_REF(conversion_target_movable) )
+      { c_type_ = Moved; }
+   conversion_target_movable &operator=(BOOST_RV_REF(conversion_target_movable) )
+      { c_type_ = Moved; return *this; }
+   ConstructionType construction_type() const
+      {  return c_type_; }
+};
+
+
+template<class T>
+class container
+{
+   T *storage_;
+   public:
+   struct const_iterator{};
+   struct iterator : const_iterator{};
+   container()
+      : storage_(0)
+   {}
+
+   ~container()
+   {  delete storage_; }
+
+   container(const container &c)
+      : storage_(c.storage_ ? new T(*c.storage_) : 0)
+   {}
+
+   container &operator=(const container &c)
+   {
+      if(storage_){
+         delete storage_;
+         storage_ = 0;
+      }
+      storage_ = c.storage_ ? new T(*c.storage_) : 0;
+      return *this;
+   }
+
+   BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
+
+   BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
+
+   template <class Iterator>
+   iterator insert(Iterator, Iterator){ return iterator(); }
+
+   ConstructionType construction_type() const
+   {  return construction_type_impl
+         (typename ::boost::move_detail::integral_constant<bool, ::boost::move_detail::is_class_or_union<T>::value>());
+   }
+
+   ConstructionType construction_type_impl(::boost::move_detail::true_type) const
+     {  return storage_->construction_type(); }
+
+   ConstructionType construction_type_impl(::boost::move_detail::false_type) const
+     {  return Copied; }
+
+   iterator begin() const { return iterator(); }
+   
+   private:
+   template<class U>
+    void priv_construct(BOOST_MOVE_CATCH_FWD(U) x)
+   {
+      if(storage_){
+         delete storage_;
+         storage_ = 0;
+      }
+      storage_ = new T(::boost::forward<U>(x));
+   }
+
+   template<class U>
+   void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
+   {  priv_construct(::boost::forward<U>(x));   }
+
+   template<class U>
+   iterator priv_insert(const_iterator, BOOST_MOVE_CATCH_FWD(U) x)
+   {  priv_construct(::boost::forward<U>(x));   return iterator();   }
+};
+
+class recursive_container
+{
+   BOOST_COPYABLE_AND_MOVABLE(recursive_container)
+   public:
+   recursive_container()
+   {}
+
+   recursive_container(const recursive_container &c)
+      : container_(c.container_)
+   {}
+
+   recursive_container(BOOST_RV_REF(recursive_container) c)
+      : container_(::boost::move(c.container_))
+   {}
+
+   recursive_container & operator =(BOOST_COPY_ASSIGN_REF(recursive_container) c)
+   {
+      container_= c.container_;
+      return *this;
+   }
+
+   recursive_container & operator =(BOOST_RV_REF(recursive_container) c)
+   {
+      container_= ::boost::move(c.container_);
+      return *this;
+   }
+
+   container<recursive_container> container_;
+   friend bool operator< (const recursive_container &a, const recursive_container &b)
+   {  return &a < &b;   }
+};
+
+
+int main()
+{
+   conversion_target_movable a;
+   conversion_target_movable b(::boost::move(a));
+   {
+      container<conversion_target> c;
+      {
+         conversion_target x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         const conversion_target x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         c.push_back(conversion_target());
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), conversion_target());
+         assert(c.construction_type() == Copied);
+      }
+      {
+         conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         const conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         c.push_back(conversion_source());
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), conversion_source());
+         assert(c.construction_type() == Copied);
+      }
+   }
+
+   {
+      container<conversion_target_copymovable> c;
+      {
+         conversion_target_copymovable x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         const conversion_target_copymovable x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         c.push_back(conversion_target_copymovable());
+         assert(c.construction_type() == Moved);
+         c.insert(c.begin(), conversion_target_copymovable());
+         assert(c.construction_type() == Moved);
+      }
+      {
+         conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Moved);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Moved);
+      }
+      {
+         const conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Moved);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Moved);
+      }
+      {
+         c.push_back(conversion_source());
+         assert(c.construction_type() == Moved);
+         c.insert(c.begin(), conversion_source());
+         assert(c.construction_type() == Moved);
+      }
+   }
+   {
+      container<conversion_target_movable> c;
+      //This should not compile
+      //{
+      //   conversion_target_movable x;
+      //   c.push_back(x);
+      //   assert(c.construction_type() == Copied);
+      //}
+      //{
+      //   const conversion_target_movable x;
+      //   c.push_back(x);
+      //   assert(c.construction_type() == Copied);
+      //}
+      {
+         c.push_back(conversion_target_movable());
+         assert(c.construction_type() == Moved);
+         c.insert(c.begin(), conversion_target_movable());
+         assert(c.construction_type() == Moved);
+      }
+      {
+         conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Moved);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Moved);
+      }
+      {
+         const conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Moved);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Moved);
+      }
+      {
+         c.push_back(conversion_source());
+         assert(c.construction_type() == Moved);
+         c.insert(c.begin(), conversion_source());
+         assert(c.construction_type() == Moved);
+      }
+   }
+   {
+      container<int> c;
+      {
+         int x = 0;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), c.construction_type());
+         assert(c.construction_type() == Copied);
+      }
+      {
+         const int x = 0;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         c.push_back(int(0));
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), int(0));
+         assert(c.construction_type() == Copied);
+      }
+      {
+         conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+
+      {
+         const conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         c.push_back(conversion_source());
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), conversion_source());
+         assert(c.construction_type() == Copied);
+      }
+      //c.insert(c.begin(), c.begin());
+   }
+
+   {
+      container<int> c;
+      {
+         int x = 0;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), c.construction_type());
+         assert(c.construction_type() == Copied);
+      }
+      {
+         const int x = 0;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         c.push_back(int(0));
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), int(0));
+         assert(c.construction_type() == Copied);
+      }
+      {
+         conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+
+      {
+         const conversion_source x;
+         c.push_back(x);
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), x);
+         assert(c.construction_type() == Copied);
+      }
+      {
+         c.push_back(conversion_source());
+         assert(c.construction_type() == Copied);
+         c.insert(c.begin(), conversion_source());
+         assert(c.construction_type() == Copied);
+      }
+      c.insert(c.begin(), c.begin());
+   }
+
+   {
+      recursive_container c;
+      recursive_container internal;
+      c.container_.insert(c.container_.begin(), recursive_container());
+      c.container_.insert(c.container_.begin(), internal);
+      c.container_.insert(c.container_.begin(), c.container_.begin());
+   }
+
+   return 0;
+}
diff --git a/test/copy_elision_test.cpp b/test/copy_elision_test.cpp
new file mode 100644
index 0000000..39123e1
--- /dev/null
+++ b/test/copy_elision_test.cpp
@@ -0,0 +1,177 @@
+// Copyright David Abrahams 2009. 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)
+
+#include <boost/move/detail/config_begin.hpp>
+#include <iostream>
+#include <boost/core/lightweight_test.hpp>
+
+#ifdef NO_MOVE
+# undef BOOST_COPY_ASSIGN_REF
+# define BOOST_COPY_ASSIGN_REF(X) X const&
+# undef BOOST_COPYABLE_AND_MOVABLE
+# define BOOST_COPYABLE_AND_MOVABLE(X)
+# define MOVE(x) (x)
+#else
+#include <boost/move/utility_core.hpp>
+# define MOVE(x) boost::move(x)
+#endif
+
+struct X
+{
+    X() : id(instances++)
+    {
+        std::cout << "X" << id << ": construct\n";
+    }
+    
+    X(X const& rhs) : id(instances++)
+    {
+        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": **copy**\n";
+        ++copies;
+    }
+
+    // This particular test doesn't exercise assignment, but for
+    // completeness:
+    X& operator=(BOOST_COPY_ASSIGN_REF(X) rhs)
+    {
+        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": assign\n";
+        return *this;
+    }
+
+#ifndef NO_MOVE
+    X& operator=(BOOST_RV_REF(X) rhs)
+    {
+        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": move assign\n";
+        return *this;
+    }
+    
+    X(BOOST_RV_REF(X) rhs) : id(instances++)
+    {
+        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": ..move construct..\n";
+        ++copies;
+    }
+#endif 
+
+    ~X() { std::cout << "X" << id << ": destroy\n"; }
+
+    unsigned id;
+    
+    static unsigned copies;
+    static unsigned instances;
+
+    BOOST_COPYABLE_AND_MOVABLE(X)
+};
+
+unsigned X::copies = 0;
+unsigned X::instances = 0;
+
+#define CHECK_COPIES( stmt, min, max, comment )                         \
+{                                                                       \
+    unsigned const old_copies = X::copies;                              \
+                                                                        \
+    std::cout << "\n" comment "\n" #stmt "\n===========\n";             \
+    {                                                                   \
+        stmt;                                                           \
+    }                                                                   \
+    unsigned const n = X::copies - old_copies;                          \
+    volatile unsigned const minv(min), maxv(max);                       \
+    BOOST_TEST(n <= maxv);                                              \
+    if (n > maxv)                                                       \
+        std::cout << "*** max is too low or compiler is buggy ***\n";   \
+    BOOST_TEST(n >= minv);                                              \
+    if (n < minv)                                                       \
+        std::cout << "*** min is too high or compiler is buggy ***\n";  \
+                                                                        \
+    std::cout << "-----------\n"                                        \
+              << n << "/" << max                                        \
+              << " possible copies/moves made\n"                        \
+              << max - n << "/" << max - min                            \
+              << " possible elisions performed\n\n";                    \
+                                                                        \
+    if (n > minv)                                                       \
+        std::cout << "*** " << n - min                                  \
+                  << " possible elisions missed! ***\n";                \
+}
+
+struct trace
+{
+    trace(char const* name)
+        : m_name(name)
+    {
+        std::cout << "->: " << m_name << "\n";
+    }
+    
+    ~trace()
+    {
+        std::cout << "<-: " << m_name << "\n";
+    }
+    
+    char const* m_name;
+};
+
+void sink(X)
+{
+  trace t("sink");
+}
+
+X nrvo_source()
+{
+    trace t("nrvo_source");
+    X a;
+    return a;
+}
+
+X urvo_source()
+{
+    trace t("urvo_source");
+    return X();
+}
+
+X identity(X a)
+{
+    trace t("identity");
+    return a;
+}
+
+X lvalue_;
+X& lvalue()
+{
+    return lvalue_;
+}
+typedef X rvalue;
+
+X ternary( bool y )
+{
+    X a, b;
+    return MOVE(y?a:b);
+}
+
+int main(int argc, char* argv[])
+{
+   (void)argv;
+    // Double parens prevent "most vexing parse"
+    CHECK_COPIES( X a(( lvalue() )), 1U, 1U, "Direct initialization from lvalue");
+    CHECK_COPIES( X a(( rvalue() )), 0U, 1U, "Direct initialization from rvalue");
+    
+    CHECK_COPIES( X a = lvalue(), 1U, 1U, "Copy initialization from lvalue" );
+    CHECK_COPIES( X a = rvalue(), 0U, 1U, "Copy initialization from rvalue" );
+
+    CHECK_COPIES( sink( lvalue() ), 1U, 1U, "Pass lvalue by value" );
+    CHECK_COPIES( sink( rvalue() ), 0U, 1U, "Pass rvalue by value" );
+
+    CHECK_COPIES( nrvo_source(), 0U, 1U, "Named return value optimization (NRVO)" );
+    CHECK_COPIES( urvo_source(), 0U, 1U, "Unnamed return value optimization (URVO)" );
+
+    // Just to prove these things compose properly
+    CHECK_COPIES( X a(urvo_source()), 0U, 2U, "Return value used as ctor arg" );
+    
+    // Expect to miss one possible elision here
+    CHECK_COPIES( identity( rvalue() ), 0U, 2U, "Return rvalue passed by value" );
+
+    // Expect to miss an elision in at least one of the following lines
+    CHECK_COPIES( X a = ternary( argc == 1000 ), 0U, 2U, "Return result of ternary operation" );
+    CHECK_COPIES( X a = ternary( argc != 1000 ), 0U, 2U, "Return result of ternary operation again" );
+    return boost::report_errors();
+}
+
+#include <boost/move/detail/config_end.hpp>
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>
diff --git a/test/inplace_merge_test.cpp b/test/inplace_merge_test.cpp
new file mode 100644
index 0000000..b69bce0
--- /dev/null
+++ b/test/inplace_merge_test.cpp
@@ -0,0 +1,283 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2016-2016.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
+#define BOOST_MOVE_ADAPTIVE_SORT_STATS
+
+#include "order_type.hpp"
+
+#include <iostream>  //std::cout
+#include <boost/config.hpp>
+
+#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/move/make_unique.hpp>
+
+#include <boost/move/detail/type_traits.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+#include <cstddef>
+
+const std::size_t BlockSize = 7u;
+
+#if defined(BOOST_MSVC)
+#pragma warning (disable : 4267)
+#endif
+
+
+const std::size_t left_merge = 0;
+const std::size_t buf_merge  = 1;
+const std::size_t unbuf_merge= 2;
+const std::size_t max_merge  = 3;
+
+template<class Op>
+void alternating_test(
+   const std::size_t NumBlocksA,
+   const std::size_t NumBlocksB,
+   const std::size_t ExtraA,
+   const std::size_t ExtraB,
+   Op op)
+{
+   using namespace boost::movelib::detail_adaptive;
+
+
+   const std::size_t DataSize   = ExtraA + NumBlocksA*BlockSize + NumBlocksB*BlockSize + ExtraB;
+   const std::size_t KeySize    = NumBlocksA + NumBlocksB + 1;
+   const std::size_t HdrSize    = BlockSize + KeySize;
+   const std::size_t ArraySize  = HdrSize + DataSize;
+
+   boost::movelib::unique_ptr<order_move_type[]> testarray(boost::movelib::make_unique<order_move_type[]>(ArraySize));
+
+
+   for(std::size_t szt_merge = 0; szt_merge != max_merge; ++szt_merge){
+      //Order keys
+      for (std::size_t szt_i = 0u; szt_i != KeySize; ++szt_i) {
+         testarray[szt_i].key = szt_i;
+         testarray[szt_i].val = std::size_t(-1);
+      }
+
+      //Order buffer
+      for (std::size_t szt_i = 0u; szt_i != BlockSize; ++szt_i) {
+         testarray[KeySize+szt_i].key = std::size_t(-1);
+         testarray[KeySize+szt_i].val = szt_i;
+      }
+
+      //Block A
+      std::size_t szt_k = 0;
+      for (std::size_t szt_i = 0u; szt_i != ExtraA;  ++szt_i) {
+         testarray[HdrSize+szt_k].key = (szt_k/2)*2;
+         testarray[HdrSize+szt_k].val = szt_k & 1;
+         ++szt_k;
+      }
+
+      for (std::size_t szt_b = 0u; szt_b != NumBlocksA; ++szt_b)
+      for (std::size_t szt_i = 0u; szt_i != BlockSize;  ++szt_i) {
+         testarray[HdrSize+szt_k].key = (szt_k/2)*2;
+         testarray[HdrSize+szt_k].val = szt_k & 1;
+         ++szt_k;
+      }
+
+      //Block B
+      std::size_t szt_l = 0;
+      for (std::size_t szt_b = 0u, szt_t = 0; szt_b != NumBlocksB; ++szt_b)
+      for (std::size_t szt_i = 0u; szt_i != BlockSize;  ++szt_i, ++szt_t) {
+         testarray[HdrSize+szt_k].key = (szt_l/2)*2+1;
+         testarray[HdrSize+szt_k].val = szt_l & 1;
+         ++szt_k;
+         ++szt_l;
+      }
+
+      for (std::size_t szt_i = 0u; szt_i != ExtraB;  ++szt_i) {
+         testarray[HdrSize+szt_k].key = (szt_l/2)*2+1;
+         testarray[HdrSize+szt_k].val = szt_l & 1;
+         ++szt_k;
+         ++szt_l;
+      }
+
+      if(szt_merge == left_merge){
+         //Merge Left
+         op_merge_blocks_left
+            ( testarray.get(), order_type_less()
+            , testarray.get()+HdrSize, BlockSize, ExtraA, NumBlocksA, NumBlocksB, ExtraB
+            , order_type_less(), op );
+         BOOST_TEST( is_order_type_ordered(testarray.get()+KeySize, DataSize) );
+         BOOST_TEST( is_key(testarray.get(), KeySize) );
+         BOOST_TEST(( !boost::move_detail::is_same<Op, boost::movelib::swap_op>::value
+                     || is_buffer(testarray.get()+ KeySize+DataSize, BlockSize) ));
+      }
+      else if(szt_merge == buf_merge){
+         //Merge with buf
+         op_merge_blocks_with_buf
+            ( testarray.get(), order_type_less()
+            , testarray.get()+HdrSize, BlockSize, ExtraA, NumBlocksA, NumBlocksB, ExtraB
+            , order_type_less(), op, testarray.get()+KeySize );
+         BOOST_TEST( is_order_type_ordered(testarray.get()+HdrSize, DataSize) );
+         BOOST_TEST( is_key(testarray.get(), KeySize) );
+         BOOST_TEST(( !boost::move_detail::is_same<Op, boost::movelib::swap_op>::value
+                     || is_buffer(testarray.get()+ KeySize, BlockSize) ));
+      }
+      else if(szt_merge == unbuf_merge){
+         //Merge Left
+         merge_blocks_bufferless
+            ( testarray.get(), order_type_less()
+            , testarray.get()+HdrSize, BlockSize, ExtraA, NumBlocksA, NumBlocksB, ExtraB
+            , order_type_less());
+         BOOST_TEST( is_order_type_ordered(testarray.get()+HdrSize, DataSize) );
+         BOOST_TEST( is_key(testarray.get(), KeySize) );
+         BOOST_TEST(( !boost::move_detail::is_same<Op, boost::movelib::swap_op>::value
+                     || is_buffer(testarray.get()+ KeySize, BlockSize) ));
+      }
+   }
+}
+
+int main()
+{
+   {
+      const std::size_t NumBlocksA = 3u;
+      const std::size_t NumBlocksB = 3u;
+      const std::size_t ExtraA     = BlockSize/2;
+      const std::size_t ExtraB     = ExtraA;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 3u;
+      const std::size_t NumBlocksB = 3u;
+      const std::size_t ExtraA     = 0u;
+      const std::size_t ExtraB     = BlockSize/2;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 3u;
+      const std::size_t NumBlocksB = 3u;
+      const std::size_t ExtraA     = BlockSize/2;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 3u;
+      const std::size_t NumBlocksB = 3u;
+      const std::size_t ExtraA     = 0;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 6u;
+      const std::size_t NumBlocksB = 3u;
+      const std::size_t ExtraA     = BlockSize/2;
+      const std::size_t ExtraB     = ExtraA;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 6u;
+      const std::size_t NumBlocksB = 3u;
+      const std::size_t ExtraA     = BlockSize/2;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 3u;
+      const std::size_t NumBlocksB = 5u;
+      const std::size_t ExtraA     = BlockSize/2;
+      const std::size_t ExtraB     = ExtraA;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 3u;
+      const std::size_t NumBlocksB = 5u;
+      const std::size_t ExtraA     = BlockSize/2;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 0u;
+      const std::size_t NumBlocksB = 0u;
+      const std::size_t ExtraA     = 0;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 0u;
+      const std::size_t NumBlocksB = 0u;
+      const std::size_t ExtraA     = BlockSize/2;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 0u;
+      const std::size_t NumBlocksB = 0u;
+      const std::size_t ExtraA     = 0;
+      const std::size_t ExtraB     = BlockSize/2;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   //
+   {
+      const std::size_t NumBlocksA = 0u;
+      const std::size_t NumBlocksB = 1u;
+      const std::size_t ExtraA     = 0;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 1u;
+      const std::size_t NumBlocksB = 0u;
+      const std::size_t ExtraA     = 0;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 1u;
+      const std::size_t NumBlocksB = 0u;
+      const std::size_t ExtraA     = BlockSize/2;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 0u;
+      const std::size_t NumBlocksB = 1u;
+      const std::size_t ExtraA     = BlockSize/2;
+      const std::size_t ExtraB     = 0;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 1u;
+      const std::size_t NumBlocksB = 0u;
+      const std::size_t ExtraA     = 0;
+      const std::size_t ExtraB     = BlockSize/2;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+   {
+      const std::size_t NumBlocksA = 0u;
+      const std::size_t NumBlocksB = 1u;
+      const std::size_t ExtraA     = 0;
+      const std::size_t ExtraB     = BlockSize/2;
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
+      alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
+   }
+
+   return ::boost::report_errors();
+}
diff --git a/test/move.cpp b/test/move.cpp
new file mode 100644
index 0000000..2d40ec8
--- /dev/null
+++ b/test/move.cpp
@@ -0,0 +1,183 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
+// (C) Copyright Ion Gaztanaga 2009-2014.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/utility_core.hpp>
+#include "../example/movable.hpp"
+#include "../example/copymovable.hpp"
+#include <boost/static_assert.hpp>
+
+movable function(movable m)
+{
+   return movable(boost::move(m));
+}
+
+movable functionr(BOOST_RV_REF(movable) m)
+{
+   return movable(boost::move(m));
+}
+
+movable function2(movable m)
+{
+   return boost::move(m);
+}
+
+BOOST_RV_REF(movable) function2r(BOOST_RV_REF(movable) m)
+{
+   return boost::move(m);
+}
+
+movable move_return_function2 ()
+{
+    return movable();
+}
+
+movable move_return_function ()
+{
+    movable m;
+    return (boost::move(m));
+}
+
+
+//Catch by value
+void function_value(movable)
+{}
+
+//Catch by reference
+void function_ref(const movable &)
+{}
+
+//Catch by reference
+void function_ref(BOOST_RV_REF(movable))
+{}
+
+movable create_movable()
+{  return movable(); }
+
+template<class Type>
+struct factory
+{
+   Type operator()() const
+   {
+      Type t;
+      return BOOST_MOVE_RET(Type, t);
+   }
+};
+
+template<class Type>
+struct factory<Type &>
+{
+   static Type t;
+   Type &operator()() const
+   {
+      return BOOST_MOVE_RET(Type&, t);
+   }
+};
+
+template<class Type>
+Type factory<Type&>::t;
+
+template <class R, class F>
+R factory_wrapper(F f)
+{
+  // lock();
+  R r = f();
+  // unlock();
+  return BOOST_MOVE_RET(R, r);
+}
+
+int main()
+{
+   #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+   BOOST_STATIC_ASSERT((boost::has_nothrow_move<movable>::value == true));
+   BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<copyable>::value == false));
+   BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<copyable*>::value == false));
+   BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<int>::value == false));
+   BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<int&>::value == false));
+   BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<int*>::value == false));
+   #endif
+
+   {
+      movable m;
+      movable m2(boost::move(m));
+      movable m3(function(movable(boost::move(m2))));
+      movable m4(function(boost::move(m3)));
+      (void)m;(void)m2;(void)m3;(void)m4;
+   }
+   {
+      movable m;
+      movable m2(boost::move(m));
+      movable m3(functionr(movable(boost::move(m2))));
+      movable m4(functionr(boost::move(m3))); 
+      (void)m;(void)m2;(void)m3;(void)m4;
+   }
+   {
+      movable m;
+      movable m2(boost::move(m));
+      movable m3(function2(movable(boost::move(m2))));
+      movable m4(function2(boost::move(m3)));
+      (void)m;(void)m2;(void)m3;(void)m4;
+   }
+   {
+      movable m;
+      movable m2(boost::move(m));
+      movable m3(function2r(movable(boost::move(m2))));
+      movable m4(function2r(boost::move(m3)));
+      (void)m;(void)m2;(void)m3;(void)m4;
+   }
+   {
+      movable m;
+      movable m2(boost::move(m));
+      movable m3(move_return_function());
+      (void)m;(void)m2;(void)m3;
+   }
+   {
+      movable m;
+      movable m2(boost::move(m));
+      movable m3(move_return_function2());
+      (void)m;(void)m2;(void)m3;
+   }
+   {
+      //movable
+      movable m (factory_wrapper<movable>(factory<movable>()));
+      m = factory_wrapper<movable>(factory<movable>());
+      movable&mr(factory_wrapper<movable&>(factory<movable&>()));
+      movable&mr2 = factory_wrapper<movable&>(factory<movable&>());
+      (void)mr;
+      (void)mr2;
+      (void)m;
+   }
+   {
+      //copyable
+      copyable c (factory_wrapper<copyable>(factory<copyable>()));
+      c = factory_wrapper<copyable>(factory<copyable>());
+      copyable&cr(factory_wrapper<copyable&>(factory<copyable&>()));
+      copyable&cr2 = factory_wrapper<copyable&>(factory<copyable&>());
+      (void)cr;
+      (void)cr2;
+      (void)c;
+   }
+
+   {
+      //copy_movable
+      copy_movable c (factory_wrapper<copy_movable>(factory<copy_movable>()));
+      c = factory_wrapper<copy_movable>(factory<copy_movable>());
+      copy_movable&cr(factory_wrapper<copy_movable&>(factory<copy_movable&>()));
+      copy_movable&cr2 = factory_wrapper<copy_movable&>(factory<copy_movable&>());
+      (void)cr;
+      (void)cr2;
+      (void)c;
+   }
+
+   return 0;
+}
+
+#include <boost/move/detail/config_end.hpp>
diff --git a/test/move_algorithm.cpp b/test/move_algorithm.cpp
new file mode 100644
index 0000000..2178328
--- /dev/null
+++ b/test/move_algorithm.cpp
@@ -0,0 +1,58 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/algorithm.hpp>
+#include <boost/container/vector.hpp>
+#include "../example/movable.hpp"
+
+int main()
+{
+   namespace bc = ::boost::container;
+   //Default construct 10 movable objects
+   bc::vector<movable> v(10);
+   bc::vector<movable> v2(10);
+
+   //Move to v2
+   boost::move(v.begin(), v.end(), v2.begin());
+
+   //Test values have been moved
+   if(!v[0].moved()){
+      return 1;
+   }
+
+   if(v2.size() != 10){
+      return 1;
+   }
+
+   if(v2[0].moved()){
+      return 1;
+   }
+
+   //Move to v again
+   boost::move_backward(v2.begin(), v2.end(), v.end());
+
+   //Test values have been moved
+   if(!v2[1].moved()){
+      return 1;
+   }
+
+   if(v.size() != 10){
+      return 1;
+   }
+
+   if(v[1].moved()){
+      return 1;
+   }
+
+   return 0;
+}
+
+#include <boost/move/detail/config_end.hpp>
diff --git a/test/move_if_noexcept.cpp b/test/move_if_noexcept.cpp
new file mode 100644
index 0000000..a03a821
--- /dev/null
+++ b/test/move_if_noexcept.cpp
@@ -0,0 +1,230 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Antony Polukhin 2014.
+// (C) Copyright Ion Gaztanaga 2014.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "../example/movable.hpp"
+#include "../example/copymovable.hpp"
+#include <boost/static_assert.hpp>
+
+//////////////////////////////////////////////////////////////////////////////
+//A copy_movable_noexcept class
+class copy_movable_noexcept
+{
+   BOOST_COPYABLE_AND_MOVABLE(copy_movable_noexcept)
+   int value_;
+
+   public:
+   copy_movable_noexcept() : value_(1){}
+
+   //Move constructor and assignment
+   copy_movable_noexcept(BOOST_RV_REF(copy_movable_noexcept) m)
+   {  value_ = m.value_;   m.value_ = 0;  }
+
+   copy_movable_noexcept(const copy_movable_noexcept &m)
+   {  value_ = m.value_;   }
+
+   copy_movable_noexcept & operator=(BOOST_RV_REF(copy_movable_noexcept) m)
+   {  value_ = m.value_;   m.value_ = 0;  return *this;  }
+
+   copy_movable_noexcept & operator=(BOOST_COPY_ASSIGN_REF(copy_movable_noexcept) m)
+   {  value_ = m.value_;   return *this;  }
+
+   bool moved() const //Observer
+   {  return value_ == 0; }
+};
+
+namespace boost{
+
+template<>
+struct has_nothrow_move<copy_movable_noexcept>
+{
+   static const bool value = true;
+};
+
+}  //namespace boost{
+
+//////////////////////////////////////////////////////////////////////////////
+//A movable_throwable class
+class movable_throwable
+{
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_throwable)
+   int value_;
+
+   public:
+   movable_throwable() : value_(1){}
+
+   //Move constructor and assignment
+   movable_throwable(BOOST_RV_REF(movable_throwable) m)
+   {  value_ = m.value_;   m.value_ = 0;  }
+
+   movable_throwable & operator=(BOOST_RV_REF(movable_throwable) m)
+   {  value_ = m.value_;   m.value_ = 0;  return *this;  }
+
+   bool moved() const //Observer
+   {  return !value_; }
+
+   int value() const //Observer
+   {  return value_; }
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Helper functions
+movable function(movable m)
+{
+   return movable(boost::move_if_noexcept(m));
+}
+
+copy_movable function(copy_movable m)
+{
+   return copy_movable(boost::move_if_noexcept(m));
+}
+
+copy_movable_noexcept function(copy_movable_noexcept m)
+{
+   return copy_movable_noexcept(boost::move_if_noexcept(m));
+}
+
+movable_throwable function(movable_throwable m)
+{
+   return movable_throwable(boost::move_if_noexcept(m));
+}
+
+movable functionr(BOOST_RV_REF(movable) m)
+{
+   return movable(boost::move_if_noexcept(m));
+}
+
+movable function2(movable m)
+{
+   return boost::move_if_noexcept(m);
+}
+
+BOOST_RV_REF(movable) function2r(BOOST_RV_REF(movable) m)
+{
+   return boost::move_if_noexcept(m);
+}
+
+movable move_return_function2 ()
+{
+    return movable();
+}
+
+movable move_return_function ()
+{
+    movable m;
+    return (boost::move_if_noexcept(m));
+}
+
+#define BOOST_CHECK(x) if (!(x)) { return __LINE__; }
+
+int main()
+{
+   {
+      movable m;
+      movable m2(boost::move_if_noexcept(m));
+      BOOST_CHECK(m.moved());
+      movable m3(function(movable(boost::move_if_noexcept(m2))));
+      BOOST_CHECK(m2.moved());
+      movable m4(function(boost::move_if_noexcept(m3)));
+      BOOST_CHECK(m3.moved());
+      BOOST_CHECK(!m4.moved());
+   }
+   {
+      movable m;
+      movable m2(boost::move_if_noexcept(m));
+      BOOST_CHECK(m.moved());
+      movable m3(functionr(movable(boost::move_if_noexcept(m2))));
+      BOOST_CHECK(m2.moved());
+      movable m4(functionr(boost::move_if_noexcept(m3)));
+      BOOST_CHECK(m3.moved());
+      BOOST_CHECK(!m4.moved());
+   }
+   {
+      movable m;
+      movable m2(boost::move_if_noexcept(m));
+      BOOST_CHECK(m.moved());
+      movable m3(function2(movable(boost::move_if_noexcept(m2))));
+      BOOST_CHECK(m2.moved());
+      movable m4(function2(boost::move_if_noexcept(m3)));
+      BOOST_CHECK(m3.moved());
+      BOOST_CHECK(!m4.moved());
+   }
+   {
+      movable m;
+      movable m2(boost::move_if_noexcept(m));
+      BOOST_CHECK(m.moved());
+      movable m3(function2r(movable(boost::move_if_noexcept(m2))));
+      BOOST_CHECK(m2.moved());
+      movable m4(function2r(boost::move_if_noexcept(m3)));
+      BOOST_CHECK(m3.moved());
+      BOOST_CHECK(!m4.moved());
+   }
+   {
+      movable m;
+      movable m2(boost::move_if_noexcept(m));
+      BOOST_CHECK(m.moved());
+      BOOST_CHECK(!m2.moved());
+      movable m3(move_return_function());
+      BOOST_CHECK(!m3.moved());
+   }
+   {
+      movable m;
+      movable m2(boost::move_if_noexcept(m));
+      BOOST_CHECK(m.moved());
+      BOOST_CHECK(!m2.moved());
+      movable m3(move_return_function2());
+      BOOST_CHECK(!m3.moved());
+   }
+
+   // copy_movable may throw during move, so it must be copied
+   {
+      copy_movable m;
+      copy_movable m2(boost::move_if_noexcept(m));
+      BOOST_CHECK(!m.moved());
+      copy_movable m3(function(copy_movable(boost::move_if_noexcept(m2))));
+      BOOST_CHECK(!m2.moved());
+      copy_movable m4(function(boost::move_if_noexcept(m3)));
+      BOOST_CHECK(!m3.moved());
+      BOOST_CHECK(!m4.moved());
+   }
+
+
+   // copy_movable_noexcept can not throw during move
+   {
+      copy_movable_noexcept m;
+      copy_movable_noexcept m2(boost::move_if_noexcept(m));
+      BOOST_CHECK(m.moved());
+      copy_movable_noexcept m3(function(copy_movable_noexcept(boost::move_if_noexcept(m2))));
+      BOOST_CHECK(m2.moved());
+      copy_movable_noexcept m4(function(boost::move_if_noexcept(m3)));
+      BOOST_CHECK(m3.moved());
+      BOOST_CHECK(!m4.moved());
+   }
+
+   // movable_throwable can not throw during move but it has no copy constructor
+   {
+      movable_throwable m;
+      movable_throwable m2(boost::move_if_noexcept(m));
+      BOOST_CHECK(m.moved());
+      movable_throwable m3(function(movable_throwable(boost::move_if_noexcept(m2))));
+      BOOST_CHECK(m2.moved());
+      movable_throwable m4(function(boost::move_if_noexcept(m3)));
+      BOOST_CHECK(m3.moved());
+      BOOST_CHECK(!m4.moved());
+   }
+
+   return boost::report_errors();
+}
+
+#include <boost/move/detail/config_end.hpp>
diff --git a/test/move_iterator.cpp b/test/move_iterator.cpp
new file mode 100644
index 0000000..fded99a
--- /dev/null
+++ b/test/move_iterator.cpp
@@ -0,0 +1,44 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "../example/movable.hpp"
+
+int main()
+{
+   namespace bc = ::boost::container;
+   //Default construct 10 movable objects
+   bc::vector<movable> v(10);
+
+   //Test default constructed value
+   BOOST_TEST(!v[0].moved());
+
+   //Move values
+   bc::vector<movable> v2
+      (boost::make_move_iterator(v.begin()), boost::make_move_iterator(v.end()));
+
+   //Test values have been moved
+   BOOST_TEST(v[0].moved());
+   BOOST_TEST(v2.size() == 10);
+
+   //Move again
+   v.assign(boost::make_move_iterator(v2.begin()), boost::make_move_iterator(v2.end()));
+
+   //Test values have been moved
+   BOOST_TEST(v2[0].moved());
+   BOOST_TEST(!v[0].moved());
+
+   return ::boost::report_errors();
+}
+
+#include <boost/move/detail/config_end.hpp>
diff --git a/test/order_type.hpp b/test/order_type.hpp
new file mode 100644
index 0000000..da4a90a
--- /dev/null
+++ b/test/order_type.hpp
@@ -0,0 +1,172 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2016.
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_TEST_ORDER_TYPE_HPP
+#define BOOST_MOVE_TEST_ORDER_TYPE_HPP
+
+#include <boost/config.hpp>
+#include <boost/move/core.hpp>
+#include <cstddef>
+#include <cstdio>
+
+struct order_perf_type
+{
+   public:
+   std::size_t key;
+   std::size_t val;
+
+   order_perf_type()
+   {
+      ++num_elements;
+   }
+
+   order_perf_type(const order_perf_type& other)
+      : key(other.key), val(other.val)
+   {
+      ++num_elements;
+      ++num_copy;
+   }
+
+   order_perf_type & operator=(const order_perf_type& other)
+   {
+      ++num_copy;
+      key = other.key;
+      val = other.val;
+      return *this;
+   }
+
+   ~order_perf_type ()
+   {
+      --num_elements;
+   }
+
+   static void reset_stats()
+   {
+      num_compare=0;
+      num_copy=0;
+   }
+
+   friend bool operator< (const order_perf_type& left, const order_perf_type& right)
+   {  ++num_compare; return left.key < right.key;  }
+
+   static boost::ulong_long_type num_compare;
+   static boost::ulong_long_type num_copy;
+   static boost::ulong_long_type num_elements;
+};
+
+boost::ulong_long_type order_perf_type::num_compare = 0;
+boost::ulong_long_type order_perf_type::num_copy = 0;
+boost::ulong_long_type order_perf_type::num_elements = 0;
+
+
+struct order_move_type
+{
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(order_move_type)
+
+   public:
+   std::size_t key;
+   std::size_t val;
+
+   static const std::size_t moved_constr_mark = std::size_t(-1);
+   static const std::size_t moved_assign_mark = std::size_t(-2);
+
+   order_move_type()
+      : key(0u), val(0u)
+   {}
+
+   order_move_type(BOOST_RV_REF(order_move_type) other)
+      : key(other.key), val(other.val)
+   {
+      other.key = other.val = std::size_t(-1);
+   }
+
+   order_move_type & operator=(BOOST_RV_REF(order_move_type) other)
+   {
+      key = other.key;
+      val = other.val;
+      other.key = other.val = std::size_t(-2);
+      return *this;
+   }
+
+   friend bool operator< (const order_move_type& left, const order_move_type& right)
+   {  return left.key < right.key;  }
+
+   ~order_move_type ()
+   {
+      key = val = std::size_t(-3);
+   }
+};
+
+struct order_type_less
+{
+   template<class T, class U>
+   bool operator()(const T &a, U const &b) const
+   {  return a < b;   }
+};
+
+template<class T>
+inline bool is_order_type_ordered(T *elements, std::size_t element_count, bool stable = true)
+{
+   for(std::size_t i = 1; i < element_count; ++i){
+      if(order_type_less()(elements[i], elements[i-1])){
+         std::printf("\n Ord KO !!!!");
+         return false;
+      }
+      if( stable && !(order_type_less()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
+         std::printf("\n Stb KO !!!! ");
+         return false;
+      }
+   }
+   return true;
+}
+
+namespace boost {
+namespace movelib {
+namespace detail_adaptive {
+
+
+
+}}}
+
+template<class T>
+inline bool is_key(T *elements, std::size_t element_count)
+{
+   for(std::size_t i = 1; i < element_count; ++i){
+      if(elements[i].key >= element_count){
+         std::printf("\n Key.key KO !!!!");
+         return false;
+      }
+      if(elements[i].val != std::size_t(-1)){
+         std::printf("\n Key.val KO !!!!");
+         return false;
+      }
+   }
+   return true;
+}
+
+template<class T>
+inline bool is_buffer(T *elements, std::size_t element_count)
+{
+   for(std::size_t i = 1; i < element_count; ++i){
+      if(elements[i].key != std::size_t(-1)){
+         std::printf("\n Buf.key KO !!!!");
+         return false;
+      }
+      if(elements[i].val >= element_count){
+         std::printf("\n Buf.val KO !!!!");
+         return false;
+      }
+   }
+   return true;
+}
+
+
+#endif   //BOOST_MOVE_TEST_ORDER_TYPE_HPP
diff --git a/test/random_shuffle.hpp b/test/random_shuffle.hpp
new file mode 100644
index 0000000..5041d96
--- /dev/null
+++ b/test/random_shuffle.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_MOVE_TEST_RANDOM_SHUFFLE_HPP
+#define BOOST_MOVE_TEST_RANDOM_SHUFFLE_HPP
+
+
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <stdlib.h>
+
+template< class RandomIt >
+void random_shuffle( RandomIt first, RandomIt last )
+{
+   typedef typename boost::movelib::iterator_traits<RandomIt>::difference_type difference_type;
+   difference_type n = last - first;
+   for (difference_type i = n-1; i > 0; --i) {
+      difference_type j = std::rand() % (i+1);
+      if(j != i) {
+         boost::adl_move_swap(first[i], first[j]);
+      }
+   }
+}
+
+
+#endif// BOOST_MOVE_TEST_RANDOM_SHUFFLE_HPP
diff --git a/test/type_traits.cpp b/test/type_traits.cpp
new file mode 100644
index 0000000..3625777
--- /dev/null
+++ b/test/type_traits.cpp
@@ -0,0 +1,98 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/detail/type_traits.hpp>
+#include <boost/move/core.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+//
+//       pod_struct
+//
+#if defined(BOOST_MOVE_IS_POD)
+struct pod_struct
+{
+   int i;
+   float f;
+};
+#endif
+
+//
+//       deleted_copy_and_assign_type
+//
+#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+
+struct deleted_copy_and_assign_type
+{
+   deleted_copy_and_assign_type(const deleted_copy_and_assign_type&) = delete;
+   deleted_copy_and_assign_type & operator=(const deleted_copy_and_assign_type&) = delete;
+};
+
+#endif   //defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+
+//
+//       boost_move_type
+//
+class boost_move_type
+{
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(boost_move_type)
+   public:
+   boost_move_type(BOOST_RV_REF(boost_move_type)){}
+   boost_move_type & operator=(BOOST_RV_REF(boost_move_type)){ return *this; }
+};
+
+namespace is_pod_test
+{
+
+void test()
+{
+   BOOST_STATIC_ASSERT((boost::move_detail::is_pod<int>::value));
+   #if defined(BOOST_MOVE_IS_POD)
+   BOOST_STATIC_ASSERT((boost::move_detail::is_pod<pod_struct>::value));
+   #endif
+}
+
+}  //namespace is_pod_test
+
+namespace trivially_memcopyable_test {
+
+void test()
+{
+   #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+   BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible<deleted_copy_and_assign_type>::value));
+   BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable<deleted_copy_and_assign_type>::value));
+   #endif   //#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+   //boost_move_type
+   BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible<boost_move_type>::value));
+   BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable<boost_move_type>::value));
+   BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_constructible<boost_move_type>::value));
+   BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_assignable<boost_move_type>::value));
+   //POD
+   BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_constructible<int>::value));
+   BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_assignable<int>::value));
+   BOOST_STATIC_ASSERT((boost::move_detail::is_copy_constructible<int>::value));
+   BOOST_STATIC_ASSERT((boost::move_detail::is_copy_assignable<int>::value));
+   #if defined(BOOST_MOVE_IS_POD)
+   BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_constructible<pod_struct>::value));
+   BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_assignable<pod_struct>::value));
+   BOOST_STATIC_ASSERT((boost::move_detail::is_copy_constructible<pod_struct>::value));
+   BOOST_STATIC_ASSERT((boost::move_detail::is_copy_assignable<pod_struct>::value));
+   #endif
+}
+
+}  //namespace trivially_memcopyable_test {
+
+int main()
+{
+   trivially_memcopyable_test::test();
+   is_pod_test::test();
+   boost::report_errors();
+}
diff --git a/test/unique_ptr_assign.cpp b/test/unique_ptr_assign.cpp
new file mode 100644
index 0000000..088b7f4
--- /dev/null
+++ b/test/unique_ptr_assign.cpp
@@ -0,0 +1,444 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/utility_core.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+//////////////////////////////////////////////
+//
+// The initial implementation of these tests
+// was written by Howard Hinnant. 
+//
+// These test were later refactored grouping
+// and porting them to Boost.Move.
+//
+// Many thanks to Howard for releasing his C++03
+// unique_ptr implementation with such detailed
+// test cases.
+//
+//////////////////////////////////////////////
+
+#include "unique_ptr_test_utils_beg.hpp"
+
+namespace bml = ::boost::movelib;
+
+////////////////////////////////
+//   unique_ptr_asgn_move_convert_defdel
+////////////////////////////////
+namespace unique_ptr_asgn_move_convert_defdel {
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<B> s(new B);
+   A* p = s.get();
+   bml::unique_ptr<A> s2(new A);
+   BOOST_TEST(A::count == 2);
+   s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[]> s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<const A[]> s2(new const A[2]);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[2]> s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<const A[2]> s2(new const A[2]);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   }
+   {
+   BOOST_TEST(A::count == 0);
+   bml::unique_ptr<A[2]> s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<const A[]> s2(new const A[2]);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_asgn_move_convert_defdel{
+
+////////////////////////////////
+//   unique_ptr_asgn_move_convert_movdel
+////////////////////////////////
+
+namespace unique_ptr_asgn_move_convert_movedel{
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<B, move_constr_deleter<B> > s(new B);
+   A* p = s.get();
+   bml::unique_ptr<A, move_constr_deleter<A> > s2(new A);
+   BOOST_TEST(A::count == 2);
+   s2 = (boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[], move_constr_deleter<A[]> > s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<const A[], move_constr_deleter<const A[]> > s2(new const A[2]);
+   BOOST_TEST(A::count == 4);
+   s2 = (boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s(new A[3]);
+   A* p = s.get();
+   bml::unique_ptr<const A[2], move_constr_deleter<const A[2]> > s2(new const A[2]);
+   BOOST_TEST(A::count == 5);
+   s2 = (boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 3);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   reset_counters();
+   {
+   bml::unique_ptr<A[2], move_constr_deleter<A[3]> > s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<const A[], move_constr_deleter<const A[]> > s2(new const A[2]);
+   BOOST_TEST(A::count == 4);
+   s2 = (boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_asgn_move_convert_movedel{
+
+////////////////////////////////
+//   unique_ptr_asgn_move_convert_copydelref
+////////////////////////////////
+
+namespace unique_ptr_asgn_move_convert_copydelref{
+
+// test converting move assignment with reference deleters
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   copy_constr_deleter<B> db(5);
+   bml::unique_ptr<B, copy_constr_deleter<B>&> s(new B, db);
+   A* p = s.get();
+   copy_constr_deleter<A> da(6);
+   bml::unique_ptr<A, copy_constr_deleter<A>&> s2(new A, da);
+   s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   copy_constr_deleter<A[]> db(5);
+   bml::unique_ptr<A[], copy_constr_deleter<A[]>&> s(new A[2], db);
+   A* p = s.get();
+   copy_constr_deleter<const A[]> da(6);
+   bml::unique_ptr<const A[], copy_constr_deleter<const A[]>&> s2(new const A[2], da);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   copy_constr_deleter<A[2]> db(5);
+   bml::unique_ptr<A[2], copy_constr_deleter<A[2]>&> s(new A[2], db);
+   A* p = s.get();
+   copy_constr_deleter<const A[2]> da(6);
+   bml::unique_ptr<const A[2], copy_constr_deleter<const A[2]>&> s2(new const A[2], da);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   reset_counters();
+   {
+   copy_constr_deleter<A[2]> db(5);
+   bml::unique_ptr<A[2], copy_constr_deleter<A[2]>&> s(new A[2], db);
+   A* p = s.get();
+   copy_constr_deleter<const A[]> da(6);
+   bml::unique_ptr<const A[], copy_constr_deleter<const A[]>&> s2(new const A[2], da);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_asgn_move_convert_copydelref{
+
+////////////////////////////////
+//   unique_ptr_asgn_move_defdel
+////////////////////////////////
+namespace unique_ptr_asgn_move_defdel {
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A> s1(new A);
+   A* p = s1.get();
+   bml::unique_ptr<A> s2(new A);
+   BOOST_TEST(A::count == 2);
+   s2 = boost::move(s1);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s1.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[]> s1(new A[2]);
+   A* p = s1.get();
+   bml::unique_ptr<A[]> s2(new A[2]);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s1);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s1.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[2]> s1(new A[2]);
+   A* p = s1.get();
+   bml::unique_ptr<A[2]> s2(new A[2]);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s1);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s1.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //unique_ptr_asgn_move_defdel
+
+////////////////////////////////
+//   unique_ptr_asgn_move_movedel
+////////////////////////////////
+namespace unique_ptr_asgn_move_movedel {
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A, move_constr_deleter<A> > s1(new A);
+   A* p = s1.get();
+   bml::unique_ptr<A, move_constr_deleter<A> > s2(new A);
+   BOOST_TEST(A::count == 2);
+   s2 = boost::move(s1);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s1.get() == 0);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s1.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[], move_constr_deleter<A[]> > s1(new A[2]);
+   A* p = s1.get();
+   bml::unique_ptr<A[], move_constr_deleter<A[]> > s2(new A[2]);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s1);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s1.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s1.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s1(new A[2]);
+   A* p = s1.get();
+   bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s2(new A[2]);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s1);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s1.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s1.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //unique_ptr_asgn_move_movedel
+
+////////////////////////////////
+//   unique_ptr_asgn_move_copydelref
+////////////////////////////////
+namespace unique_ptr_asgn_move_copydelref {
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   copy_constr_deleter<A> d1(5);
+   bml::unique_ptr<A, copy_constr_deleter<A>&> s1(new A, d1);
+   A* p = s1.get();
+   copy_constr_deleter<A> d2(6);
+   bml::unique_ptr<A, copy_constr_deleter<A>&> s2(new A, d2);
+   s2 = boost::move(s1);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s1.get() == 0);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(d1.state() == 5);
+   BOOST_TEST(d2.state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   copy_constr_deleter<A[]> d1(5);
+   bml::unique_ptr<A[], copy_constr_deleter<A[]>&> s1(new A[2], d1);
+   A* p = s1.get();
+   copy_constr_deleter<A[]> d2(6);
+   bml::unique_ptr<A[], copy_constr_deleter<A[]>&> s2(new A[2], d2);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s1);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s1.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(d1.state() == 5);
+   BOOST_TEST(d2.state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   copy_constr_deleter<A[2]> d1(5);
+   bml::unique_ptr<A[2], copy_constr_deleter<A[2]>&> s1(new A[2], d1);
+   A* p = s1.get();
+   copy_constr_deleter<A[2]> d2(6);
+   bml::unique_ptr<A[2], copy_constr_deleter<A[2]>&> s2(new A[2], d2);
+   BOOST_TEST(A::count == 4);
+   s2 = boost::move(s1);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s1.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(d1.state() == 5);
+   BOOST_TEST(d2.state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //unique_ptr_asgn_move_copydelref
+
+////////////////////////////////
+//             main
+////////////////////////////////
+int main()
+{
+   //Assignment
+   unique_ptr_asgn_move_convert_defdel::test();
+   unique_ptr_asgn_move_convert_movedel::test();
+   unique_ptr_asgn_move_convert_copydelref::test();
+   unique_ptr_asgn_move_defdel::test();
+   unique_ptr_asgn_move_movedel::test();
+   unique_ptr_asgn_move_copydelref::test();
+
+   //Test results
+   return boost::report_errors();
+}
+
+#include "unique_ptr_test_utils_end.hpp"
diff --git a/test/unique_ptr_ctordtor.cpp b/test/unique_ptr_ctordtor.cpp
new file mode 100644
index 0000000..a583b92
--- /dev/null
+++ b/test/unique_ptr_ctordtor.cpp
@@ -0,0 +1,811 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/utility_core.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+//////////////////////////////////////////////
+//
+// The initial implementation of these tests
+// was written by Howard Hinnant. 
+//
+// These test were later refactored grouping
+// and porting them to Boost.Move.
+//
+// Many thanks to Howard for releasing his C++03
+// unique_ptr implementation with such detailed
+// test cases.
+//
+//////////////////////////////////////////////
+
+#include "unique_ptr_test_utils_beg.hpp"
+
+namespace bml = ::boost::movelib;
+
+////////////////////////////////
+//   unique_ptr_dtor_null
+////////////////////////////////
+
+namespace unique_ptr_dtor_null{
+
+// The deleter is not called if get() == 0
+
+void test()
+{
+   //Single unique_ptr
+   {
+   def_constr_deleter<int> d;
+   BOOST_TEST(d.state() == 5);
+   {
+   bml::unique_ptr<int, def_constr_deleter<int>&> p(0, d);
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(&p.get_deleter() == &d);
+   }
+   BOOST_TEST(d.state() == 5);
+   }
+   {
+   //Unbounded array unique_ptr
+   def_constr_deleter<int[]> d;
+   BOOST_TEST(d.state() == 5);
+   {
+   bml::unique_ptr<int[], def_constr_deleter<int[]>&> p(0, d);
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(&p.get_deleter() == &d);
+   }
+   BOOST_TEST(d.state() == 5);
+   }
+   {
+   //Bounded array unique_ptr
+   def_constr_deleter<int[2]> d;
+   BOOST_TEST(d.state() == 5);
+   {
+   bml::unique_ptr<int[2], def_constr_deleter<int[2]>&> p(0, d);
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(&p.get_deleter() == &d);
+   }
+   BOOST_TEST(d.state() == 5);
+   }
+}
+
+}  //namespace unique_ptr_dtor_null{
+
+////////////////////////////////
+//   unique_ptr_ctor_default_delreq
+////////////////////////////////
+
+namespace unique_ptr_ctor_default_delreq{
+
+// default unique_ptr ctor should only require default deleter ctor
+
+void test()
+{
+   //Single unique_ptr
+   {
+   bml::unique_ptr<int> p;
+   BOOST_TEST(p.get() == 0);
+   }
+   {
+   bml::unique_ptr<int, def_constr_deleter<int> > p;
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(p.get_deleter().state() == 5);
+   }
+   //Unbounded array unique_ptr
+   {
+   bml::unique_ptr<int[]> p;
+   BOOST_TEST(p.get() == 0);
+   }
+   {
+   bml::unique_ptr<int[], def_constr_deleter<int[]> > p;
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(p.get_deleter().state() == 5);
+   }
+
+   //Unbounded array unique_ptr
+   {
+   bml::unique_ptr<int[]> p;
+   BOOST_TEST(p.get() == 0);
+   }
+   {
+   bml::unique_ptr<int[], def_constr_deleter<int[]> > p;
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(p.get_deleter().state() == 5);
+   }
+
+   //Unbounded array unique_ptr
+   {
+   bml::unique_ptr<int[2]> p;
+   BOOST_TEST(p.get() == 0);
+   }
+   {
+   bml::unique_ptr<int[2], def_constr_deleter<int[2]> > p;
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(p.get_deleter().state() == 5);
+   }
+}
+
+}  //namespace unique_ptr_ctor_default_delreq{
+
+////////////////////////////////
+//   unique_ptr_ctor_default_nocomplete
+////////////////////////////////
+
+namespace unique_ptr_ctor_default_nocomplete{
+
+// default unique_ptr ctor shouldn't require complete type
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   J<I> s;
+   BOOST_TEST(s.get() == 0);
+   }
+   check(0);
+   {
+   J<I, def_constr_deleter<I> > s;
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   check(0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   J<I[]> s;
+   BOOST_TEST(s.get() == 0);
+   }
+   check(0);
+   {
+   J<I[], def_constr_deleter<I[]> > s;
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   check(0);
+
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   J<I[2]> s;
+   BOOST_TEST(s.get() == 0);
+   }
+   check(0);
+   {
+   J<I[2], def_constr_deleter<I[2]> > s;
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   check(0);
+}
+
+}  //namespace unique_ptr_ctor_default_nocomplete{
+
+////////////////////////////////
+//   unique_ptr_ctor_pointer_delreq
+////////////////////////////////
+
+namespace unique_ptr_ctor_pointer_delreq{
+
+// unique_ptr(pointer) ctor should only require default deleter ctor
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   A* p = new A;
+   BOOST_TEST(A::count == 1);
+   bml::unique_ptr<A> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   A* p = new A;
+   BOOST_TEST(A::count == 1);
+   bml::unique_ptr<A, def_constr_deleter<A> > s(p);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<A[]> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<A[], def_constr_deleter<A[]> > s(p);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<A[2]> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<A[2], def_constr_deleter<A[2]> > s(p);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_pointer_delreq{
+
+////////////////////////////////
+//   unique_ptr_ctor_pointer_nocomplete
+////////////////////////////////
+
+namespace unique_ptr_ctor_pointer_nocomplete{
+
+// unique_ptr(pointer) ctor shouldn't require complete type
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   I* p = get();
+   check(1);
+   J<I> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   check(0);
+   {
+   I* p = get();
+   check(1);
+   J<I, def_constr_deleter<I> > s(p);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   check(0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   I* p = get_array(2);
+   check(2);
+   J<I[]> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   check(0);
+   {
+   I* p = get_array(2);
+   check(2);
+   J<I[], def_constr_deleter<I[]> > s(p);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   check(0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   I* p = get_array(2);
+   check(2);
+   J<I[]> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   check(0);
+   {
+   I* p = get_array(2);
+   check(2);
+   J<I[2], def_constr_deleter<I[2]> > s(p);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   check(0);
+}
+
+}  //namespace unique_ptr_ctor_pointer_nocomplete{
+
+////////////////////////////////
+//   unique_ptr_ctor_pointer_convert
+////////////////////////////////
+
+namespace unique_ptr_ctor_pointer_convert{
+
+// unique_ptr(pointer) ctor should work with derived pointers
+// or same types (cv aside) for unique_ptr<arrays>
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   B* p = new B;
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   bml::unique_ptr<A> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   {
+   B* p = new B;
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   bml::unique_ptr<A, def_constr_deleter<A> > s(p);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<const A[]> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   const A* p = new const A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<const volatile A[], def_constr_deleter<const volatile A[]> > s(p);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<const A[2]> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   const A* p = new const A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<const volatile A[2], def_constr_deleter<const volatile A[2]> > s(p);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_pointer_convert{
+
+////////////////////////////////
+//   unique_ptr_ctor_pointer_deleter_movedel
+////////////////////////////////
+
+namespace unique_ptr_ctor_pointer_deleter_movedel{
+
+// test move ctor.  Should only require a MoveConstructible deleter, or if
+//    deleter is a reference, not even that.
+
+// unique_ptr(pointer, deleter()) only requires MoveConstructible deleter
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   A* p = new A;
+   BOOST_TEST(A::count == 1);
+   move_constr_deleter<A> d;
+   bml::unique_ptr<A, move_constr_deleter<A> > s(p, ::boost::move(d));
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   bml::unique_ptr<A, move_constr_deleter<A> > s2(s.release(), move_constr_deleter<A>(6));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s2.get_deleter().state() == 6);
+   }
+   BOOST_TEST(A::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   move_constr_deleter<A[]> d;
+   bml::unique_ptr<A[], move_constr_deleter<A[]> > s(p, ::boost::move(d));
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   bml::unique_ptr<A[], move_constr_deleter<A[]> > s2(s.release(), move_constr_deleter<A[]>(6));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s2.get_deleter().state() == 6);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   move_constr_deleter<A[2]> d;
+   bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s(p, ::boost::move(d));
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s2(s.release(), move_constr_deleter<A[2]>(6));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s2.get_deleter().state() == 6);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_pointer_deleter_movedel{
+
+////////////////////////////////
+//   unique_ptr_ctor_pointer_deleter_copydel
+////////////////////////////////
+
+namespace unique_ptr_ctor_pointer_deleter_copydel{
+
+// unique_ptr(pointer, d) requires CopyConstructible deleter
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   A* p = new A;
+   BOOST_TEST(A::count == 1);
+   copy_constr_deleter<A> d;
+   bml::unique_ptr<A, copy_constr_deleter<A> > s(p, d);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   d.set_state(6);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   copy_constr_deleter<A[]> d;
+   bml::unique_ptr<A[], copy_constr_deleter<A[]> > s(p, d);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   d.set_state(6);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   copy_constr_deleter<A[2]> d;
+   bml::unique_ptr<A[2], copy_constr_deleter<A[2]> > s(p, d);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   d.set_state(6);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_pointer_deleter_copydel{
+
+////////////////////////////////
+//   unique_ptr_ctor_pointer_deleter_dfctrdelref
+////////////////////////////////
+
+namespace unique_ptr_ctor_pointer_deleter_dfctrdelref{
+
+// unique_ptr<T, D&>(pointer, d) does not requires CopyConstructible deleter
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   A* p = new A;
+   BOOST_TEST(A::count == 1);
+   def_constr_deleter<A> d;
+   bml::unique_ptr<A, def_constr_deleter<A>&> s(p, d);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   d.set_state(6);
+   BOOST_TEST(s.get_deleter().state() == 6);
+   }
+   BOOST_TEST(A::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   def_constr_deleter<A[]> d;
+   bml::unique_ptr<A[], def_constr_deleter<A[]>&> s(p, d);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   d.set_state(6);
+   BOOST_TEST(s.get_deleter().state() == 6);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   def_constr_deleter<A[2]> d;
+   bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> s(p, d);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   d.set_state(6);
+   BOOST_TEST(s.get_deleter().state() == 6);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_pointer_deleter_dfctrdelref{
+
+////////////////////////////////
+//   unique_ptr_ctor_pointer_deleter_dfctrdelconstref
+////////////////////////////////
+
+namespace unique_ptr_ctor_pointer_deleter_dfctrdelconstref{
+
+// unique_ptr<T, const D&>(pointer, d) does not requires CopyConstructible deleter
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   A* p = new A;
+   BOOST_TEST(A::count == 1);
+   def_constr_deleter<A> d;
+   bml::unique_ptr<A, const def_constr_deleter<A>&> s(p, d);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   def_constr_deleter<A[]> d;
+   bml::unique_ptr<A[], const def_constr_deleter<A[]>&> s(p, d);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   def_constr_deleter<A[2]> d;
+   bml::unique_ptr<A[2], const def_constr_deleter<A[2]>&> s(p, d);
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_pointer_deleter_dfctrdelconstref{
+
+////////////////////////////////
+//   unique_ptr_ctor_pointer_deleter_convert
+////////////////////////////////
+
+namespace unique_ptr_ctor_pointer_deleter_convert{
+
+// unique_ptr(pointer, deleter) should work with derived pointers
+// or same (cv aside) types for array unique_ptrs
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   B* p = new B;
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   bml::unique_ptr<A, copy_constr_deleter<A> > s(p, copy_constr_deleter<A>());
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<const A[], copy_constr_deleter<const A[]> > s(p, copy_constr_deleter<const A[]>());
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   bml::unique_ptr<const A[2], copy_constr_deleter<const A[2]> > s(p, copy_constr_deleter<const A[2]>());
+   BOOST_TEST(s.get() == p);
+   BOOST_TEST(s.get_deleter().state() == 5);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_pointer_deleter_convert{
+
+////////////////////////////////
+//   unique_ptr_ctor_pointer_deleter_void
+////////////////////////////////
+
+namespace unique_ptr_ctor_pointer_deleter_void{
+
+// unique_ptr(pointer, deleter) should work with function pointers
+// unique_ptr<void> should work
+
+bool my_free_called = false;
+
+void my_free(void*)
+{
+    my_free_called = true;
+}
+
+void test()
+{
+   {
+   int i = 0;
+   bml::unique_ptr<void, void (*)(void*)> s(&i, my_free);
+   BOOST_TEST(s.get() == &i);
+   BOOST_TEST(s.get_deleter() == my_free);
+   BOOST_TEST(!my_free_called);
+   }
+   BOOST_TEST(my_free_called);
+}
+
+}  //namespace unique_ptr_ctor_pointer_deleter_void{
+
+////////////////////////////////
+//   return_unique_single_conversion
+////////////////////////////////
+
+namespace return_unique_single_conversion{
+
+template<class T>
+bml::unique_ptr<T> make_unique_ptr_of_t()
+{
+   return bml::unique_ptr<T>(new T);
+}
+
+template<class T>
+bml::unique_ptr<T const> return_const_unique_of_t()
+{
+   return bml::unique_ptr<T const> (make_unique_ptr_of_t<T>());
+} 
+
+void test()
+{
+   reset_counters();
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<const A> p(return_const_unique_of_t<A>());
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<const A> p(return_const_unique_of_t<B>());
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace return_unique_single_conversion{
+
+
+////////////////////////////////
+//   return_unique_array_conversion
+////////////////////////////////
+
+namespace return_unique_array_conversion{
+
+template<class T>
+bml::unique_ptr<T[]> return_unique_array_of_t(std::size_t n)
+{
+   return bml::unique_ptr<T[]>(new T[n]);
+}
+
+template<class T>
+bml::unique_ptr<const T[]> return_const_array_of_t(std::size_t n)
+{
+   return bml::unique_ptr<const T[]>(return_unique_array_of_t<T>(n));
+} 
+
+template<class T>
+bml::unique_ptr<T[2]> return_unique_array_of_t_2()
+{
+   return bml::unique_ptr<T[2]>(new T[2]);
+}
+
+template<class T>
+bml::unique_ptr<const T[2]> return_const_array_of_t_2()
+{
+   return bml::unique_ptr<const T[2]>(return_unique_array_of_t_2<T>());
+} 
+
+void test()
+{
+   reset_counters();
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<const A[]> p(return_unique_array_of_t<A>(2));
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(B::count == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<const volatile A[]> p(return_unique_array_of_t<volatile A>(2));
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(B::count == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<const volatile A[2]> p(return_const_array_of_t_2<A>());
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(B::count == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<const volatile A[]> p(return_const_array_of_t_2<A>());
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(B::count == 0);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace return_unique_array_conversion{
+
+////////////////////////////////
+//             main
+////////////////////////////////
+int main()
+{
+   //Constructors/Destructor
+   unique_ptr_dtor_null::test();
+   unique_ptr_ctor_default_delreq::test();
+   unique_ptr_ctor_default_nocomplete::test();
+   unique_ptr_ctor_pointer_delreq::test();
+   unique_ptr_ctor_pointer_nocomplete::test();
+   unique_ptr_ctor_pointer_convert::test();
+   unique_ptr_ctor_pointer_deleter_movedel::test();
+   unique_ptr_ctor_pointer_deleter_copydel::test();
+   unique_ptr_ctor_pointer_deleter_dfctrdelref::test();
+   unique_ptr_ctor_pointer_deleter_dfctrdelconstref::test();
+   unique_ptr_ctor_pointer_deleter_convert::test();
+   unique_ptr_ctor_pointer_deleter_void::test();
+   return_unique_single_conversion::test();
+   return_unique_array_conversion::test();
+
+   //Test results
+   return boost::report_errors();
+
+}
+
+#include "unique_ptr_test_utils_end.hpp"
diff --git a/test/unique_ptr_default_deleter.cpp b/test/unique_ptr_default_deleter.cpp
new file mode 100644
index 0000000..1bf16ea
--- /dev/null
+++ b/test/unique_ptr_default_deleter.cpp
@@ -0,0 +1,204 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/default_delete.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+//////////////////////////////////////////////
+//
+// The initial implementation of these tests
+// was written by Howard Hinnant. 
+//
+// These test were later refactored grouping
+// and porting them to Boost.Move.
+//
+// Many thanks to Howard for releasing his C++03
+// unique_ptr implementation with such detailed
+// test cases.
+//
+//////////////////////////////////////////////
+
+////////////////////////////////
+//   unique_ptr_dltr_dflt_convert_ctor
+////////////////////////////////
+
+namespace bml = ::boost::movelib;
+
+struct A
+{
+   static int count;
+   A() {++count;}
+   A(const A&) {++count;}
+   virtual ~A() {--count;}
+};
+
+int A::count = 0;
+
+struct B
+   : public A
+{
+   static int count;
+   B() : A() {++count;}
+   B(const B&) : A() {++count;}
+   virtual ~B() {--count;}
+};
+
+int B::count = 0;
+
+void reset_counters()
+{  A::count = B::count = 0;  }
+
+namespace unique_ptr_dltr_dflt_convert_ctor{
+
+void test()
+{
+   //Single element deleter
+   {
+   reset_counters();
+   bml::default_delete<B> d2;
+   bml::default_delete<A> d1 = d2;
+   A* p = new B;
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   d1(p);
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   }
+   //Array element deleter
+   {
+   reset_counters();
+   bml::default_delete<A[]> d2;
+   bml::default_delete<const A[]> d1 = d2;
+   const A* p = new const A[2];
+   BOOST_TEST(A::count == 2);
+   d1(p);
+   BOOST_TEST(A::count == 0);
+   }
+   //Bounded array element deleter
+   {
+   reset_counters();
+   bml::default_delete<A[2]> d2;
+   bml::default_delete<const A[2]> d1 = d2;
+   const A* p = new const A[2];
+   BOOST_TEST(A::count == 2);
+   d1(p);
+   bml::default_delete<const A[]> d0 = d1;
+   d0(0);
+   BOOST_TEST(A::count == 0);
+   }
+}
+
+}  //namespace unique_ptr_dltr_dflt_convert_ctor{
+
+////////////////////////////////
+//   unique_ptr_dltr_dflt_convert_assign
+////////////////////////////////
+
+namespace unique_ptr_dltr_dflt_convert_assign{
+
+void test()
+{
+   //Single element deleter
+   {
+   reset_counters();
+   bml::default_delete<B> d2;
+   bml::default_delete<A> d1;
+   d1 = d2;
+   A* p = new B;
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   d1(p);
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   }
+   //Array element deleter
+   {
+   reset_counters();
+   bml::default_delete<A[]> d2;
+   bml::default_delete<const A[]> d1;
+   d1 = d2;
+   const A* p = new const A[2];
+   BOOST_TEST(A::count == 2);
+   d1(p);
+   BOOST_TEST(A::count == 0);
+   }
+   //Bounded array element deleter
+   {
+   reset_counters();
+   bml::default_delete<A[2]> d2;
+   bml::default_delete<const A[2]> d1;
+   d1 = d2;
+   const A* p = new const A[2];
+   BOOST_TEST(A::count == 2);
+   d1(p);
+   bml::default_delete<const A[]> d0;
+   d0 = d1;
+   d0(0);
+   BOOST_TEST(A::count == 0);
+   }
+}
+
+}  //namespace unique_ptr_dltr_dflt_convert_assign{
+
+
+////////////////////////////////
+//   unique_ptr_dltr_dflt_default
+////////////////////////////////
+
+namespace unique_ptr_dltr_dflt_default{
+
+void test()
+{
+   {
+   //Single element deleter
+   reset_counters();
+   bml::default_delete<A> d;
+   A* p = new A;
+   BOOST_TEST(A::count == 1);
+   d(p);
+   BOOST_TEST(A::count == 0);
+   }
+   {
+   //Array element deleter
+   reset_counters();
+   bml::default_delete<A[]> d;
+   A* p = new A[2];
+   BOOST_TEST(A::count == 2);
+   d(p);
+   BOOST_TEST(A::count == 0);
+   }
+
+   {
+   //Bounded Array element deleter
+   reset_counters();
+   bml::default_delete<A[10]> d;
+   A* p = new A[10];
+   BOOST_TEST(A::count == 10);
+   d(p);
+   BOOST_TEST(A::count == 0);
+   }
+}
+
+}  //namespace unique_ptr_dltr_dflt_default{
+
+////////////////////////////////
+//             main
+////////////////////////////////
+int main()
+{
+   unique_ptr_dltr_dflt_convert_ctor::test();
+   unique_ptr_dltr_dflt_convert_assign::test();
+   unique_ptr_dltr_dflt_default::test();
+
+   //Test results
+   return boost::report_errors();
+}
diff --git a/test/unique_ptr_functions.cpp b/test/unique_ptr_functions.cpp
new file mode 100644
index 0000000..d3b4d6d
--- /dev/null
+++ b/test/unique_ptr_functions.cpp
@@ -0,0 +1,395 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/make_unique.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <cstring>
+
+struct A
+{
+   int a, b, c;
+   static int count;
+   A() : a (999), b(1000), c(1001) {++count;}
+   A(int a) : a (a), b(1000), c(1001) {++count;}
+   A(int a, int b) : a (a), b(b), c(1001) {++count;}
+   A(int a, int b, int c) : a (a), b(b), c(c) {++count;}
+   A(const A&) {++count;}
+   virtual ~A() {--count;}
+};
+
+int A::count = 0;
+
+struct B
+   : public A
+{
+   static int count;
+   B() : A() {++count;}
+   B(const B&) : A() {++count;}
+   virtual ~B() {--count;}
+};
+
+int B::count = 0;
+
+void reset_counters()
+{  A::count = B::count = 0;  }
+
+static const unsigned PatternSize = 8;
+static const unsigned char ff_patternbuf[PatternSize] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+static const unsigned char ee_patternbuf[PatternSize] = { 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE };
+static const unsigned char dd_patternbuf[PatternSize] = { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD };
+static const unsigned char cc_patternbuf[PatternSize] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC };
+
+void volatile_memset(volatile void *p, int ch, std::size_t len)
+{
+   volatile unsigned char *puch = static_cast<volatile unsigned char *>(p);
+   for(std::size_t i = 0; i != len; ++i){
+      *puch = (unsigned char)ch;
+      ++puch;
+   }
+}
+
+int volatile_memcmp(const volatile void *p1, const volatile void *p2, std::size_t len)
+{
+   const volatile unsigned char *s1 = static_cast<const volatile unsigned char *>(p1);
+   const volatile unsigned char *s2 = static_cast<const volatile unsigned char *>(p2);
+   unsigned char u1, u2;
+
+   for ( ; len-- ; s1++, s2++) {
+      u1 = *s1;
+      u2 = *s2;
+      if (u1 != u2) {
+         return (u1-u2);
+      }
+   }
+   return 0;
+}
+
+void volatile_memcmp(volatile void *p, int ch, std::size_t len)
+{
+   volatile unsigned char *puch = static_cast<volatile unsigned char *>(p);
+   for(std::size_t i = 0; i != len; ++i){
+      *puch = (unsigned char)ch;
+      ++puch;
+   }
+}
+
+#include <iostream>
+
+struct default_init
+{
+   static void* operator new(std::size_t sz)
+   {
+      void *const p = ::operator new(sz);
+      //Make sure they are not optimized out
+      volatile_memset(p, 0xFF, sz);
+      std::cout << "0xFF" << '\n';
+      return p;
+   }
+   static void* operator new[](std::size_t sz)
+   {
+      void *const p = ::operator new[](sz);
+      //Make sure they are not optimized out
+      volatile_memset(p, 0xEE, sz);
+      std::cout << "0xEE" << '\n';
+      return p;
+   }
+   static void* operator new(std::size_t sz, const std::nothrow_t &)
+   {
+      void *const p = ::operator new(sz);
+      //Make sure they are not optimized out
+      volatile_memset(p, 0xDD, sz);
+      std::cout << "0xDD" << '\n';
+      return p;
+   }
+   static void* operator new[](std::size_t sz, const std::nothrow_t &)
+   {
+      void *const p = ::operator new[](sz);
+      //Make sure they are not optimized out
+      volatile_memset(p, 0xCC, sz);
+      std::cout << "0xCC" << '\n';
+      return p;
+   }
+   unsigned char buf[PatternSize];
+};
+
+namespace bml = ::boost::movelib;
+
+////////////////////////////////
+//   make_unique_single
+////////////////////////////////
+
+namespace make_unique_single{
+
+void test()
+{
+   //Single element deleter
+   reset_counters();
+   {
+   bml::unique_ptr<default_init> p(bml::make_unique_definit<default_init>());
+   BOOST_TEST(0 == volatile_memcmp(p.get(), ff_patternbuf, sizeof(ff_patternbuf)));
+   }
+   {
+   bml::unique_ptr<default_init> p(bml::make_unique_nothrow_definit<default_init>());
+   
+   BOOST_TEST(0 == volatile_memcmp(p.get(), dd_patternbuf, sizeof(dd_patternbuf)));
+   }
+
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<A> p(bml::make_unique<A>());
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(p->a == 999);
+   BOOST_TEST(p->b == 1000);
+   BOOST_TEST(p->c == 1001);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<A> p(bml::make_unique_nothrow<A>(0));
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(p->a == 0);
+   BOOST_TEST(p->b == 1000);
+   BOOST_TEST(p->c == 1001);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<A> p(bml::make_unique<A>(0, 1));
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(p->a == 0);
+   BOOST_TEST(p->b == 1);
+   BOOST_TEST(p->c == 1001);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<A> p(bml::make_unique_nothrow<A>(0, 1, 2));
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(p->a == 0);
+   BOOST_TEST(p->b == 1);
+   BOOST_TEST(p->c == 2);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace make_unique_single{
+
+
+////////////////////////////////
+//    make_unique_array
+////////////////////////////////
+
+namespace make_unique_array{
+
+void test()
+{
+   //Array element
+   reset_counters();
+   {
+      bml::unique_ptr<A[]> p(bml::make_unique<A[]>(10));
+      BOOST_TEST(A::count == 10);
+      for(int i = 0; i != 10; ++i){
+         BOOST_TEST(p[i].a == 999);
+         BOOST_TEST(p[i].b == 1000);
+         BOOST_TEST(p[i].c == 1001);
+      }
+   }
+   BOOST_TEST(A::count == 0);
+   {
+      bml::unique_ptr<A[]> p(bml::make_unique_nothrow<A[]>(10));
+      BOOST_TEST(A::count == 10);
+      for(int i = 0; i != 10; ++i){
+         BOOST_TEST(p[i].a == 999);
+         BOOST_TEST(p[i].b == 1000);
+         BOOST_TEST(p[i].c == 1001);
+      }
+   }
+   BOOST_TEST(A::count == 0);
+   reset_counters();
+   {
+      bml::unique_ptr<default_init[]> p(bml::make_unique_definit<default_init[]>(10));
+      for(unsigned i = 0; i != 10; ++i){
+         BOOST_TEST(0 == volatile_memcmp(&p[i], ee_patternbuf, sizeof(ee_patternbuf)));
+      }
+   }
+   reset_counters();
+   {
+      bml::unique_ptr<default_init[]> p(bml::make_unique_nothrow_definit<default_init[]>(10));
+      for(unsigned i = 0; i != 10; ++i){
+         BOOST_TEST(0 == volatile_memcmp(&p[i], cc_patternbuf, sizeof(cc_patternbuf)));
+      }
+   }
+}
+
+}  //namespace make_unique_array{
+
+////////////////////////////////
+//       unique_compare
+////////////////////////////////
+
+namespace unique_compare{
+
+void test()
+{
+   //Single element deleter
+   reset_counters();
+   {
+      bml::unique_ptr<A> pa(bml::make_unique<A>());
+      bml::unique_ptr<A> pb(bml::make_unique<A>());
+      BOOST_TEST(A::count == 2);
+
+      //Take references to less and greater
+      bml::unique_ptr<A> &rpl = pa < pb ? pa : pb;
+      bml::unique_ptr<A> &rpg = pa < pb ? pb : pa;
+
+      //Now test operations with .get()
+
+      //Equal
+      BOOST_TEST(rpl == rpl && rpl.get() == rpl.get());
+      BOOST_TEST(!(rpl == rpg) && !(rpl.get() == rpg.get()));
+      //Unequal
+      BOOST_TEST(rpl != rpg && rpl.get() != rpg.get());
+      BOOST_TEST(!(rpl != rpl) && !(rpl.get() != rpl.get()));
+      //Less
+      BOOST_TEST(rpl < rpg && rpl.get() < rpg.get());
+      BOOST_TEST(!(rpg < rpl) && !(rpg.get() < rpl.get()));
+      //Greater
+      BOOST_TEST(rpg > rpl && rpg.get() > rpl.get());
+      BOOST_TEST(!(rpg > rpg) && !(rpg.get() > rpg.get()));
+      //Less or equal
+      BOOST_TEST(rpl <= rpg && rpl.get() <= rpg.get());
+      BOOST_TEST(rpl <= rpl && rpl.get() <= rpl.get());
+      BOOST_TEST(!(rpg <= rpl) && !(rpg.get() <= rpl.get()));
+      //Greater or equal
+      BOOST_TEST(rpg >= rpl && rpg.get() >= rpl.get());
+      BOOST_TEST(rpg >= rpg && rpg.get() >= rpg.get());
+      BOOST_TEST(!(rpl >= rpg) && !(rpl.get() >= rpg.get()));
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_compare{
+
+////////////////////////////////
+//       unique_compare_zero
+////////////////////////////////
+namespace unique_compare_zero{
+
+void test()
+{
+   //Single element deleter
+   reset_counters();
+   {
+      bml::unique_ptr<A> pa(bml::make_unique<A>());
+      bml::unique_ptr<A> pb;
+      BOOST_TEST(A::count == 1);
+
+      //Equal
+      BOOST_TEST(!(pa == 0));
+      BOOST_TEST(!(0  == pa));
+      BOOST_TEST((pb == 0));
+      BOOST_TEST((0  == pb));
+      //Unequal
+      BOOST_TEST((pa != 0));
+      BOOST_TEST((0  != pa));
+      BOOST_TEST(!(pb != 0));
+      BOOST_TEST(!(0  != pb));
+      //Less
+      BOOST_TEST((pa < 0) == (pa.get() < (A*)0));
+      BOOST_TEST((0 < pa) == ((A*)0 < pa.get()));
+      BOOST_TEST((pb < 0) == (pb.get() < (A*)0));
+      BOOST_TEST((0 < pb) == ((A*)0 < pb.get()));
+      //Greater
+      BOOST_TEST((pa > 0) == (pa.get() > (A*)0));
+      BOOST_TEST((0 > pa) == ((A*)0 > pa.get()));
+      BOOST_TEST((pb > 0) == (pb.get() > (A*)0));
+      BOOST_TEST((0 > pb) == ((A*)0 > pb.get()));
+      //Less or equal
+      BOOST_TEST((pa <= 0) == (pa.get() <= (A*)0));
+      BOOST_TEST((0 <= pa) == ((A*)0 <= pa.get()));
+      BOOST_TEST((pb <= 0) == (pb.get() <= (A*)0));
+      BOOST_TEST((0 <= pb) == ((A*)0 <= pb.get()));
+      //Greater or equal
+      BOOST_TEST((pa >= 0) == (pa.get() >= (A*)0));
+      BOOST_TEST((0 >= pa) == ((A*)0 >= pa.get()));
+      BOOST_TEST((pb >= 0) == (pb.get() >= (A*)0));
+      BOOST_TEST((0 >= pb) == ((A*)0 >= pb.get()));
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_compare_zero{
+
+////////////////////////////////
+//       unique_compare_nullptr
+////////////////////////////////
+
+namespace unique_compare_nullptr{
+
+void test()
+{
+   #if !defined(BOOST_NO_CXX11_NULLPTR)
+   //Single element deleter
+   reset_counters();
+   {
+      bml::unique_ptr<A> pa(bml::make_unique<A>());
+      bml::unique_ptr<A> pb;
+      BOOST_TEST(A::count == 1);
+
+      //Equal
+      BOOST_TEST(!(pa == nullptr));
+      BOOST_TEST(!(nullptr  == pa));
+      BOOST_TEST((pb == nullptr));
+      BOOST_TEST((nullptr  == pb));
+      //Unequal
+      BOOST_TEST((pa != nullptr));
+      BOOST_TEST((nullptr  != pa));
+      BOOST_TEST(!(pb != nullptr));
+      BOOST_TEST(!(nullptr  != pb));
+      //Less
+      BOOST_TEST((pa < nullptr) == (pa.get() < (A*)nullptr));
+      BOOST_TEST((nullptr < pa) == ((A*)nullptr < pa.get()));
+      BOOST_TEST((pb < nullptr) == (pb.get() < (A*)nullptr));
+      BOOST_TEST((nullptr < pb) == ((A*)nullptr < pb.get()));
+      //Greater
+      BOOST_TEST((pa > nullptr) == (pa.get() > (A*)nullptr));
+      BOOST_TEST((nullptr > pa) == ((A*)nullptr > pa.get()));
+      BOOST_TEST((pb > nullptr) == (pb.get() > (A*)nullptr));
+      BOOST_TEST((nullptr > pb) == ((A*)nullptr > pb.get()));
+      //Less or equal
+      BOOST_TEST((pa <= nullptr) == (pa.get() <= (A*)nullptr));
+      BOOST_TEST((nullptr <= pa) == ((A*)nullptr <= pa.get()));
+      BOOST_TEST((pb <= nullptr) == (pb.get() <= (A*)nullptr));
+      BOOST_TEST((nullptr <= pb) == ((A*)nullptr <= pb.get()));
+      //Greater or equal
+      BOOST_TEST((pa >= nullptr) == (pa.get() >= (A*)nullptr));
+      BOOST_TEST((nullptr >= pa) == ((A*)nullptr >= pa.get()));
+      BOOST_TEST((pb >= nullptr) == (pb.get() >= (A*)nullptr));
+      BOOST_TEST((nullptr >= pb) == ((A*)nullptr >= pb.get()));
+   }
+   BOOST_TEST(A::count == 0);
+   #endif   //#if !defined(BOOST_NO_CXX11_NULLPTR)
+}
+
+}  //namespace unique_compare_nullptr{
+
+
+////////////////////////////////
+//             main
+////////////////////////////////
+int main()
+{
+   make_unique_single::test();
+   make_unique_array::test();
+   unique_compare::test();
+   unique_compare_zero::test();
+   unique_compare_nullptr::test();
+
+   //Test results
+   return boost::report_errors();
+}
diff --git a/test/unique_ptr_modifiers.cpp b/test/unique_ptr_modifiers.cpp
new file mode 100644
index 0000000..376c104
--- /dev/null
+++ b/test/unique_ptr_modifiers.cpp
@@ -0,0 +1,381 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/utility_core.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+//////////////////////////////////////////////
+//
+// The initial implementation of these tests
+// was written by Howard Hinnant. 
+//
+// These test were later refactored grouping
+// and porting them to Boost.Move.
+//
+// Many thanks to Howard for releasing his C++03
+// unique_ptr implementation with such detailed
+// test cases.
+//
+//////////////////////////////////////////////
+
+#include "unique_ptr_test_utils_beg.hpp"
+
+namespace bml = ::boost::movelib;
+
+////////////////////////////////
+//   unique_ptr_modifiers_release
+////////////////////////////////
+
+namespace unique_ptr_modifiers_release{
+
+void test()
+{
+   //Single unique_ptr
+   {
+   bml::unique_ptr<int> p(new int(3));
+   int* i = p.get();
+   int* j = p.release();
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(i == j);
+   p.reset(j);
+   }
+   //Unbounded array unique_ptr
+   {
+   bml::unique_ptr<int[]> p(new int[2]);
+   int* i = p.get();
+   int* j = p.release();
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(i == j);
+   p.reset(j);
+   }
+   //Bounded array unique_ptr
+   {
+   bml::unique_ptr<int[2]> p(new int[2]);
+   int* i = p.get();
+   int* j = p.release();
+   BOOST_TEST(p.get() == 0);
+   BOOST_TEST(i == j);
+   p.reset(j);
+   }
+}
+
+}  //namespace unique_ptr_modifiers_release{
+
+////////////////////////////////
+//   unique_ptr_modifiers_reset
+////////////////////////////////
+
+namespace unique_ptr_modifiers_reset{
+
+void test()
+{
+   //Single unique_ptr
+   {
+      reset_counters();
+      {  //reset()
+      bml::unique_ptr<A> p(new A);
+      BOOST_TEST(A::count == 1);
+      A* i = p.get();
+      (void)i;
+      p.reset();
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+      }
+      BOOST_TEST(A::count == 0);
+      {  //reset(p)
+      bml::unique_ptr<A> p(new A);
+      BOOST_TEST(A::count == 1);
+      A* i = p.get();
+      (void)i;
+      p.reset(new A);
+      BOOST_TEST(A::count == 1);
+      }
+      BOOST_TEST(A::count == 0);
+      {  //reset(0)
+      bml::unique_ptr<A> p(new A);
+      BOOST_TEST(A::count == 1);
+      A* i = p.get();
+      (void)i;
+      p.reset(0);
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+      }
+      BOOST_TEST(A::count == 0);
+   }
+   //Unbounded array unique_ptr
+   {
+      reset_counters();
+      {  //reset()
+      bml::unique_ptr<A[]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p.reset();
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+      }
+      BOOST_TEST(A::count == 0);
+      {  //reset(p)
+      bml::unique_ptr<A[]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p.reset(new A[3]);
+      BOOST_TEST(A::count == 3);
+      }
+      BOOST_TEST(A::count == 0);
+      {  //reset(0)
+      bml::unique_ptr<A[]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p.reset(0);
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+      }
+      BOOST_TEST(A::count == 0);
+   }
+   {
+      //Bounded array unique_ptr
+      reset_counters();
+      {  //reset()
+      bml::unique_ptr<A[2]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p.reset();
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+      }
+      BOOST_TEST(A::count == 0);
+      {  //reset(p)
+      bml::unique_ptr<A[2]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p.reset(new A[3]);
+      BOOST_TEST(A::count == 3);
+      }
+      BOOST_TEST(A::count == 0);
+      {  //reset(0)
+      bml::unique_ptr<A[2]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p.reset(0);
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+      }
+      BOOST_TEST(A::count == 0);
+   }
+}
+
+}  //namespace unique_ptr_modifiers_reset{
+
+////////////////////////////////
+//   unique_ptr_modifiers_reset_convert
+////////////////////////////////
+
+namespace unique_ptr_modifiers_reset_convert{
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A> p(new A);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 0);
+   A* i = p.get();
+   (void)i;
+   p.reset(new B);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   {
+   bml::unique_ptr<A> p(new B);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   A* i = p.get();
+   (void)i;
+   p.reset(new B);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<const volatile A[2]> p(new const A[2]);
+   BOOST_TEST(A::count == 2);
+   const volatile A* i = p.get();
+   (void)i;
+   p.reset(new volatile A[3]);
+   BOOST_TEST(A::count == 3);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<const A[2]> p(new A[2]);
+   BOOST_TEST(A::count == 2);
+   const A* i = p.get();
+   (void)i;
+   p.reset(new const A[3]);
+   BOOST_TEST(A::count == 3);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<const volatile A[2]> p(new const A[2]);
+   BOOST_TEST(A::count == 2);
+   const volatile A* i = p.get();
+   (void)i;
+   p.reset(new volatile A[3]);
+   BOOST_TEST(A::count == 3);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<const A[2]> p(new A[2]);
+   BOOST_TEST(A::count == 2);
+   const A* i = p.get();
+   (void)i;
+   p.reset(new const A[3]);
+   BOOST_TEST(A::count == 3);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //unique_ptr_modifiers_reset_convert
+
+
+////////////////////////////////
+//   unique_ptr_modifiers
+////////////////////////////////
+
+namespace unique_ptr_modifiers_swap{
+
+// test swap
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   A* p1 = new A(1);
+   move_constr_deleter<A> d1(1);
+   bml::unique_ptr<A, move_constr_deleter<A> > s1(p1, ::boost::move(d1));
+   A* p2 = new A(2);
+   move_constr_deleter<A> d2(2);
+   bml::unique_ptr<A, move_constr_deleter<A> > s2(p2, ::boost::move(d2));
+   BOOST_TEST(s1.get() == p1);
+   BOOST_TEST(*s1 == A(1));
+   BOOST_TEST(s1.get_deleter().state() == 1);
+   BOOST_TEST(s2.get() == p2);
+   BOOST_TEST(*s2 == A(2));
+   BOOST_TEST(s2.get_deleter().state() == 2);
+   boost::adl_move_swap(s1, s2);
+   BOOST_TEST(s1.get() == p2);
+   BOOST_TEST(*s1 == A(2));
+   BOOST_TEST(s1.get_deleter().state() == 2);
+   BOOST_TEST(s2.get() == p1);
+   BOOST_TEST(*s2 == A(1));
+   BOOST_TEST(s2.get_deleter().state() == 1);
+   }
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   A* p1 = new A[2];
+   p1[0].set(1);
+   p1[1].set(2);
+   move_constr_deleter<A[]> d1(1);
+   bml::unique_ptr<A[], move_constr_deleter<A[]> > s1(p1, ::boost::move(d1));
+   A* p2 = new A[2];
+   p2[0].set(3);
+   p2[1].set(4);
+   move_constr_deleter<A[]> d2(2);
+   bml::unique_ptr<A[], move_constr_deleter<A[]> > s2(p2, ::boost::move(d2));
+   BOOST_TEST(s1.get() == p1);
+   BOOST_TEST(s1[0] == A(1));
+   BOOST_TEST(s1[1] == A(2));
+   BOOST_TEST(s1.get_deleter().state() == 1);
+   BOOST_TEST(s2.get() == p2);
+   BOOST_TEST(s2[0] == A(3));
+   BOOST_TEST(s2[1] == A(4));
+   BOOST_TEST(s2.get_deleter().state() == 2);
+   swap(s1, s2);
+   BOOST_TEST(s1.get() == p2);
+   BOOST_TEST(s1[0] == A(3));
+   BOOST_TEST(s1[1] == A(4));
+   BOOST_TEST(s1.get_deleter().state() == 2);
+   BOOST_TEST(s2.get() == p1);
+   BOOST_TEST(s2[0] == A(1));
+   BOOST_TEST(s2[1] == A(2));
+   BOOST_TEST(s2.get_deleter().state() == 1);
+   }
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   A* p1 = new A[2];
+   p1[0].set(1);
+   p1[1].set(2);
+   move_constr_deleter<A[2]> d1(1);
+   bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s1(p1, ::boost::move(d1));
+   A* p2 = new A[2];
+   p2[0].set(3);
+   p2[1].set(4);
+   move_constr_deleter<A[2]> d2(2);
+   bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s2(p2, ::boost::move(d2));
+   BOOST_TEST(s1.get() == p1);
+   BOOST_TEST(s1[0] == A(1));
+   BOOST_TEST(s1[1] == A(2));
+   BOOST_TEST(s1.get_deleter().state() == 1);
+   BOOST_TEST(s2.get() == p2);
+   BOOST_TEST(s2[0] == A(3));
+   BOOST_TEST(s2[1] == A(4));
+   BOOST_TEST(s2.get_deleter().state() == 2);
+   swap(s1, s2);
+   BOOST_TEST(s1.get() == p2);
+   BOOST_TEST(s1[0] == A(3));
+   BOOST_TEST(s1[1] == A(4));
+   BOOST_TEST(s1.get_deleter().state() == 2);
+   BOOST_TEST(s2.get() == p1);
+   BOOST_TEST(s2[0] == A(1));
+   BOOST_TEST(s2[1] == A(2));
+   BOOST_TEST(s2.get_deleter().state() == 1);
+   }
+}
+
+}  //namespace unique_ptr_modifiers_swap{
+
+////////////////////////////////
+//             main
+////////////////////////////////
+int main()
+{
+   //Modifiers
+   unique_ptr_modifiers_release::test();
+   unique_ptr_modifiers_reset::test();
+   unique_ptr_modifiers_reset_convert::test();
+   unique_ptr_modifiers_swap::test();
+
+   //Test results
+   return boost::report_errors();
+
+}
+
+#include "unique_ptr_test_utils_end.hpp"
diff --git a/test/unique_ptr_movector.cpp b/test/unique_ptr_movector.cpp
new file mode 100644
index 0000000..ece216b
--- /dev/null
+++ b/test/unique_ptr_movector.cpp
@@ -0,0 +1,517 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/utility_core.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+//////////////////////////////////////////////
+//
+// The initial implementation of these tests
+// was written by Howard Hinnant. 
+//
+// These test were later refactored grouping
+// and porting them to Boost.Move.
+//
+// Many thanks to Howard for releasing his C++03
+// unique_ptr implementation with such detailed
+// test cases.
+//
+//////////////////////////////////////////////
+
+#include "unique_ptr_test_utils_beg.hpp"
+
+namespace bml = ::boost::movelib;
+namespace bmupmu = ::boost::move_upmu;
+
+////////////////////////////////
+//   unique_ptr_ctor_move_defdel
+////////////////////////////////
+
+namespace unique_ptr_ctor_move_defdel{
+
+// test converting move ctor.  Should only require a MoveConstructible deleter, or if
+//    deleter is a reference, not even that.
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A> s(new A);
+   A* p = s.get();
+   bml::unique_ptr<A> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 1);
+   }
+   BOOST_TEST(A::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[]> s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<A[]> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[2]> s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<A[2]> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_move_defdel{
+
+////////////////////////////////
+//   unique_ptr_ctor_move_movedel
+////////////////////////////////
+
+namespace unique_ptr_ctor_move_movedel{
+
+// test converting move ctor.  Should only require a MoveConstructible deleter, or if
+//    deleter is a reference, not even that.
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A, move_constr_deleter<A> > s(new A);
+   A* p = s.get();
+   bml::unique_ptr<A, move_constr_deleter<A> > s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[], move_constr_deleter<A[]> > s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<A[], move_constr_deleter<A[]> > s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[2]> s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<A[2]> s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_move_movedel{
+
+////////////////////////////////
+//   unique_ptr_ctor_move_dfctrdelref
+////////////////////////////////
+
+namespace unique_ptr_ctor_move_dfctrdelref{
+
+// test converting move ctor.  Should only require a MoveConstructible deleter, or if
+//    deleter is a reference, not even that.
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   def_constr_deleter<A> d;
+   bml::unique_ptr<A, def_constr_deleter<A>&> s(new A, d);
+   A* p = s.get();
+   bml::unique_ptr<A, def_constr_deleter<A>&> s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 1);
+   d.set_state(6);
+   BOOST_TEST(s2.get_deleter().state() == d.state());
+   BOOST_TEST(s.get_deleter().state() ==  d.state());
+   }
+   BOOST_TEST(A::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   def_constr_deleter<A[]> d;
+   bml::unique_ptr<A[], def_constr_deleter<A[]>&> s(new A[2], d);
+   A* p = s.get();
+   bml::unique_ptr<A[], def_constr_deleter<A[]>&> s2 = boost::move(s);
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   d.set_state(6);
+   BOOST_TEST(s2.get_deleter().state() == d.state());
+   BOOST_TEST(s.get_deleter().state() ==  d.state());
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   def_constr_deleter<A[2]> d;
+   bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> s(new A[2], d);
+   A* p = s.get();
+   bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   d.set_state(6);
+   BOOST_TEST(s2.get_deleter().state() == d.state());
+   BOOST_TEST(s.get_deleter().state() ==  d.state());
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_move_dfctrdelref{
+
+////////////////////////////////
+//   unique_ptr_ctor_move_convert_defdel
+////////////////////////////////
+
+namespace unique_ptr_ctor_move_convert_defdel{
+
+// test converting move ctor.  Should only require a MoveConstructible deleter, or if
+//    deleter is a reference, not even that.
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<B> s(new B);
+   A* p = s.get();
+   bml::unique_ptr<A> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[]> s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<const volatile A[]> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A[2]> s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<const volatile A[2]> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<A[2]> s(new A[2]);
+   A* p = s.get();
+   bml::unique_ptr<const volatile A[]> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_move_convert_defdel{
+
+////////////////////////////////
+//   unique_ptr_ctor_move_convert_movedel
+////////////////////////////////
+
+namespace unique_ptr_ctor_move_convert_movedel{
+
+// test converting move ctor.  Should only require a MoveConstructible deleter, or if
+//    deleter is a reference, not even that.
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   BOOST_STATIC_ASSERT((bmupmu::is_convertible<B, A>::value));
+   {
+   bml::unique_ptr<B, move_constr_deleter<B> > s(new B);
+   A* p = s.get();
+   bml::unique_ptr<A, move_constr_deleter<A> > s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<const A[], move_constr_deleter<const A[]> > s(new const A[2]);
+   const A* p = s.get();
+   bml::unique_ptr<const volatile A[], move_constr_deleter<const volatile A[]> > s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<const A[2], move_constr_deleter<const A[2]> > s(new const A[2]);
+   const A* p = s.get();
+   bml::unique_ptr<const volatile A[2], move_constr_deleter<const volatile A[2]> > s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   {
+   bml::unique_ptr<const A[2], move_constr_deleter<const A[2]> > s(new const A[2]);
+   const A* p = s.get();
+   bml::unique_ptr<const volatile A[], move_constr_deleter<const volatile A[]> > s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   BOOST_TEST(s2.get_deleter().state() == 5);
+   BOOST_TEST(s.get_deleter().state() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_move_convert_movedel{
+
+////////////////////////////////
+//   unique_ptr_ctor_move_convert_dfctrdelref
+////////////////////////////////
+
+namespace unique_ptr_ctor_move_convert_dfctrdelref{
+
+// test converting move ctor.  Should only require a MoveConstructible deleter, or if
+//    deleter is a reference, not even that.
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   def_constr_deleter<A> d;
+   bml::unique_ptr<B, def_constr_deleter<A>&> s(new B, d);
+   A* p = s.get();
+   bml::unique_ptr<A, def_constr_deleter<A>&> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 1);
+   BOOST_TEST(B::count == 1);
+   d.set_state(6);
+   BOOST_TEST(s2.get_deleter().state() == d.state());
+   BOOST_TEST(s.get_deleter().state() ==  d.state());
+   }
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(B::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+   def_constr_deleter<volatile A[]> d;
+   bml::unique_ptr<A[], def_constr_deleter<volatile A[]>&> s(new A[2], d);
+   A* p = s.get();
+   bml::unique_ptr<volatile A[], def_constr_deleter<volatile A[]>&> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   d.set_state(6);
+   BOOST_TEST(s2.get_deleter().state() == d.state());
+   BOOST_TEST(s.get_deleter().state() ==  d.state());
+   }
+   BOOST_TEST(A::count == 0);
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+   def_constr_deleter<volatile A[2]> d;
+   bml::unique_ptr<A[2], def_constr_deleter<volatile A[2]>&> s(new A[2], d);
+   A* p = s.get();
+   bml::unique_ptr<volatile A[2], def_constr_deleter<volatile A[2]>&> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   d.set_state(6);
+   BOOST_TEST(s2.get_deleter().state() == d.state());
+   BOOST_TEST(s.get_deleter().state() ==  d.state());
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   def_constr_deleter<volatile A[]> d;
+   bml::unique_ptr<A[2], def_constr_deleter<volatile A[]>&> s(new A[2], d);
+   A* p = s.get();
+   bml::unique_ptr<volatile A[], def_constr_deleter<volatile A[]>&> s2(boost::move(s));
+   BOOST_TEST(s2.get() == p);
+   BOOST_TEST(s.get() == 0);
+   BOOST_TEST(A::count == 2);
+   d.set_state(6);
+   BOOST_TEST(s2.get_deleter().state() == d.state());
+   BOOST_TEST(s.get_deleter().state() ==  d.state());
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_move_convert_dfctrdelref{
+
+////////////////////////////////
+//   unique_ptr_ctor_move_sourcesink
+////////////////////////////////
+
+namespace unique_ptr_ctor_move_sourcesink{
+
+// test move ctor.  Should only require a MoveConstructible deleter, or if
+//    deleter is a reference, not even that.
+
+bml::unique_ptr<A> source1()
+{  return bml::unique_ptr<A>(new A);  }
+
+bml::unique_ptr<A[]> source1_unbounded_array()
+{  return bml::unique_ptr<A[]> (new A[2]);  }
+
+bml::unique_ptr<A[2]> source1_bounded_array()
+{  return bml::unique_ptr<A[2]> (new A[2]);  }
+
+void sink1(bml::unique_ptr<A>)
+{}
+
+void sink1_unbounded_array(bml::unique_ptr<A[]>)
+{}
+
+void sink1_bounded_array(bml::unique_ptr<A[2]>)
+{}
+
+bml::unique_ptr<A, move_constr_deleter<A> > source2()
+{  return bml::unique_ptr<A, move_constr_deleter<A> > (new A);  }
+
+bml::unique_ptr<A[], move_constr_deleter<A[]> > source2_unbounded_array()
+{  return bml::unique_ptr<A[], move_constr_deleter<A[]> >(new A[2]);  }
+
+bml::unique_ptr<A[2], move_constr_deleter<A[2]> > source2_bounded_array()
+{  return bml::unique_ptr<A[2], move_constr_deleter<A[2]> >(new A[2]);  }
+
+void sink2(bml::unique_ptr<A, move_constr_deleter<A> >)
+{}
+
+void sink2_unbounded_array(bml::unique_ptr<A[], move_constr_deleter<A[]> >)
+{}
+
+void sink2_bounded_array(bml::unique_ptr<A[2], move_constr_deleter<A[2]> >)
+{}
+
+bml::unique_ptr<A, def_constr_deleter<A>&> source3()
+{
+   static def_constr_deleter<A> d;
+   return bml::unique_ptr<A, def_constr_deleter<A>&>(new A, d);
+}
+
+bml::unique_ptr<A[], def_constr_deleter<A[]>&> source3_unbounded_array()
+{
+   static def_constr_deleter<A[]> d;
+   return bml::unique_ptr<A[], def_constr_deleter<A[]>&>(new A[2], d);
+}
+
+bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> source3_bounded_array()
+{
+   static def_constr_deleter<A[2]> d;
+   return bml::unique_ptr<A[2], def_constr_deleter<A[2]>&>(new A[2], d);
+}
+
+void sink3(bml::unique_ptr<A, def_constr_deleter<A>&> )
+{}
+
+void sink3_unbounded_array(bml::unique_ptr<A[], def_constr_deleter<A[]>&> )
+{}
+
+void sink3_bounded_array(bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> )
+{}
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters(); 
+   sink1(source1());
+   sink2(source2());
+   sink3(source3());
+   BOOST_TEST(A::count == 0);
+   //Unbounded array unique_ptr
+   reset_counters();
+   sink1_unbounded_array(source1_unbounded_array());
+   sink2_unbounded_array(source2_unbounded_array());
+   sink3_unbounded_array(source3_unbounded_array());
+   BOOST_TEST(A::count == 0);
+   //Bbounded array unique_ptr
+   reset_counters();
+   sink1_bounded_array(source1_bounded_array());
+   sink2_bounded_array(source2_bounded_array());
+   sink3_bounded_array(source3_bounded_array());
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_ctor_move_sourcesink{
+
+////////////////////////////////
+//             main
+////////////////////////////////
+int main()
+{
+   //Move Constructor
+   unique_ptr_ctor_move_defdel::test();
+   unique_ptr_ctor_move_movedel::test();
+   unique_ptr_ctor_move_dfctrdelref::test();
+   unique_ptr_ctor_move_convert_defdel::test();
+   unique_ptr_ctor_move_convert_movedel::test();
+   unique_ptr_ctor_move_convert_dfctrdelref::test();
+   unique_ptr_ctor_move_sourcesink::test();
+
+   //Test results
+   return boost::report_errors();
+}
+
+#include "unique_ptr_test_utils_end.hpp"
diff --git a/test/unique_ptr_nullptr.cpp b/test/unique_ptr_nullptr.cpp
new file mode 100644
index 0000000..555fcc2
--- /dev/null
+++ b/test/unique_ptr_nullptr.cpp
@@ -0,0 +1,228 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/utility_core.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+//////////////////////////////////////////////
+//
+// The initial implementation of these tests
+// was written by Howard Hinnant. 
+//
+// These test were later refactored grouping
+// and porting them to Boost.Move.
+//
+// Many thanks to Howard for releasing his C++03
+// unique_ptr implementation with such detailed
+// test cases.
+//
+//////////////////////////////////////////////
+
+#include "unique_ptr_test_utils_beg.hpp"
+
+namespace bml = ::boost::movelib;
+
+////////////////////////////////
+//   unique_ptr_zero
+////////////////////////////////
+namespace unique_ptr_zero {
+
+// test initialization/assignment from zero
+
+void test()
+{
+   //Single unique_ptr
+   reset_counters();
+   {
+   bml::unique_ptr<A> s2(0);
+   BOOST_TEST(A::count == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<A> s2(new A);
+   BOOST_TEST(A::count == 1);
+   s2 = 0;
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(s2.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Unbounded array unique_ptr
+   {
+   bml::unique_ptr<A[]> s2(0);
+   BOOST_TEST(A::count == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<A[]> s2(new A[2]);
+   BOOST_TEST(A::count == 2);
+   s2 = 0;
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(s2.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Bounded array unique_ptr
+   {
+   bml::unique_ptr<A[2]> s2(0);
+   BOOST_TEST(A::count == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+   bml::unique_ptr<A[2]> s2(new A[2]);
+   BOOST_TEST(A::count == 2);
+   s2 = 0;
+   BOOST_TEST(A::count == 0);
+   BOOST_TEST(s2.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+}
+
+}  //namespace unique_ptr_zero {
+
+
+////////////////////////////////
+//       unique_ptr_nullptr
+////////////////////////////////
+
+namespace unique_ptr_nullptr{
+
+void test()
+{
+   #if !defined(BOOST_NO_CXX11_NULLPTR)
+   //Single unique_ptr
+   reset_counters();
+   {
+      bml::unique_ptr<A> p(new A);
+      BOOST_TEST(A::count == 1);
+      A* i = p.get();
+      (void)i;
+      p.reset(nullptr);
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+      bml::unique_ptr<A> p(new A);
+      BOOST_TEST(A::count == 1);
+      A* i = p.get();
+      (void)i;
+      p = nullptr;
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+
+   {
+      bml::unique_ptr<A> pi(nullptr);
+      BOOST_TEST(pi.get() == nullptr);
+      BOOST_TEST(pi.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+      bml::unique_ptr<A> pi(nullptr, bml::unique_ptr<A>::deleter_type());
+      BOOST_TEST(pi.get() == nullptr);
+      BOOST_TEST(pi.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Unbounded array unique_ptr
+   reset_counters();
+   {
+      bml::unique_ptr<A[]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p.reset(nullptr);
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+      bml::unique_ptr<A[]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p = nullptr;
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+      bml::unique_ptr<A[]> pi(nullptr);
+      BOOST_TEST(pi.get() == nullptr);
+      BOOST_TEST(pi.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+      bml::unique_ptr<A[]> pi(nullptr, bml::unique_ptr<A[]>::deleter_type());
+      BOOST_TEST(pi.get() == nullptr);
+      BOOST_TEST(pi.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+
+   //Bounded array unique_ptr
+   reset_counters();
+   {
+      bml::unique_ptr<A[2]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p.reset(nullptr);
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+      bml::unique_ptr<A[2]> p(new A[2]);
+      BOOST_TEST(A::count == 2);
+      A* i = p.get();
+      (void)i;
+      p = nullptr;
+      BOOST_TEST(A::count == 0);
+      BOOST_TEST(p.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+      bml::unique_ptr<A[2]> pi(nullptr);
+      BOOST_TEST(pi.get() == nullptr);
+      BOOST_TEST(pi.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   {
+      bml::unique_ptr<A[2]> pi(nullptr, bml::unique_ptr<A[2]>::deleter_type());
+      BOOST_TEST(pi.get() == nullptr);
+      BOOST_TEST(pi.get() == 0);
+   }
+   BOOST_TEST(A::count == 0);
+   #endif
+}
+
+}  //namespace unique_ptr_nullptr{
+
+////////////////////////////////
+//             main
+////////////////////////////////
+int main()
+{
+   //nullptr
+   unique_ptr_zero::test();
+   unique_ptr_nullptr::test();
+
+   //Test results
+   return boost::report_errors();
+
+}
+
+#include "unique_ptr_test_utils_end.hpp"
diff --git a/test/unique_ptr_observers.cpp b/test/unique_ptr_observers.cpp
new file mode 100644
index 0000000..14376a0
--- /dev/null
+++ b/test/unique_ptr_observers.cpp
@@ -0,0 +1,287 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/utility_core.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+//////////////////////////////////////////////
+//
+// The initial implementation of these tests
+// was written by Howard Hinnant. 
+//
+// These test were later refactored grouping
+// and porting them to Boost.Move.
+//
+// Many thanks to Howard for releasing his C++03
+// unique_ptr implementation with such detailed
+// test cases.
+//
+//////////////////////////////////////////////
+
+#include "unique_ptr_test_utils_beg.hpp"
+
+namespace bml = ::boost::movelib;
+
+////////////////////////////////
+//   unique_ptr_observers_dereference
+////////////////////////////////
+
+namespace unique_ptr_observers_dereference{
+
+void test()
+{
+   //Single unique_ptr
+   {
+   bml::unique_ptr<int> p(new int(3));
+   BOOST_TEST(*p == 3);
+   }
+   //Unbounded array unique_ptr
+   {
+   int *pi = new int[2];
+   pi[0] = 3;
+   pi[1] = 4;
+   bml::unique_ptr<int[]> p(pi);
+   BOOST_TEST(p[0] == 3);
+   BOOST_TEST(p[1] == 4);
+   }
+   //Bounded array unique_ptr
+   {
+   int *pi = new int[2];
+   pi[0] = 3;
+   pi[1] = 4;
+   bml::unique_ptr<int[2]> p(pi);
+   BOOST_TEST(p[0] == 3);
+   BOOST_TEST(p[1] == 4);
+   }
+}
+
+}  //namespace unique_ptr_observers_dereference{
+
+////////////////////////////////
+//   unique_ptr_observers_dereference
+////////////////////////////////
+
+namespace unique_ptr_observers_explicit_bool{
+
+void test()
+{
+   //Single unique_ptr
+   {
+   bml::unique_ptr<int> p(new int(3));
+   if (p)
+      ;
+   else
+      BOOST_TEST(false);
+   if (!p)
+      BOOST_TEST(false);
+   }
+   {
+   bml::unique_ptr<int> p;
+   if (!p)
+      ;
+   else
+      BOOST_TEST(false);
+   if (p)
+      BOOST_TEST(false);
+   }
+   //Unbounded array unique_ptr
+   {
+   bml::unique_ptr<int[]> p(new int[2]);
+   if (p)
+      ;
+   else
+      BOOST_TEST(false);
+   if (!p)
+      BOOST_TEST(false);
+   }
+   {
+   bml::unique_ptr<int[]> p;
+   if (!p)
+      ;
+   else
+      BOOST_TEST(false);
+   if (p)
+      BOOST_TEST(false);
+   }
+   //Bounded array unique_ptr
+   {
+   bml::unique_ptr<int[2]> p(new int[2]);
+   if (p)
+      ;
+   else
+      BOOST_TEST(false);
+   if (!p)
+      BOOST_TEST(false);
+   }
+   {
+   bml::unique_ptr<int[2]> p;
+   if (!p)
+      ;
+   else
+      BOOST_TEST(false);
+   if (p)
+      BOOST_TEST(false);
+   }
+}
+
+}  //namespace unique_ptr_observers_explicit_bool{
+
+////////////////////////////////
+//   unique_ptr_observers_get
+////////////////////////////////
+
+namespace unique_ptr_observers_get{
+
+void test()
+{
+   //Single unique_ptr
+   {
+   int* p = new int;
+   bml::unique_ptr<int> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   //Unbounded array unique_ptr
+   {
+   int* p = new int[2];
+   bml::unique_ptr<int[]> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   {
+   int* p = new int[2];
+   bml::unique_ptr<int[2]> s(p);
+   BOOST_TEST(s.get() == p);
+   }
+   //Bounded array unique_ptr
+   {
+   int *pi = new int[2];
+   pi[0] = 3;
+   pi[1] = 4;
+   bml::unique_ptr<int[2]> p(pi);
+   BOOST_TEST(p[0] == 3);
+   BOOST_TEST(p[1] == 4);
+   }
+}
+
+}  //namespace unique_ptr_observers_get{
+
+////////////////////////////////
+//   unique_ptr_observers_get_deleter
+////////////////////////////////
+
+namespace unique_ptr_observers_get_deleter{
+
+struct Deleter
+{
+   void operator()(void*) {}
+
+   int test() {return 5;}
+   int test() const {return 6;}
+};
+
+void test()
+{
+   //Single unique_ptr
+   {
+   bml::unique_ptr<int, Deleter> p;
+   BOOST_TEST(p.get_deleter().test() == 5);
+   }
+   {
+   const bml::unique_ptr<int, Deleter> p;
+   BOOST_TEST(p.get_deleter().test() == 6);
+   }
+   //Unbounded array unique_ptr
+   {
+   bml::unique_ptr<int[], Deleter> p;
+   BOOST_TEST(p.get_deleter().test() == 5);
+   }
+   {
+   const bml::unique_ptr<int[], Deleter> p;
+   BOOST_TEST(p.get_deleter().test() == 6);
+   }
+   //Bounded array unique_ptr
+   {
+   bml::unique_ptr<int[2], Deleter> p;
+   BOOST_TEST(p.get_deleter().test() == 5);
+   }
+   {
+   const bml::unique_ptr<int[2], Deleter> p;
+   BOOST_TEST(p.get_deleter().test() == 6);
+   }
+}
+
+}  //namespace unique_ptr_observers_get_deleter{
+
+////////////////////////////////
+//   unique_ptr_observers_op_arrow
+////////////////////////////////
+
+namespace unique_ptr_observers_op_arrow{
+
+void test()
+{
+   //Single unique_ptr
+   {
+   bml::unique_ptr<A> p(new A);
+   BOOST_TEST(p->state_ == 999);
+   }
+}
+
+}  //namespace unique_ptr_observers_op_arrow{
+
+
+namespace unique_ptr_observers_op_index{
+
+void test()
+{
+   //Unbounded array unique_ptr
+   {
+   A *pa = new A[2];
+   //pa[0] is left default constructed
+   pa[1].set(888);
+   bml::unique_ptr<A[]> p(pa);
+   BOOST_TEST(p[0].state_ == 999);
+   BOOST_TEST(p[1].state_ == 888);
+   }
+   //Bounded array unique_ptr
+   {
+   A *pa = new A[2];
+   //pa[0] is left default constructed
+   pa[1].set(888);
+   bml::unique_ptr<A[2]> p(pa);
+   BOOST_TEST(p[0].state_ == 999);
+   BOOST_TEST(p[1].state_ == 888);
+   }
+}
+
+}  //namespace unique_ptr_observers_op_index{
+
+////////////////////////////////
+//             main
+////////////////////////////////
+int main()
+{
+   //Observers
+   unique_ptr_observers_dereference::test();
+   unique_ptr_observers_explicit_bool::test();
+   unique_ptr_observers_get::test();
+   unique_ptr_observers_get_deleter::test();
+   unique_ptr_observers_op_arrow::test();
+   unique_ptr_observers_op_index::test();
+
+   //Test results
+   return boost::report_errors();
+
+}
+
+#include "unique_ptr_test_utils_end.hpp"
diff --git a/test/unique_ptr_test_utils_beg.hpp b/test/unique_ptr_test_utils_beg.hpp
new file mode 100644
index 0000000..965732c
--- /dev/null
+++ b/test/unique_ptr_test_utils_beg.hpp
@@ -0,0 +1,209 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP
+#define BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP
+#include <boost/move/core.hpp>
+#include <boost/move/detail/unique_ptr_meta_utils.hpp>
+#include <boost/static_assert.hpp>
+
+//////////////////////////////////////////////
+//
+// The initial implementation of these tests
+// was written by Howard Hinnant. 
+//
+// These test were later refactored grouping
+// and porting them to Boost.Move.
+//
+// Many thanks to Howard for releasing his C++03
+// unique_ptr implementation with such detailed
+// test cases.
+//
+//////////////////////////////////////////////
+
+//A deleter that can only default constructed
+template <class T>
+class def_constr_deleter
+{
+   int state_;
+   def_constr_deleter(const def_constr_deleter&);
+   def_constr_deleter& operator=(const def_constr_deleter&);
+
+   public:
+   typedef typename ::boost::move_upmu::remove_extent<T>::type element_type;
+   static const bool is_array = ::boost::move_upmu::is_array<T>::value;
+
+   def_constr_deleter() : state_(5) {}
+
+   explicit def_constr_deleter(int s) : state_(s) {}
+
+   int state() const {return state_;}
+
+   void set_state(int s) {state_ = s;}
+
+   void operator()(element_type* p) const
+   {  is_array ? delete []p : delete p;   }
+
+   void operator()(element_type* p)
+   {  ++state_;   is_array ? delete []p : delete p;  }
+};
+
+//A deleter that can be copy constructed
+template <class T>
+class copy_constr_deleter
+{
+   int state_;
+
+   public:
+   typedef typename ::boost::move_upmu::remove_extent<T>::type element_type;
+   static const bool is_array = ::boost::move_upmu::is_array<T>::value;
+
+   copy_constr_deleter() : state_(5) {}
+
+   template<class U>
+   copy_constr_deleter(const copy_constr_deleter<U>&
+      , typename boost::move_upd::enable_def_del<U, T>::type* =0)
+   {  state_ = 5; }
+
+   explicit copy_constr_deleter(int s) : state_(s) {}
+
+   template <class U>
+   typename boost::move_upd::enable_def_del<U, T, copy_constr_deleter&>::type
+      operator=(const copy_constr_deleter<U> &d)
+   {
+      state_ = d.state();
+      return *this;
+   }
+
+   int state() const          {return state_;}
+
+   void set_state(int s)      {state_ = s;}
+
+   void operator()(element_type* p) const
+   {  is_array ? delete []p : delete p;   }
+
+   void operator()(element_type* p)
+   {  ++state_;   is_array ? delete []p : delete p;  }
+};
+
+//A deleter that can be only move constructed
+template <class T>
+class move_constr_deleter
+{
+   int state_;
+
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(move_constr_deleter)
+
+   public:
+   typedef typename ::boost::move_upmu::remove_extent<T>::type element_type;
+   static const bool is_array = ::boost::move_upmu::is_array<T>::value;
+
+   move_constr_deleter() : state_(5) {}
+
+   move_constr_deleter(BOOST_RV_REF(move_constr_deleter) r)
+      : state_(r.state_)
+   {  r.state_ = 0;  }
+
+   explicit move_constr_deleter(int s) : state_(s) {}
+
+   template <class U>
+   move_constr_deleter(BOOST_RV_REF(move_constr_deleter<U>) d
+      , typename boost::move_upd::enable_def_del<U, T>::type* =0)
+      : state_(d.state())
+   { d.set_state(0);  }
+
+   move_constr_deleter& operator=(BOOST_RV_REF(move_constr_deleter) r)
+   {
+      state_ = r.state_;
+      r.state_ = 0;
+      return *this;
+   }
+
+   template <class U>
+   typename boost::move_upd::enable_def_del<U, T, move_constr_deleter&>::type
+      operator=(BOOST_RV_REF(move_constr_deleter<U>) d)
+   {
+      state_ = d.state();
+      d.set_state(0);
+      return *this;
+   }
+
+   int state() const          {return state_;}
+
+   void set_state(int s)      {state_ = s;}
+
+   void operator()(element_type* p) const
+   {  is_array ? delete []p : delete p;   }
+
+   void operator()(element_type* p)
+   {  ++state_;   is_array ? delete []p : delete p;  }
+
+   friend bool operator==(const move_constr_deleter& x, const move_constr_deleter& y)
+      {return x.state_ == y.state_;}
+};
+
+//A base class containing state with a static instance counter
+struct A
+{
+   int state_;
+   static int count;
+
+   A()               : state_(999)      {++count;}
+   explicit A(int i) : state_(i)        {++count;}
+   A(const A& a)     : state_(a.state_) {++count;}
+   A& operator=(const A& a) { state_ = a.state_; return *this; }
+   void set(int i)   {state_ = i;}
+   virtual ~A()      {--count;}
+   friend bool operator==(const A& x, const A& y) { return x.state_ == y.state_; }
+};
+
+int A::count = 0;
+
+//A class derived from A with a static instance counter
+struct B
+   : public A
+{
+   static int count;
+   B() : A() {++count;}
+   B(const B &b) : A(b) {++count;}
+   virtual ~B() {--count;}
+};
+
+int B::count = 0;
+
+void reset_counters();
+
+BOOST_STATIC_ASSERT((::boost::move_upmu::is_convertible<B, A>::value));
+
+//Incomplete Type function declarations
+struct I;
+void check(int i);
+I* get();
+I* get_array(int i);
+
+#include <boost/move/unique_ptr.hpp>
+
+template <class T, class D = ::boost::movelib::default_delete<T> >
+struct J
+{
+   typedef boost::movelib::unique_ptr<T, D> unique_ptr_type;
+   typedef typename unique_ptr_type::element_type element_type;
+   boost::movelib::unique_ptr<T, D> a_;
+   J() {}
+   explicit J(element_type*a) : a_(a) {}
+   ~J();
+
+   element_type* get() const {return a_.get();}
+   D& get_deleter() {return a_.get_deleter();}
+};
+
+#endif   //BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP
diff --git a/test/unique_ptr_test_utils_end.hpp b/test/unique_ptr_test_utils_end.hpp
new file mode 100644
index 0000000..ca0fb92
--- /dev/null
+++ b/test/unique_ptr_test_utils_end.hpp
@@ -0,0 +1,46 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_END_HPP
+#define BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_END_HPP
+
+#ifndef BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP
+#error "unique_ptr_test_utils_beg.hpp MUST be included before this header"
+#endif
+
+//Define the incomplete I type and out of line functions
+
+struct I
+{
+   static int count;
+   I() {++count;}
+   I(const A&) {++count;}
+   ~I() {--count;}
+};
+
+int I::count = 0;
+
+I* get() {return new I;}
+I* get_array(int i) {return new I[i];}
+
+void check(int i)
+{
+   BOOST_TEST(I::count == i);
+}
+
+template <class T, class D>
+J<T, D>::~J() {}
+
+void reset_counters()
+{  A::count = 0; B::count = 0; I::count = 0; }
+
+#endif   //BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_END_HPP
diff --git a/test/unique_ptr_types.cpp b/test/unique_ptr_types.cpp
new file mode 100644
index 0000000..7dbc0c3
--- /dev/null
+++ b/test/unique_ptr_types.cpp
@@ -0,0 +1,200 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2009
+// (C) Copyright Ion Gaztanaga 2014-2014.
+//
+// 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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/move/utility_core.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/move/detail/type_traits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+//////////////////////////////////////////////
+//
+// The initial implementation of these tests
+// was written by Howard Hinnant. 
+//
+// These test were later refactored grouping
+// and porting them to Boost.Move.
+//
+// Many thanks to Howard for releasing his C++03
+// unique_ptr implementation with such detailed
+// test cases.
+//
+//////////////////////////////////////////////
+
+#include "unique_ptr_test_utils_beg.hpp"
+
+namespace bml = ::boost::movelib;
+namespace bmupmu = ::boost::move_upmu;
+
+////////////////////////////////
+//   unique_ptr_pointer_type
+////////////////////////////////
+namespace unique_ptr_pointer_type {
+
+struct Deleter
+{
+   struct pointer {};
+};
+
+// Test unique_ptr::pointer type
+void test()
+{
+   //Single unique_ptr
+   {
+   typedef bml::unique_ptr<int> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, int*>::value));
+   }
+   {
+   typedef bml::unique_ptr<int, Deleter> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, Deleter::pointer>::value));
+   }
+   //Unbounded array unique_ptr
+   {
+   typedef bml::unique_ptr<int[]> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, int*>::value));
+   }
+   {
+   typedef bml::unique_ptr<int[], Deleter> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, Deleter::pointer>::value));
+   }
+   //Bounded array unique_ptr
+   {
+   typedef bml::unique_ptr<int[5]> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, int*>::value));
+   }
+   {
+   typedef bml::unique_ptr<int[5], Deleter> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, Deleter::pointer>::value));
+   }
+   //Unbounded array of bounded array unique_ptr
+   {
+   typedef int int_5_t [5];
+   typedef bml::unique_ptr<int_5_t[]> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, int_5_t*>::value));
+   }
+   {
+   typedef int int_5_t [5];
+   typedef bml::unique_ptr<int_5_t[], Deleter> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, Deleter::pointer>::value));
+   }
+}
+
+}  //namespace unique_ptr_pointer_type {
+
+////////////////////////////////
+//    unique_ptr_deleter_type
+////////////////////////////////
+namespace unique_ptr_deleter_type {
+
+struct Deleter
+{};
+
+// Test unique_ptr::deleter type
+void test()
+{
+   //Single unique_ptr
+   {
+   typedef bml::unique_ptr<int> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, bml::default_delete<int> >::value));
+   }
+   {
+   typedef bml::unique_ptr<int, Deleter> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, Deleter >::value));
+   }
+   //Unbounded array unique_ptr
+   {
+   typedef bml::unique_ptr<int[]> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, bml::default_delete<int[]> >::value));
+   }
+   {
+   typedef bml::unique_ptr<int[], Deleter> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, Deleter >::value));
+   }
+   //Bounded array unique_ptr
+   {
+   typedef bml::unique_ptr<int[2]> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, bml::default_delete<int[2]> >::value));
+   }
+   {
+   typedef bml::unique_ptr<int[2], Deleter> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, Deleter >::value));
+   }
+}
+
+}  //namespace unique_ptr_deleter_type {
+
+////////////////////////////////
+//    unique_ptr_element_type
+////////////////////////////////
+namespace unique_ptr_element_type {
+
+// Test unique_ptr::deleter type
+void test()
+{
+   //Single unique_ptr
+   {
+   typedef bml::unique_ptr<const int> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::element_type, const int>::value));
+   }
+   //Unbounded array unique_ptr
+   {
+   typedef bml::unique_ptr<const int[]> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::element_type, const int>::value));
+   }
+   //Bounded array unique_ptr
+   {
+   typedef bml::unique_ptr<const int[2]> P;
+   BOOST_STATIC_ASSERT((bmupmu::is_same<P::element_type, const int>::value));
+   }
+}
+
+}  //namespace unique_ptr_element_type {
+
+////////////////////////////////
+//    unique_ptr_construct_assign_traits
+////////////////////////////////
+
+namespace unique_ptr_construct_assign_traits {
+
+   void test()
+   {
+      typedef bml::unique_ptr<int> unique_ptr_t;
+      //Even if BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE is not defined
+      //boost::unique_ptr shall work with boost::movelib traits
+      BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_constructible<unique_ptr_t>::value));
+      //Even if BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE is not defined
+      //boost::unique_ptr shall work with boost::movelib traits
+      BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_assignable<unique_ptr_t>::value));
+      //Important traits for containers like boost::vector
+      BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible<unique_ptr_t>::value));
+      BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable<unique_ptr_t>::value));
+   }
+
+}  //namespace unique_ptr_construct_assign_traits {
+
+////////////////////////////////
+//             main
+////////////////////////////////
+
+int main()
+{
+   //General
+   unique_ptr_pointer_type::test();
+   unique_ptr_deleter_type::test();
+   unique_ptr_element_type::test();
+   unique_ptr_construct_assign_traits::test();
+
+   //Test results
+   return boost::report_errors();
+}
+
+#include "unique_ptr_test_utils_end.hpp"