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/include/boost/move/adl_move_swap.hpp b/include/boost/move/adl_move_swap.hpp
new file mode 100644
index 0000000..d9096e3
--- /dev/null
+++ b/include/boost/move/adl_move_swap.hpp
@@ -0,0 +1,272 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright 2007, 2008 Steven Watanabe, Joseph Gauterin, Niels Dekker
+// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
+#define BOOST_MOVE_ADL_MOVE_SWAP_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//Based on Boost.Core's swap.
+//Many thanks to Steven Watanabe, Joseph Gauterin and Niels Dekker.
+#include <cstddef> //for std::size_t
+#include <boost/move/detail/workaround.hpp> //forceinline
+
+//Try to avoid including <algorithm>, as it's quite big
+#if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB)
+ #include <utility> //Dinkum libraries define std::swap in utility which is lighter than algorithm
+#elif defined(BOOST_GNU_STDLIB)
+ //For non-GCC compilers, where GNUC version is not very reliable, or old GCC versions
+ //use the good old stl_algobase header, which is quite lightweight
+ #if !defined(BOOST_GCC) || ((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 3)))
+ #include <bits/stl_algobase.h>
+ #elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
+ //In GCC 4.3 a tiny stl_move.h was created with swap and move utilities
+ #include <bits/stl_move.h>
+ #else
+ //In GCC 4.4 stl_move.h was renamed to move.h
+ #include <bits/move.h>
+ #endif
+#elif defined(_LIBCPP_VERSION)
+ #include <type_traits> //The initial import of libc++ defines std::swap and still there
+#elif __cplusplus >= 201103L
+ #include <utility> //Fallback for C++ >= 2011
+#else
+ #include <algorithm> //Fallback for C++98/03
+#endif
+
+#include <boost/move/utility_core.hpp> //for boost::move
+
+#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+namespace boost_move_member_swap {
+
+struct dont_care
+{
+ dont_care(...);
+};
+
+struct private_type
+{
+ static private_type p;
+ private_type const &operator,(int) const;
+};
+
+typedef char yes_type;
+struct no_type{ char dummy[2]; };
+
+template<typename T>
+no_type is_private_type(T const &);
+
+yes_type is_private_type(private_type const &);
+
+template <typename Type>
+class has_member_function_named_swap
+{
+ struct BaseMixin
+ {
+ void swap();
+ };
+
+ struct Base : public Type, public BaseMixin { Base(); };
+ template <typename T, T t> class Helper{};
+
+ template <typename U>
+ static no_type deduce(U*, Helper<void (BaseMixin::*)(), &U::swap>* = 0);
+ static yes_type deduce(...);
+
+ public:
+ static const bool value = sizeof(yes_type) == sizeof(deduce((Base*)(0)));
+};
+
+template<typename Fun, bool HasFunc>
+struct has_member_swap_impl
+{
+ static const bool value = false;
+};
+
+template<typename Fun>
+struct has_member_swap_impl<Fun, true>
+{
+ struct FunWrap : Fun
+ {
+ FunWrap();
+
+ using Fun::swap;
+ private_type swap(dont_care) const;
+ };
+
+ static Fun &declval_fun();
+ static FunWrap declval_wrap();
+
+ static bool const value =
+ sizeof(no_type) == sizeof(is_private_type( (declval_wrap().swap(declval_fun()), 0)) );
+};
+
+template<typename Fun>
+struct has_member_swap : public has_member_swap_impl
+ <Fun, has_member_function_named_swap<Fun>::value>
+{};
+
+} //namespace boost_move_member_swap
+
+namespace boost_move_adl_swap{
+
+template<class P1, class P2, bool = P1::value>
+struct and_op_impl
+{ static const bool value = false; };
+
+template<class P1, class P2>
+struct and_op_impl<P1, P2, true>
+{ static const bool value = P2::value; };
+
+template<class P1, class P2>
+struct and_op
+ : and_op_impl<P1, P2>
+{};
+
+//////
+
+template<class P1, class P2, bool = P1::value>
+struct and_op_not_impl
+{ static const bool value = false; };
+
+template<class P1, class P2>
+struct and_op_not_impl<P1, P2, true>
+{ static const bool value = !P2::value; };
+
+template<class P1, class P2>
+struct and_op_not
+ : and_op_not_impl<P1, P2>
+{};
+
+template<class T>
+BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
+{
+ //use std::swap if argument dependent lookup fails
+ //Use using directive ("using namespace xxx;") instead as some older compilers
+ //don't do ADL with using declarations ("using ns::func;").
+ using namespace std;
+ swap(x, y);
+}
+
+template<class T>
+BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
+ , typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>
+ , boost_move_member_swap::has_member_swap<T> >
+ >::type* = 0)
+{ T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t); }
+
+template<class T>
+BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
+ , typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T>
+ , boost_move_member_swap::has_member_swap<T> >
+ >::type* = 0)
+{ x.swap(y); }
+
+} //namespace boost_move_adl_swap{
+
+#else
+
+namespace boost_move_adl_swap{
+
+template<class T>
+BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y)
+{
+ using std::swap;
+ swap(x, y);
+}
+
+} //namespace boost_move_adl_swap{
+
+#endif //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+namespace boost_move_adl_swap{
+
+template<class T, std::size_t N>
+void swap_proxy(T (& x)[N], T (& y)[N])
+{
+ for (std::size_t i = 0; i < N; ++i){
+ ::boost_move_adl_swap::swap_proxy(x[i], y[i]);
+ }
+}
+
+} //namespace boost_move_adl_swap {
+
+#endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+namespace boost{
+
+//! Exchanges the values of a and b, using Argument Dependent Lookup (ADL) to select a
+//! specialized swap function if available. If no specialized swap function is available,
+//! std::swap is used.
+//!
+//! <b>Exception</b>: If T uses Boost.Move's move emulation and the compiler has
+//! no rvalue references then:
+//!
+//! - If T has a <code>T::swap(T&)</code> member, that member is called.
+//! - Otherwise a move-based swap is called, equivalent to:
+//! <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>.
+template<class T>
+BOOST_MOVE_FORCEINLINE void adl_move_swap(T& x, T& y)
+{
+ ::boost_move_adl_swap::swap_proxy(x, y);
+}
+
+//! Exchanges elements between range [first1, last1) and another range starting at first2
+//! using boost::adl_move_swap.
+//!
+//! Parameters:
+//! first1, last1 - the first range of elements to swap
+//! first2 - beginning of the second range of elements to swap
+//!
+//! Type requirements:
+//! - ForwardIt1, ForwardIt2 must meet the requirements of ForwardIterator.
+//! - The types of dereferenced ForwardIt1 and ForwardIt2 must meet the
+//! requirements of Swappable
+//!
+//! Return value: Iterator to the element past the last element exchanged in the range
+//! beginning with first2.
+template<class ForwardIt1, class ForwardIt2>
+ForwardIt2 adl_move_swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
+{
+ while (first1 != last1) {
+ ::boost::adl_move_swap(*first1, *first2);
+ ++first1;
+ ++first2;
+ }
+ return first2;
+}
+
+template<class BidirIt1, class BidirIt2>
+BidirIt2 adl_move_swap_ranges_backward(BidirIt1 first1, BidirIt1 last1, BidirIt2 last2)
+{
+ while (first1 != last1) {
+ ::boost::adl_move_swap(*(--last1), *(--last2));
+ }
+ return last2;
+}
+
+template<class ForwardIt1, class ForwardIt2>
+void adl_move_iter_swap(ForwardIt1 a, ForwardIt2 b)
+{
+ boost::adl_move_swap(*a, *b);
+}
+
+} //namespace boost{
+
+#endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
diff --git a/include/boost/move/algo/adaptive_merge.hpp b/include/boost/move/algo/adaptive_merge.hpp
new file mode 100644
index 0000000..4de4007
--- /dev/null
+++ b/include/boost/move/algo/adaptive_merge.hpp
@@ -0,0 +1,343 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ADAPTIVE_MERGE_HPP
+#define BOOST_MOVE_ADAPTIVE_MERGE_HPP
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
+
+namespace boost {
+namespace movelib {
+
+///@cond
+namespace detail_adaptive {
+
+template<class RandIt, class Compare, class XBuf>
+inline void adaptive_merge_combine_blocks( RandIt first
+ , typename iterator_traits<RandIt>::size_type len1
+ , typename iterator_traits<RandIt>::size_type len2
+ , typename iterator_traits<RandIt>::size_type collected
+ , typename iterator_traits<RandIt>::size_type n_keys
+ , typename iterator_traits<RandIt>::size_type l_block
+ , bool use_internal_buf
+ , bool xbuf_used
+ , Compare comp
+ , XBuf & xbuf
+ )
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const len = len1+len2;
+ size_type const l_combine = len-collected;
+ size_type const l_combine1 = len1-collected;
+
+ if(n_keys){
+ RandIt const first_data = first+collected;
+ RandIt const keys = first;
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combine: ", len);
+ if(xbuf_used){
+ if(xbuf.size() < l_block){
+ xbuf.initialize_until(l_block, *first);
+ }
+ BOOST_ASSERT(xbuf.size() >= l_block);
+ size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
+ combine_params( keys, comp, l_combine
+ , l_combine1, l_block, xbuf
+ , n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
+ op_merge_blocks_with_buf
+ (keys, comp, first_data, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, move_op(), xbuf.data());
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" A mrg xbf: ", len);
+ }
+ else{
+ size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
+ combine_params( keys, comp, l_combine
+ , l_combine1, l_block, xbuf
+ , n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
+ if(use_internal_buf){
+ op_merge_blocks_with_buf
+ (keys, comp, first_data, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, swap_op(), first_data-l_block);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A mrg buf: ", len);
+ }
+ else{
+ merge_blocks_bufferless
+ (keys, comp, first_data, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" A mrg nbf: ", len);
+ }
+ }
+ }
+ else{
+ xbuf.shrink_to_fit(l_block);
+ if(xbuf.size() < l_block){
+ xbuf.initialize_until(l_block, *first);
+ }
+ size_type *const uint_keys = xbuf.template aligned_trailing<size_type>(l_block);
+ size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
+ combine_params( uint_keys, less(), l_combine
+ , l_combine1, l_block, xbuf
+ , n_block_a, n_block_b, l_irreg1, l_irreg2, true); //Outputs
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combine: ", len);
+ BOOST_ASSERT(xbuf.size() >= l_block);
+ op_merge_blocks_with_buf
+ (uint_keys, less(), first, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, move_op(), xbuf.data());
+ xbuf.clear();
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" A mrg buf: ", len);
+ }
+}
+
+template<class RandIt, class Compare, class XBuf>
+inline void adaptive_merge_final_merge( RandIt first
+ , typename iterator_traits<RandIt>::size_type len1
+ , typename iterator_traits<RandIt>::size_type len2
+ , typename iterator_traits<RandIt>::size_type collected
+ , typename iterator_traits<RandIt>::size_type l_intbuf
+ , typename iterator_traits<RandIt>::size_type l_block
+ , bool use_internal_buf
+ , bool xbuf_used
+ , Compare comp
+ , XBuf & xbuf
+ )
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ (void)l_block;
+ size_type n_keys = collected-l_intbuf;
+ size_type len = len1+len2;
+ if(use_internal_buf){
+ if(xbuf_used){
+ xbuf.clear();
+ //Nothing to do
+ if(n_keys){
+ unstable_sort(first, first+n_keys, comp, xbuf);
+ stable_merge(first, first+n_keys, first+len, comp, xbuf);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A key mrg: ", len);
+ }
+ }
+ else{
+ xbuf.clear();
+ unstable_sort(first, first+collected, comp, xbuf);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A k/b srt: ", len);
+ stable_merge(first, first+collected, first+len, comp, xbuf);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A k/b mrg: ", len);
+ }
+ }
+ else{
+ xbuf.clear();
+ unstable_sort(first, first+collected, comp, xbuf);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A k/b srt: ", len);
+ stable_merge(first, first+collected, first+len1+len2, comp, xbuf);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A k/b mrg: ", len);
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" A fin mrg: ", len);
+}
+
+template<class SizeType>
+inline static SizeType adaptive_merge_n_keys_without_external_keys(SizeType l_block, SizeType len1, SizeType len2, SizeType l_intbuf)
+{
+ typedef SizeType size_type;
+ //This is the minimum number of keys to implement the ideal algorithm
+ size_type n_keys = len1/l_block+len2/l_block;
+ const size_type second_half_blocks = len2/l_block;
+ const size_type first_half_aux = len1-l_intbuf;
+ while(n_keys >= ((first_half_aux-n_keys)/l_block + second_half_blocks)){
+ --n_keys;
+ }
+ ++n_keys;
+ return n_keys;
+}
+
+template<class SizeType>
+inline static SizeType adaptive_merge_n_keys_with_external_keys(SizeType l_block, SizeType len1, SizeType len2, SizeType l_intbuf)
+{
+ typedef SizeType size_type;
+ //This is the minimum number of keys to implement the ideal algorithm
+ size_type n_keys = (len1-l_intbuf)/l_block + len2/l_block;
+ return n_keys;
+}
+
+template<class SizeType, class Xbuf>
+inline SizeType adaptive_merge_n_keys_intbuf(SizeType &rl_block, SizeType len1, SizeType len2, Xbuf & xbuf, SizeType &l_intbuf_inout)
+{
+ typedef SizeType size_type;
+ size_type l_block = rl_block;
+ size_type l_intbuf = xbuf.capacity() >= l_block ? 0u : l_block;
+
+ while(xbuf.capacity() >= l_block*2){
+ l_block *= 2;
+ }
+
+ //This is the minimum number of keys to implement the ideal algorithm
+ size_type n_keys = adaptive_merge_n_keys_without_external_keys(l_block, len1, len2, l_intbuf);
+ BOOST_ASSERT(n_keys >= ((len1-l_intbuf-n_keys)/l_block + len2/l_block));
+
+ if(xbuf.template supports_aligned_trailing<size_type>
+ ( l_block
+ , adaptive_merge_n_keys_with_external_keys(l_block, len1, len2, l_intbuf)))
+ {
+ n_keys = 0u;
+ }
+ l_intbuf_inout = l_intbuf;
+ rl_block = l_block;
+ return n_keys;
+}
+
+// Main explanation of the merge algorithm.
+//
+// csqrtlen = ceil(sqrt(len));
+//
+// * First, csqrtlen [to be used as buffer] + (len/csqrtlen - 1) [to be used as keys] => to_collect
+// unique elements are extracted from elements to be sorted and placed in the beginning of the range.
+//
+// * Step "combine_blocks": the leading (len1-to_collect) elements plus trailing len2 elements
+// are merged with a non-trivial ("smart") algorithm to form an ordered range trailing "len-to_collect" elements.
+//
+// Explanation of the "combine_blocks" step:
+//
+// * Trailing [first+to_collect, first+len1) elements are divided in groups of cqrtlen elements.
+// Remaining elements that can't form a group are grouped in front of those elements.
+// * Trailing [first+len1, first+len1+len2) elements are divided in groups of cqrtlen elements.
+// Remaining elements that can't form a group are grouped in the back of those elements.
+// * In parallel the following two steps are performed:
+// * Groups are selection-sorted by first or last element (depending whether they are going
+// to be merged to left or right) and keys are reordered accordingly as an imitation-buffer.
+// * Elements of each block pair are merged using the csqrtlen buffer taking into account
+// if they belong to the first half or second half (marked by the key).
+//
+// * In the final merge step leading "to_collect" elements are merged with rotations
+// with the rest of merged elements in the "combine_blocks" step.
+//
+// Corner cases:
+//
+// * If no "to_collect" elements can be extracted:
+//
+// * If more than a minimum number of elements is extracted
+// then reduces the number of elements used as buffer and keys in the
+// and "combine_blocks" steps. If "combine_blocks" has no enough keys due to this reduction
+// then uses a rotation based smart merge.
+//
+// * If the minimum number of keys can't be extracted, a rotation-based merge is performed.
+//
+// * If auxiliary memory is more or equal than min(len1, len2), a buffered merge is performed.
+//
+// * If the len1 or len2 are less than 2*csqrtlen then a rotation-based merge is performed.
+//
+// * If auxiliary memory is more than csqrtlen+n_keys*sizeof(std::size_t),
+// then no csqrtlen need to be extracted and "combine_blocks" will use integral
+// keys to combine blocks.
+template<class RandIt, class Compare, class XBuf>
+void adaptive_merge_impl
+ ( RandIt first
+ , typename iterator_traits<RandIt>::size_type len1
+ , typename iterator_traits<RandIt>::size_type len2
+ , Compare comp
+ , XBuf & xbuf
+ )
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ if(xbuf.capacity() >= min_value<size_type>(len1, len2)){
+ buffered_merge(first, first+len1, first+(len1+len2), comp, xbuf);
+ }
+ else{
+ const size_type len = len1+len2;
+ //Calculate ideal parameters and try to collect needed unique keys
+ size_type l_block = size_type(ceil_sqrt(len));
+
+ //One range is not big enough to extract keys and the internal buffer so a
+ //rotation-based based merge will do just fine
+ if(len1 <= l_block*2 || len2 <= l_block*2){
+ merge_bufferless(first, first+len1, first+len1+len2, comp);
+ return;
+ }
+
+ //Detail the number of keys and internal buffer. If xbuf has enough memory, no
+ //internal buffer is needed so l_intbuf will remain 0.
+ size_type l_intbuf = 0;
+ size_type n_keys = adaptive_merge_n_keys_intbuf(l_block, len1, len2, xbuf, l_intbuf);
+ size_type const to_collect = l_intbuf+n_keys;
+ //Try to extract needed unique values from the first range
+ size_type const collected = collect_unique(first, first+len1, to_collect, comp, xbuf);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1("\n A collect: ", len);
+
+ //Not the minimum number of keys is not available on the first range, so fallback to rotations
+ if(collected != to_collect && collected < 4){
+ merge_bufferless(first, first+collected, first+len1, comp);
+ merge_bufferless(first, first + len1, first + len1 + len2, comp);
+ return;
+ }
+
+ //If not enough keys but more than minimum, adjust the internal buffer and key count
+ bool use_internal_buf = collected == to_collect;
+ if (!use_internal_buf){
+ l_intbuf = 0u;
+ n_keys = collected;
+ l_block = lblock_for_combine(l_intbuf, n_keys, len, use_internal_buf);
+ //If use_internal_buf is false, then then internal buffer will be zero and rotation-based combination will be used
+ l_intbuf = use_internal_buf ? l_block : 0u;
+ }
+
+ bool const xbuf_used = collected == to_collect && xbuf.capacity() >= l_block;
+ //Merge trailing elements using smart merges
+ adaptive_merge_combine_blocks(first, len1, len2, collected, n_keys, l_block, use_internal_buf, xbuf_used, comp, xbuf);
+ //Merge buffer and keys with the rest of the values
+ adaptive_merge_final_merge (first, len1, len2, collected, l_intbuf, l_block, use_internal_buf, xbuf_used, comp, xbuf);
+ }
+}
+
+} //namespace detail_adaptive {
+
+///@endcond
+
+//! <b>Effects</b>: Merges two consecutive sorted ranges [first, middle) and [middle, last)
+//! into one sorted range [first, last) according to the given comparison function comp.
+//! The algorithm is stable (if there are equivalent elements in the original two ranges,
+//! the elements from the first range (preserving their original order) precede the elements
+//! from the second range (preserving their original order).
+//!
+//! <b>Requires</b>:
+//! - RandIt must meet the requirements of ValueSwappable and RandomAccessIterator.
+//! - The type of dereferenced RandIt must meet the requirements of MoveAssignable and MoveConstructible.
+//!
+//! <b>Parameters</b>:
+//! - first: the beginning of the first sorted range.
+//! - middle: the end of the first sorted range and the beginning of the second
+//! - last: the end of the second sorted range
+//! - comp: comparison function object which returns true if the first argument is is ordered before the second.
+//! - uninitialized, uninitialized_len: raw storage starting on "uninitialized", able to hold "uninitialized_len"
+//! elements of type iterator_traits<RandIt>::value_type. Maximum performance is achieved when uninitialized_len
+//! is min(std::distance(first, middle), std::distance(middle, last)).
+//!
+//! <b>Throws</b>: If comp throws or the move constructor, move assignment or swap of the type
+//! of dereferenced RandIt throws.
+//!
+//! <b>Complexity</b>: Always K x O(N) comparisons and move assignments/constructors/swaps.
+//! Constant factor for comparisons and data movement is minimized when uninitialized_len
+//! is min(std::distance(first, middle), std::distance(middle, last)).
+//! Pretty good enough performance is achieved when uninitialized_len is
+//! ceil(sqrt(std::distance(first, last)))*2.
+//!
+//! <b>Caution</b>: Experimental implementation, not production-ready.
+template<class RandIt, class Compare>
+void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp
+ , typename iterator_traits<RandIt>::value_type* uninitialized = 0
+ , std::size_t uninitialized_len = 0)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ ::boost::movelib::detail_adaptive::adaptive_xbuf<value_type> xbuf(uninitialized, uninitialized_len);
+ ::boost::movelib::detail_adaptive::adaptive_merge_impl(first, size_type(middle - first), size_type(last - middle), comp, xbuf);
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#define BOOST_MOVE_ADAPTIVE_MERGE_HPP
diff --git a/include/boost/move/algo/adaptive_sort.hpp b/include/boost/move/algo/adaptive_sort.hpp
new file mode 100644
index 0000000..4f50bf1
--- /dev/null
+++ b/include/boost/move/algo/adaptive_sort.hpp
@@ -0,0 +1,631 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ADAPTIVE_SORT_HPP
+#define BOOST_MOVE_ADAPTIVE_SORT_HPP
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
+
+namespace boost {
+namespace movelib {
+
+///@cond
+namespace detail_adaptive {
+
+template<class RandIt>
+void move_data_backward( RandIt cur_pos
+ , typename iterator_traits<RandIt>::size_type const l_data
+ , RandIt new_pos
+ , bool const xbuf_used)
+{
+ //Move buffer to the total combination right
+ if(xbuf_used){
+ boost::move_backward(cur_pos, cur_pos+l_data, new_pos+l_data);
+ }
+ else{
+ boost::adl_move_swap_ranges_backward(cur_pos, cur_pos+l_data, new_pos+l_data);
+ //Rotate does less moves but it seems slower due to cache issues
+ //rotate_gcd(first-l_block, first+len-l_block, first+len);
+ }
+}
+
+template<class RandIt>
+void move_data_forward( RandIt cur_pos
+ , typename iterator_traits<RandIt>::size_type const l_data
+ , RandIt new_pos
+ , bool const xbuf_used)
+{
+ //Move buffer to the total combination right
+ if(xbuf_used){
+ boost::move(cur_pos, cur_pos+l_data, new_pos);
+ }
+ else{
+ boost::adl_move_swap_ranges(cur_pos, cur_pos+l_data, new_pos);
+ //Rotate does less moves but it seems slower due to cache issues
+ //rotate_gcd(first-l_block, first+len-l_block, first+len);
+ }
+}
+
+// build blocks of length 2*l_build_buf. l_build_buf is power of two
+// input: [0, l_build_buf) elements are buffer, rest unsorted elements
+// output: [0, l_build_buf) elements are buffer, blocks 2*l_build_buf and last subblock sorted
+//
+// First elements are merged from right to left until elements start
+// at first. All old elements [first, first + l_build_buf) are placed at the end
+// [first+len-l_build_buf, first+len). To achieve this:
+// - If we have external memory to merge, we save elements from the buffer
+// so that a non-swapping merge is used. Buffer elements are restored
+// at the end of the buffer from the external memory.
+//
+// - When the external memory is not available or it is insufficient
+// for a merge operation, left swap merging is used.
+//
+// Once elements are merged left to right in blocks of l_build_buf, then a single left
+// to right merge step is performed to achieve merged blocks of size 2K.
+// If external memory is available, usual merge is used, swap merging otherwise.
+//
+// As a last step, if auxiliary memory is available in-place merge is performed.
+// until all is merged or auxiliary memory is not large enough.
+template<class RandIt, class Compare, class XBuf>
+typename iterator_traits<RandIt>::size_type
+ adaptive_sort_build_blocks
+ ( RandIt const first
+ , typename iterator_traits<RandIt>::size_type const len
+ , typename iterator_traits<RandIt>::size_type const l_base
+ , typename iterator_traits<RandIt>::size_type const l_build_buf
+ , XBuf & xbuf
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ BOOST_ASSERT(l_build_buf <= len);
+ BOOST_ASSERT(0 == ((l_build_buf / l_base)&(l_build_buf/l_base-1)));
+
+ //Place the start pointer after the buffer
+ RandIt first_block = first + l_build_buf;
+ size_type const elements_in_blocks = len - l_build_buf;
+
+ //////////////////////////////////
+ // Start of merge to left step
+ //////////////////////////////////
+ size_type l_merged = 0u;
+
+ BOOST_ASSERT(l_build_buf);
+ //If there is no enough buffer for the insertion sort step, just avoid the external buffer
+ size_type kbuf = min_value<size_type>(l_build_buf, size_type(xbuf.capacity()));
+ kbuf = kbuf < l_base ? 0 : kbuf;
+
+ if(kbuf){
+ //Backup internal buffer values in external buffer so they can be overwritten
+ xbuf.move_assign(first+l_build_buf-kbuf, kbuf);
+ l_merged = op_insertion_sort_step_left(first_block, elements_in_blocks, l_base, comp, move_op());
+
+ //Now combine them using the buffer. Elements from buffer can be
+ //overwritten since they've been saved to xbuf
+ l_merged = op_merge_left_step_multiple
+ ( first_block - l_merged, elements_in_blocks, l_merged, l_build_buf, kbuf - l_merged, comp, move_op());
+
+ //Restore internal buffer from external buffer unless kbuf was l_build_buf,
+ //in that case restoration will happen later
+ if(kbuf != l_build_buf){
+ boost::move(xbuf.data()+kbuf-l_merged, xbuf.data() + kbuf, first_block-l_merged+elements_in_blocks);
+ }
+ }
+ else{
+ l_merged = insertion_sort_step(first_block, elements_in_blocks, l_base, comp);
+ rotate_gcd(first_block - l_merged, first_block, first_block+elements_in_blocks);
+ }
+
+ //Now combine elements using the buffer. Elements from buffer can't be
+ //overwritten since xbuf was not big enough, so merge swapping elements.
+ l_merged = op_merge_left_step_multiple
+ (first_block - l_merged, elements_in_blocks, l_merged, l_build_buf, l_build_buf - l_merged, comp, swap_op());
+
+ BOOST_ASSERT(l_merged == l_build_buf);
+
+ //////////////////////////////////
+ // Start of merge to right step
+ //////////////////////////////////
+
+ //If kbuf is l_build_buf then we can merge right without swapping
+ //Saved data is still in xbuf
+ if(kbuf && kbuf == l_build_buf){
+ op_merge_right_step_once(first, elements_in_blocks, l_build_buf, comp, move_op());
+ //Restore internal buffer from external buffer if kbuf was l_build_buf.
+ //as this operation was previously delayed.
+ boost::move(xbuf.data(), xbuf.data() + kbuf, first);
+ }
+ else{
+ op_merge_right_step_once(first, elements_in_blocks, l_build_buf, comp, swap_op());
+ }
+ xbuf.clear();
+ //2*l_build_buf or total already merged
+ return min_value(elements_in_blocks, 2*l_build_buf);
+}
+
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class XBuf>
+void adaptive_sort_combine_blocks
+ ( RandItKeys const keys
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const len
+ , typename iterator_traits<RandIt>::size_type const l_prev_merged
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , bool const use_buf
+ , bool const xbuf_used
+ , XBuf & xbuf
+ , Compare comp
+ , bool merge_left)
+{
+ (void)xbuf;
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ size_type const l_reg_combined = 2*l_prev_merged;
+ size_type l_irreg_combined = 0;
+ size_type const l_total_combined = calculate_total_combined(len, l_prev_merged, &l_irreg_combined);
+ size_type const n_reg_combined = len/l_reg_combined;
+ RandIt combined_first = first;
+
+ (void)l_total_combined;
+ BOOST_ASSERT(l_total_combined <= len);
+
+ size_type const max_i = n_reg_combined + (l_irreg_combined != 0);
+
+ if(merge_left || !use_buf) {
+ for( size_type combined_i = 0; combined_i != max_i; ++combined_i, combined_first += l_reg_combined) {
+ //Now merge blocks
+ bool const is_last = combined_i==n_reg_combined;
+ size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined;
+
+ range_xbuf<RandIt, move_op> rbuf( (use_buf && xbuf_used) ? (combined_first-l_block) : combined_first, combined_first);
+ size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
+ combine_params( keys, key_comp, l_cur_combined
+ , l_prev_merged, l_block, rbuf
+ , n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combpar: ", len + l_block);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp));
+ if(!use_buf){
+ merge_blocks_bufferless
+ (keys, key_comp, combined_first, l_block, 0u, n_block_a, n_block_b, l_irreg2, comp);
+ }
+ else{
+ merge_blocks_left
+ (keys, key_comp, combined_first, l_block, 0u, n_block_a, n_block_b, l_irreg2, comp, xbuf_used);
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" After merge_blocks_L: ", len + l_block);
+ }
+ }
+ else{
+ combined_first += l_reg_combined*(max_i-1);
+ for( size_type combined_i = max_i; combined_i--; combined_first -= l_reg_combined) {
+ bool const is_last = combined_i==n_reg_combined;
+ size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined;
+
+ RandIt const combined_last(combined_first+l_cur_combined);
+ range_xbuf<RandIt, move_op> rbuf(combined_last, xbuf_used ? (combined_last+l_block) : combined_last);
+ size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
+ combine_params( keys, key_comp, l_cur_combined
+ , l_prev_merged, l_block, rbuf
+ , n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combpar: ", len + l_block);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp));
+ merge_blocks_right
+ (keys, key_comp, combined_first, l_block, n_block_a, n_block_b, l_irreg2, comp, xbuf_used);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" After merge_blocks_R: ", len + l_block);
+ }
+ }
+}
+
+//Returns true if buffer is placed in
+//[buffer+len-l_intbuf, buffer+len). Otherwise, buffer is
+//[buffer,buffer+l_intbuf)
+template<class RandIt, class Compare, class XBuf>
+bool adaptive_sort_combine_all_blocks
+ ( RandIt keys
+ , typename iterator_traits<RandIt>::size_type &n_keys
+ , RandIt const buffer
+ , typename iterator_traits<RandIt>::size_type const l_buf_plus_data
+ , typename iterator_traits<RandIt>::size_type l_merged
+ , typename iterator_traits<RandIt>::size_type &l_intbuf
+ , XBuf & xbuf
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ RandIt const first = buffer + l_intbuf;
+ size_type const l_data = l_buf_plus_data - l_intbuf;
+ size_type const l_unique = l_intbuf+n_keys;
+ //Backup data to external buffer once if possible
+ bool const common_xbuf = l_data > l_merged && l_intbuf && l_intbuf <= xbuf.capacity();
+ if(common_xbuf){
+ xbuf.move_assign(buffer, l_intbuf);
+ }
+
+ bool prev_merge_left = true;
+ size_type l_prev_total_combined = l_merged, l_prev_block = 0;
+ bool prev_use_internal_buf = true;
+
+ for( size_type n = 0; l_data > l_merged
+ ; l_merged*=2
+ , ++n){
+ //If l_intbuf is non-zero, use that internal buffer.
+ // Implies l_block == l_intbuf && use_internal_buf == true
+ //If l_intbuf is zero, see if half keys can be reused as a reduced emergency buffer,
+ // Implies l_block == n_keys/2 && use_internal_buf == true
+ //Otherwise, just give up and and use all keys to merge using rotations (use_internal_buf = false)
+ bool use_internal_buf = false;
+ size_type const l_block = lblock_for_combine(l_intbuf, n_keys, 2*l_merged, use_internal_buf);
+ BOOST_ASSERT(!l_intbuf || (l_block == l_intbuf));
+ BOOST_ASSERT(n == 0 || (!use_internal_buf || prev_use_internal_buf) );
+ BOOST_ASSERT(n == 0 || (!use_internal_buf || l_prev_block == l_block) );
+
+ bool const is_merge_left = (n&1) == 0;
+ size_type const l_total_combined = calculate_total_combined(l_data, l_merged);
+ if(n && prev_use_internal_buf && prev_merge_left){
+ if(is_merge_left || !use_internal_buf){
+ move_data_backward(first-l_prev_block, l_prev_total_combined, first, common_xbuf);
+ }
+ else{
+ //Put the buffer just after l_total_combined
+ RandIt const buf_end = first+l_prev_total_combined;
+ RandIt const buf_beg = buf_end-l_block;
+ if(l_prev_total_combined > l_total_combined){
+ size_type const l_diff = l_prev_total_combined - l_total_combined;
+ move_data_backward(buf_beg-l_diff, l_diff, buf_end-l_diff, common_xbuf);
+ }
+ else if(l_prev_total_combined < l_total_combined){
+ size_type const l_diff = l_total_combined - l_prev_total_combined;
+ move_data_forward(buf_end, l_diff, buf_beg, common_xbuf);
+ }
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" After move_data : ", l_data + l_intbuf);
+ }
+
+ //Combine to form l_merged*2 segments
+ if(n_keys){
+ size_type upper_n_keys_this_iter = 2*l_merged/l_block;
+ if(upper_n_keys_this_iter > 256){
+ adaptive_sort_combine_blocks
+ ( keys, comp, !use_internal_buf || is_merge_left ? first : first-l_block
+ , l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
+ }
+ else{
+ unsigned char uint_keys[256];
+ adaptive_sort_combine_blocks
+ ( uint_keys, less(), !use_internal_buf || is_merge_left ? first : first-l_block
+ , l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
+ }
+ }
+ else{
+ size_type *const uint_keys = xbuf.template aligned_trailing<size_type>();
+ adaptive_sort_combine_blocks
+ ( uint_keys, less(), !use_internal_buf || is_merge_left ? first : first-l_block
+ , l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
+ }
+
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(is_merge_left ? " After comb blocks L: " : " After comb blocks R: ", l_data + l_intbuf);
+ prev_merge_left = is_merge_left;
+ l_prev_total_combined = l_total_combined;
+ l_prev_block = l_block;
+ prev_use_internal_buf = use_internal_buf;
+ }
+ BOOST_ASSERT(l_prev_total_combined == l_data);
+ bool const buffer_right = prev_use_internal_buf && prev_merge_left;
+
+ l_intbuf = prev_use_internal_buf ? l_prev_block : 0u;
+ n_keys = l_unique - l_intbuf;
+ //Restore data from to external common buffer if used
+ if(common_xbuf){
+ if(buffer_right){
+ boost::move(xbuf.data(), xbuf.data() + l_intbuf, buffer+l_data);
+ }
+ else{
+ boost::move(xbuf.data(), xbuf.data() + l_intbuf, buffer);
+ }
+ }
+ return buffer_right;
+}
+
+
+template<class RandIt, class Compare, class XBuf>
+void adaptive_sort_final_merge( bool buffer_right
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_intbuf
+ , typename iterator_traits<RandIt>::size_type const n_keys
+ , typename iterator_traits<RandIt>::size_type const len
+ , XBuf & xbuf
+ , Compare comp)
+{
+ //BOOST_ASSERT(n_keys || xbuf.size() == l_intbuf);
+ xbuf.clear();
+
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const n_key_plus_buf = l_intbuf+n_keys;
+ if(buffer_right){
+ //Use stable sort as some buffer elements might not be unique (see non_unique_buf)
+ stable_sort(first+len-l_intbuf, first+len, comp, xbuf);
+ stable_merge(first+n_keys, first+len-l_intbuf, first+len, antistable<Compare>(comp), xbuf);
+ unstable_sort(first, first+n_keys, comp, xbuf);
+ stable_merge(first, first+n_keys, first+len, comp, xbuf);
+ }
+ else{
+ //Use stable sort as some buffer elements might not be unique (see non_unique_buf)
+ stable_sort(first, first+n_key_plus_buf, comp, xbuf);
+ if(xbuf.capacity() >= n_key_plus_buf){
+ buffered_merge(first, first+n_key_plus_buf, first+len, comp, xbuf);
+ }
+ else if(xbuf.capacity() >= min_value<size_type>(l_intbuf, n_keys)){
+ stable_merge(first+n_keys, first+n_key_plus_buf, first+len, comp, xbuf);
+ stable_merge(first, first+n_keys, first+len, comp, xbuf);
+ }
+ else{
+ stable_merge(first, first+n_key_plus_buf, first+len, comp, xbuf);
+ }
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" After final_merge : ", len);
+}
+
+template<class RandIt, class Compare, class Unsigned, class XBuf>
+bool adaptive_sort_build_params
+ (RandIt first, Unsigned const len, Compare comp
+ , Unsigned &n_keys, Unsigned &l_intbuf, Unsigned &l_base, Unsigned &l_build_buf
+ , XBuf & xbuf
+ )
+{
+ typedef Unsigned size_type;
+
+ //Calculate ideal parameters and try to collect needed unique keys
+ l_base = 0u;
+
+ //Try to find a value near sqrt(len) that is 2^N*l_base where
+ //l_base <= AdaptiveSortInsertionSortThreshold. This property is important
+ //as build_blocks merges to the left iteratively duplicating the
+ //merged size and all the buffer must be used just before the final
+ //merge to right step. This guarantees "build_blocks" produces
+ //segments of size l_build_buf*2, maximizing the classic merge phase.
+ l_intbuf = size_type(ceil_sqrt_multiple(len, &l_base));
+
+ //The internal buffer can be expanded if there is enough external memory
+ while(xbuf.capacity() >= l_intbuf*2){
+ l_intbuf *= 2;
+ }
+
+ //This is the minimum number of keys to implement the ideal algorithm
+ //
+ //l_intbuf is used as buffer plus the key count
+ size_type n_min_ideal_keys = l_intbuf-1;
+ while(n_min_ideal_keys >= (len-l_intbuf-n_min_ideal_keys)/l_intbuf){
+ --n_min_ideal_keys;
+ }
+ n_min_ideal_keys += 1;
+ BOOST_ASSERT(n_min_ideal_keys <= l_intbuf);
+
+ if(xbuf.template supports_aligned_trailing<size_type>(l_intbuf, (len-l_intbuf-1)/l_intbuf+1)){
+ n_keys = 0u;
+ l_build_buf = l_intbuf;
+ }
+ else{
+ //Try to achieve a l_build_buf of length l_intbuf*2, so that we can merge with that
+ //l_intbuf*2 buffer in "build_blocks" and use half of them as buffer and the other half
+ //as keys in combine_all_blocks. In that case n_keys >= n_min_ideal_keys but by a small margin.
+ //
+ //If available memory is 2*sqrt(l), then only sqrt(l) unique keys are needed,
+ //(to be used for keys in combine_all_blocks) as the whole l_build_buf
+ //will be backuped in the buffer during build_blocks.
+ bool const non_unique_buf = xbuf.capacity() >= l_intbuf;
+ size_type const to_collect = non_unique_buf ? n_min_ideal_keys : l_intbuf*2;
+ size_type collected = collect_unique(first, first+len, to_collect, comp, xbuf);
+
+ //If available memory is 2*sqrt(l), then for "build_params"
+ //the situation is the same as if 2*l_intbuf were collected.
+ if(non_unique_buf && collected == n_min_ideal_keys){
+ l_build_buf = l_intbuf;
+ n_keys = n_min_ideal_keys;
+ }
+ else if(collected == 2*l_intbuf){
+ //l_intbuf*2 elements found. Use all of them in the build phase
+ l_build_buf = l_intbuf*2;
+ n_keys = l_intbuf;
+ }
+ else if(collected == (n_min_ideal_keys+l_intbuf)){
+ l_build_buf = l_intbuf;
+ n_keys = n_min_ideal_keys;
+ }
+ //If collected keys are not enough, try to fix n_keys and l_intbuf. If no fix
+ //is possible (due to very low unique keys), then go to a slow sort based on rotations.
+ else{
+ BOOST_ASSERT(collected < (n_min_ideal_keys+l_intbuf));
+ if(collected < 4){ //No combination possible with less that 4 keys
+ return false;
+ }
+ n_keys = l_intbuf;
+ while(n_keys&(n_keys-1)){
+ n_keys &= n_keys-1; // make it power or 2
+ }
+ while(n_keys > collected){
+ n_keys/=2;
+ }
+ //AdaptiveSortInsertionSortThreshold is always power of two so the minimum is power of two
+ l_base = min_value<Unsigned>(n_keys, AdaptiveSortInsertionSortThreshold);
+ l_intbuf = 0;
+ l_build_buf = n_keys;
+ }
+ BOOST_ASSERT((n_keys+l_intbuf) >= l_build_buf);
+ }
+
+ return true;
+}
+
+// Main explanation of the sort algorithm.
+//
+// csqrtlen = ceil(sqrt(len));
+//
+// * First, 2*csqrtlen unique elements elements are extracted from elements to be
+// sorted and placed in the beginning of the range.
+//
+// * Step "build_blocks": In this nearly-classic merge step, 2*csqrtlen unique elements
+// will be used as auxiliary memory, so trailing len-2*csqrtlen elements are
+// are grouped in blocks of sorted 4*csqrtlen elements. At the end of the step
+// 2*csqrtlen unique elements are again the leading elements of the whole range.
+//
+// * Step "combine_blocks": pairs of previously formed blocks are merged with a different
+// ("smart") algorithm to form blocks of 8*csqrtlen elements. This step is slower than the
+// "build_blocks" step and repeated iteratively (forming blocks of 16*csqrtlen, 32*csqrtlen
+// elements, etc) of until all trailing (len-2*csqrtlen) elements are merged.
+//
+// In "combine_blocks" len/csqrtlen elements used are as "keys" (markers) to
+// know if elements belong to the first or second block to be merged and another
+// leading csqrtlen elements are used as buffer. Explanation of the "combine_blocks" step:
+//
+// Iteratively until all trailing (len-2*csqrtlen) elements are merged:
+// Iteratively for each pair of previously merged block:
+// * Blocks are divided groups of csqrtlen elements and
+// 2*merged_block/csqrtlen keys are sorted to be used as markers
+// * Groups are selection-sorted by first or last element (depending whether they are going
+// to be merged to left or right) and keys are reordered accordingly as an imitation-buffer.
+// * Elements of each block pair are merged using the csqrtlen buffer taking into account
+// if they belong to the first half or second half (marked by the key).
+//
+// * In the final merge step leading elements (2*csqrtlen) are sorted and merged with
+// rotations with the rest of sorted elements in the "combine_blocks" step.
+//
+// Corner cases:
+//
+// * If no 2*csqrtlen elements can be extracted:
+//
+// * If csqrtlen+len/csqrtlen are extracted, then only csqrtlen elements are used
+// as buffer in the "build_blocks" step forming blocks of 2*csqrtlen elements. This
+// means that an additional "combine_blocks" step will be needed to merge all elements.
+//
+// * If no csqrtlen+len/csqrtlen elements can be extracted, but still more than a minimum,
+// then reduces the number of elements used as buffer and keys in the "build_blocks"
+// and "combine_blocks" steps. If "combine_blocks" has no enough keys due to this reduction
+// then uses a rotation based smart merge.
+//
+// * If the minimum number of keys can't be extracted, a rotation-based sorting is performed.
+//
+// * If auxiliary memory is more or equal than ceil(len/2), half-copying mergesort is used.
+//
+// * If auxiliary memory is more than csqrtlen+n_keys*sizeof(std::size_t),
+// then only csqrtlen elements need to be extracted and "combine_blocks" will use integral
+// keys to combine blocks.
+//
+// * If auxiliary memory is available, the "build_blocks" will be extended to build bigger blocks
+// using classic merge and "combine_blocks" will use bigger blocks when merging.
+template<class RandIt, class Compare, class XBuf>
+void adaptive_sort_impl
+ ( RandIt first
+ , typename iterator_traits<RandIt>::size_type const len
+ , Compare comp
+ , XBuf & xbuf
+ )
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ //Small sorts go directly to insertion sort
+ if(len <= size_type(AdaptiveSortInsertionSortThreshold)){
+ insertion_sort(first, first + len, comp);
+ }
+ else if((len-len/2) <= xbuf.capacity()){
+ merge_sort(first, first+len, comp, xbuf.data());
+ }
+ else{
+ //Make sure it is at least four
+ BOOST_STATIC_ASSERT(AdaptiveSortInsertionSortThreshold >= 4);
+
+ size_type l_base = 0;
+ size_type l_intbuf = 0;
+ size_type n_keys = 0;
+ size_type l_build_buf = 0;
+
+ //Calculate and extract needed unique elements. If a minimum is not achieved
+ //fallback to a slow stable sort
+ if(!adaptive_sort_build_params(first, len, comp, n_keys, l_intbuf, l_base, l_build_buf, xbuf)){
+ stable_sort(first, first+len, comp, xbuf);
+ }
+ else{
+ BOOST_ASSERT(l_build_buf);
+ //Otherwise, continue the adaptive_sort
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1("\n After collect_unique: ", len);
+ size_type const n_key_plus_buf = l_intbuf+n_keys;
+ //l_build_buf is always power of two if l_intbuf is zero
+ BOOST_ASSERT(l_intbuf || (0 == (l_build_buf & (l_build_buf-1))));
+
+ //Classic merge sort until internal buffer and xbuf are exhausted
+ size_type const l_merged = adaptive_sort_build_blocks
+ (first+n_key_plus_buf-l_build_buf, len-n_key_plus_buf+l_build_buf, l_base, l_build_buf, xbuf, comp);
+ BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(" After build_blocks: ", len);
+
+ //Non-trivial merge
+ bool const buffer_right = adaptive_sort_combine_all_blocks
+ (first, n_keys, first+n_keys, len-n_keys, l_merged, l_intbuf, xbuf, comp);
+
+ //Sort keys and buffer and merge the whole sequence
+ adaptive_sort_final_merge(buffer_right, first, l_intbuf, n_keys, len, xbuf, comp);
+ }
+ }
+}
+
+} //namespace detail_adaptive {
+
+///@endcond
+
+//! <b>Effects</b>: Sorts the elements in the range [first, last) in ascending order according
+//! to comparison functor "comp". The sort is stable (order of equal elements
+//! is guaranteed to be preserved). Performance is improved if additional raw storage is
+//! provided.
+//!
+//! <b>Requires</b>:
+//! - RandIt must meet the requirements of ValueSwappable and RandomAccessIterator.
+//! - The type of dereferenced RandIt must meet the requirements of MoveAssignable and MoveConstructible.
+//!
+//! <b>Parameters</b>:
+//! - first, last: the range of elements to sort
+//! - comp: comparison function object which returns true if the first argument is is ordered before the second.
+//! - uninitialized, uninitialized_len: raw storage starting on "uninitialized", able to hold "uninitialized_len"
+//! elements of type iterator_traits<RandIt>::value_type. Maximum performance is achieved when uninitialized_len
+//! is ceil(std::distance(first, last)/2).
+//!
+//! <b>Throws</b>: If comp throws or the move constructor, move assignment or swap of the type
+//! of dereferenced RandIt throws.
+//!
+//! <b>Complexity</b>: Always K x O(Nxlog(N)) comparisons and move assignments/constructors/swaps.
+//! Comparisons are close to minimum even with no additional memory. Constant factor for data movement is minimized
+//! when uninitialized_len is ceil(std::distance(first, last)/2). Pretty good enough performance is achieved when
+//! ceil(sqrt(std::distance(first, last)))*2.
+//!
+//! <b>Caution</b>: Experimental implementation, not production-ready.
+template<class RandIt, class RandRawIt, class Compare>
+void adaptive_sort( RandIt first, RandIt last, Compare comp
+ , RandRawIt uninitialized
+ , std::size_t uninitialized_len)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ ::boost::movelib::detail_adaptive::adaptive_xbuf<value_type, RandRawIt> xbuf(uninitialized, uninitialized_len);
+ ::boost::movelib::detail_adaptive::adaptive_sort_impl(first, size_type(last - first), comp, xbuf);
+}
+
+template<class RandIt, class Compare>
+void adaptive_sort( RandIt first, RandIt last, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+ adaptive_sort(first, last, comp, (value_type*)0, 0u);
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#define BOOST_MOVE_ADAPTIVE_SORT_HPP
diff --git a/include/boost/move/algo/detail/adaptive_sort_merge.hpp b/include/boost/move/algo/detail/adaptive_sort_merge.hpp
new file mode 100644
index 0000000..4c28086
--- /dev/null
+++ b/include/boost/move/algo/detail/adaptive_sort_merge.hpp
@@ -0,0 +1,1690 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Stable sorting that works in O(N*log(N)) worst time
+// and uses O(1) extra memory
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// The main idea of the adaptive_sort algorithm was developed by Andrey Astrelin
+// and explained in the article from the russian collaborative blog
+// Habrahabr (http://habrahabr.ru/post/205290/). The algorithm is based on
+// ideas from B-C. Huang and M. A. Langston explained in their article
+// "Fast Stable Merging and Sorting in Constant Extra Space (1989-1992)"
+// (http://comjnl.oxfordjournals.org/content/35/6/643.full.pdf).
+//
+// This implementation by Ion Gaztanaga uses previous ideas with additional changes:
+//
+// - Use of GCD-based rotation.
+// - Non power of two buffer-sizes.
+// - Tries to find sqrt(len)*2 unique keys, so that the merge sort
+// phase can form up to sqrt(len)*4 segments if enough keys are found.
+// - The merge-sort phase can take advantage of external memory to
+// save some additional combination steps.
+// - Combination phase: Blocks are selection sorted and merged in parallel.
+// - The combination phase is performed alternating merge to left and merge
+// to right phases minimizing swaps due to internal buffer repositioning.
+// - When merging blocks special optimizations are made to avoid moving some
+// elements twice.
+//
+// The adaptive_merge algorithm was developed by Ion Gaztanaga reusing some parts
+// from the sorting algorithm and implementing an additional block merge algorithm
+// without moving elements to left or right.
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
+#define BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/reverse_iterator.hpp>
+#include <boost/move/algo/move.hpp>
+#include <boost/move/algo/detail/merge.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/algo/detail/insertion_sort.hpp>
+#include <boost/move/algo/detail/merge_sort.hpp>
+#include <boost/move/algo/detail/heap_sort.hpp>
+#include <boost/move/algo/detail/merge.hpp>
+#include <boost/move/algo/detail/is_sorted.hpp>
+#include <boost/assert.hpp>
+#include <boost/cstdint.hpp>
+
+#ifndef BOOST_MOVE_ADAPTIVE_SORT_STATS_LEVEL
+ #define BOOST_MOVE_ADAPTIVE_SORT_STATS_LEVEL 1
+#endif
+
+#ifdef BOOST_MOVE_ADAPTIVE_SORT_STATS
+ #if BOOST_MOVE_ADAPTIVE_SORT_STATS_LEVEL == 2
+ #define BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(STR, L) \
+ print_stats(STR, L)\
+ //
+
+ #define BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(STR, L) \
+ print_stats(STR, L)\
+ //
+ #else
+ #define BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(STR, L) \
+ print_stats(STR, L)\
+ //
+
+ #define BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(STR, L)
+ #endif
+#else
+ #define BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1(STR, L)
+ #define BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(STR, L)
+#endif
+
+#ifdef BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
+ #define BOOST_MOVE_ADAPTIVE_SORT_INVARIANT BOOST_ASSERT
+#else
+ #define BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(L)
+#endif
+
+namespace boost {
+namespace movelib {
+
+#if defined(BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS)
+
+bool is_sorted(::order_perf_type *first, ::order_perf_type *last, ::order_type_less)
+{
+ if (first != last) {
+ const order_perf_type *next = first, *cur(first);
+ while (++next != last) {
+ if (!(cur->key < next->key || (cur->key == next->key && cur->val < next->val)))
+ return false;
+ cur = next;
+ }
+ }
+ return true;
+}
+
+#endif //BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
+
+namespace detail_adaptive {
+
+static const std::size_t AdaptiveSortInsertionSortThreshold = 16;
+//static const std::size_t AdaptiveSortInsertionSortThreshold = 4;
+BOOST_STATIC_ASSERT((AdaptiveSortInsertionSortThreshold&(AdaptiveSortInsertionSortThreshold-1)) == 0);
+
+#if defined BOOST_HAS_INTPTR_T
+ typedef ::boost::uintptr_t uintptr_t;
+#else
+ typedef std::size_t uintptr_t;
+#endif
+
+template<class T>
+const T &min_value(const T &a, const T &b)
+{
+ return a < b ? a : b;
+}
+
+template<class T>
+const T &max_value(const T &a, const T &b)
+{
+ return a > b ? a : b;
+}
+
+template<class ForwardIt, class Pred, class V>
+typename iterator_traits<ForwardIt>::size_type
+ count_if_with(ForwardIt first, ForwardIt last, Pred pred, const V &v)
+{
+ typedef typename iterator_traits<ForwardIt>::size_type size_type;
+ size_type count = 0;
+ while(first != last) {
+ count += static_cast<size_type>(0 != pred(*first, v));
+ ++first;
+ }
+ return count;
+}
+
+template<class T, class RandRawIt = T*>
+class adaptive_xbuf
+{
+ adaptive_xbuf(const adaptive_xbuf &);
+ adaptive_xbuf & operator=(const adaptive_xbuf &);
+
+ public:
+ typedef RandRawIt iterator;
+
+ adaptive_xbuf()
+ : m_ptr(), m_size(0), m_capacity(0)
+ {}
+
+ adaptive_xbuf(RandRawIt raw_memory, std::size_t capacity)
+ : m_ptr(raw_memory), m_size(0), m_capacity(capacity)
+ {}
+
+ template<class RandIt>
+ void move_assign(RandIt first, std::size_t n)
+ {
+ if(n <= m_size){
+ boost::move(first, first+n, m_ptr);
+ std::size_t size = m_size;
+ while(size-- != n){
+ m_ptr[size].~T();
+ }
+ m_size = n;
+ }
+ else{
+ RandRawIt result = boost::move(first, first+m_size, m_ptr);
+ boost::uninitialized_move(first+m_size, first+n, result);
+ m_size = n;
+ }
+ }
+
+ template<class RandIt>
+ void push_back(RandIt first, std::size_t n)
+ {
+ BOOST_ASSERT(m_capacity - m_size >= n);
+ boost::uninitialized_move(first, first+n, m_ptr+m_size);
+ m_size += n;
+ }
+
+ template<class RandIt>
+ iterator add(RandIt it)
+ {
+ BOOST_ASSERT(m_size < m_capacity);
+ RandRawIt p_ret = m_ptr + m_size;
+ ::new(&*p_ret) T(::boost::move(*it));
+ ++m_size;
+ return p_ret;
+ }
+
+ template<class RandIt>
+ void insert(iterator pos, RandIt it)
+ {
+ if(pos == (m_ptr + m_size)){
+ this->add(it);
+ }
+ else{
+ this->add(m_ptr+m_size-1);
+ //m_size updated
+ boost::move_backward(pos, m_ptr+m_size-2, m_ptr+m_size-1);
+ *pos = boost::move(*it);
+ }
+ }
+
+ void set_size(std::size_t size)
+ {
+ m_size = size;
+ }
+
+ void shrink_to_fit(std::size_t const size)
+ {
+ if(m_size > size){
+ for(std::size_t szt_i = size; szt_i != m_size; ++szt_i){
+ m_ptr[szt_i].~T();
+ }
+ m_size = size;
+ }
+ }
+
+ void initialize_until(std::size_t const size, T &t)
+ {
+ BOOST_ASSERT(m_size < m_capacity);
+ if(m_size < size){
+ ::new((void*)&m_ptr[m_size]) T(::boost::move(t));
+ ++m_size;
+ for(; m_size != size; ++m_size){
+ ::new((void*)&m_ptr[m_size]) T(::boost::move(m_ptr[m_size-1]));
+ }
+ t = ::boost::move(m_ptr[m_size-1]);
+ }
+ }
+
+ private:
+ template<class RIt>
+ static bool is_raw_ptr(RIt)
+ {
+ return false;
+ }
+
+ static bool is_raw_ptr(T*)
+ {
+ return true;
+ }
+
+ public:
+ template<class U>
+ bool supports_aligned_trailing(std::size_t size, std::size_t trail_count) const
+ {
+ if(this->is_raw_ptr(this->data()) && m_capacity){
+ uintptr_t u_addr_sz = uintptr_t(&*(this->data()+size));
+ uintptr_t u_addr_cp = uintptr_t(&*(this->data()+this->capacity()));
+ u_addr_sz = ((u_addr_sz + sizeof(U)-1)/sizeof(U))*sizeof(U);
+ return (u_addr_cp >= u_addr_sz) && ((u_addr_cp - u_addr_sz)/sizeof(U) >= trail_count);
+ }
+ return false;
+ }
+
+ template<class U>
+ U *aligned_trailing() const
+ {
+ return this->aligned_trailing<U>(this->size());
+ }
+
+ template<class U>
+ U *aligned_trailing(std::size_t pos) const
+ {
+ uintptr_t u_addr = uintptr_t(&*(this->data()+pos));
+ u_addr = ((u_addr + sizeof(U)-1)/sizeof(U))*sizeof(U);
+ return (U*)u_addr;
+ }
+
+ ~adaptive_xbuf()
+ {
+ this->clear();
+ }
+
+ std::size_t capacity() const
+ { return m_capacity; }
+
+ iterator data() const
+ { return m_ptr; }
+
+ iterator end() const
+ { return m_ptr+m_size; }
+
+ std::size_t size() const
+ { return m_size; }
+
+ bool empty() const
+ { return !m_size; }
+
+ void clear()
+ {
+ this->shrink_to_fit(0u);
+ }
+
+ private:
+ RandRawIt m_ptr;
+ std::size_t m_size;
+ std::size_t m_capacity;
+};
+
+template<class Iterator, class Op>
+class range_xbuf
+{
+ range_xbuf(const range_xbuf &);
+ range_xbuf & operator=(const range_xbuf &);
+
+ public:
+ typedef typename iterator_traits<Iterator>::size_type size_type;
+ typedef Iterator iterator;
+
+ range_xbuf(Iterator first, Iterator last)
+ : m_first(first), m_last(first), m_cap(last)
+ {}
+
+ template<class RandIt>
+ void move_assign(RandIt first, std::size_t n)
+ {
+ BOOST_ASSERT(size_type(n) <= size_type(m_cap-m_first));
+ m_last = Op()(forward_t(), first, first+n, m_first);
+ }
+
+ ~range_xbuf()
+ {}
+
+ std::size_t capacity() const
+ { return m_cap-m_first; }
+
+ Iterator data() const
+ { return m_first; }
+
+ Iterator end() const
+ { return m_last; }
+
+ std::size_t size() const
+ { return m_last-m_first; }
+
+ bool empty() const
+ { return m_first == m_last; }
+
+ void clear()
+ {
+ m_last = m_first;
+ }
+
+ template<class RandIt>
+ iterator add(RandIt it)
+ {
+ Iterator pos(m_last);
+ *pos = boost::move(*it);
+ ++m_last;
+ return pos;
+ }
+
+ void set_size(std::size_t size)
+ {
+ m_last = m_first;
+ m_last += size;
+ }
+
+ private:
+ Iterator const m_first;
+ Iterator m_last;
+ Iterator const m_cap;
+};
+
+
+template<class RandIt, class Compare>
+RandIt skip_until_merge
+ ( RandIt first1, RandIt const last1
+ , const typename iterator_traits<RandIt>::value_type &next_key, Compare comp)
+{
+ while(first1 != last1 && !comp(next_key, *first1)){
+ ++first1;
+ }
+ return first1;
+}
+
+
+template<class RandItKeys, class RandIt>
+void swap_and_update_key
+ ( RandItKeys const key_next
+ , RandItKeys const key_range2
+ , RandItKeys &key_mid
+ , RandIt const begin
+ , RandIt const end
+ , RandIt const with)
+{
+ if(begin != with){
+ ::boost::adl_move_swap_ranges(begin, end, with);
+ ::boost::adl_move_swap(*key_next, *key_range2);
+ if(key_next == key_mid){
+ key_mid = key_range2;
+ }
+ else if(key_mid == key_range2){
+ key_mid = key_next;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// MERGE BUFFERLESS
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// [first1, last1) merge [last1,last2) -> [first1,last2)
+template<class RandIt, class Compare>
+RandIt partial_merge_bufferless_impl
+ (RandIt first1, RandIt last1, RandIt const last2, bool *const pis_range1_A, Compare comp)
+{
+ if(last1 == last2){
+ return first1;
+ }
+ bool const is_range1_A = *pis_range1_A;
+ if(first1 != last1 && comp(*last1, last1[-1])){
+ do{
+ RandIt const old_last1 = last1;
+ last1 = boost::movelib::lower_bound(last1, last2, *first1, comp);
+ first1 = rotate_gcd(first1, old_last1, last1);//old_last1 == last1 supported
+ if(last1 == last2){
+ return first1;
+ }
+ do{
+ ++first1;
+ } while(last1 != first1 && !comp(*last1, *first1) );
+ } while(first1 != last1);
+ }
+ *pis_range1_A = !is_range1_A;
+ return last1;
+}
+
+// [first1, last1) merge [last1,last2) -> [first1,last2)
+template<class RandIt, class Compare>
+RandIt partial_merge_bufferless
+ (RandIt first1, RandIt last1, RandIt const last2, bool *const pis_range1_A, Compare comp)
+{
+ return *pis_range1_A ? partial_merge_bufferless_impl(first1, last1, last2, pis_range1_A, comp)
+ : partial_merge_bufferless_impl(first1, last1, last2, pis_range1_A, antistable<Compare>(comp));
+}
+
+template<class SizeType>
+static SizeType needed_keys_count(SizeType n_block_a, SizeType n_block_b)
+{
+ return n_block_a + n_block_b;
+}
+
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+typename iterator_traits<RandIt>::size_type
+ find_next_block
+ ( RandItKeys key_first
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const ix_first_block
+ , typename iterator_traits<RandIt>::size_type const ix_last_block
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+ typedef typename iterator_traits<RandItKeys>::value_type key_type;
+ BOOST_ASSERT(ix_first_block <= ix_last_block);
+ size_type ix_min_block = 0u;
+ for (size_type szt_i = ix_first_block; szt_i < ix_last_block; ++szt_i) {
+ const value_type &min_val = first[ix_min_block*l_block];
+ const value_type &cur_val = first[szt_i*l_block];
+ const key_type &min_key = key_first[ix_min_block];
+ const key_type &cur_key = key_first[szt_i];
+
+ bool const less_than_minimum = comp(cur_val, min_val) ||
+ (!comp(min_val, cur_val) && key_comp(cur_key, min_key));
+
+ if (less_than_minimum) {
+ ix_min_block = szt_i;
+ }
+ }
+ return ix_min_block;
+}
+
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+void merge_blocks_bufferless
+ ( RandItKeys key_first
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const l_irreg1
+ , typename iterator_traits<RandIt>::size_type const n_block_a
+ , typename iterator_traits<RandIt>::size_type const n_block_b
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const key_count = needed_keys_count(n_block_a, n_block_b); (void)key_count;
+ //BOOST_ASSERT(n_block_a || n_block_b);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted_and_unique(key_first, key_first + key_count, key_comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + key_count, key_comp, key_first[n_block_a]));
+
+ size_type n_bef_irreg2 = 0;
+ bool l_irreg_pos_count = true;
+ RandItKeys key_mid(key_first + n_block_a);
+ RandIt const first_irr2 = first + l_irreg1 + (n_block_a+n_block_b)*l_block;
+ RandIt const last_irr2 = first_irr2 + l_irreg2;
+
+ { //Selection sort blocks
+ size_type n_block_left = n_block_b + n_block_a;
+ RandItKeys key_range2(key_first);
+
+ size_type min_check = n_block_a == n_block_left ? 0u : n_block_a;
+ size_type max_check = min_value(min_check+1, n_block_left);
+ for (RandIt f = first+l_irreg1; n_block_left; --n_block_left, ++key_range2, f += l_block, min_check -= min_check != 0, max_check -= max_check != 0) {
+ size_type const next_key_idx = find_next_block(key_range2, key_comp, f, l_block, min_check, max_check, comp);
+ RandItKeys const key_next(key_range2 + next_key_idx);
+ max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left);
+
+ RandIt const first_min = f + next_key_idx*l_block;
+
+ //Check if irregular b block should go here.
+ //If so, break to the special code handling the irregular block
+ if (l_irreg_pos_count && l_irreg2 && comp(*first_irr2, *first_min)){
+ l_irreg_pos_count = false;
+ }
+ n_bef_irreg2 += l_irreg_pos_count;
+
+ swap_and_update_key(key_next, key_range2, key_mid, f, f + l_block, first_min);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(f, f+l_block, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_min, first_min + l_block, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((f == (first+l_irreg1)) || !comp(*f, *(f-l_block)));
+ }
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first+l_irreg1+n_bef_irreg2*l_block, first_irr2, comp));
+
+ RandIt first1 = first;
+ RandIt last1 = first+l_irreg1;
+ RandItKeys const key_end (key_first+n_bef_irreg2);
+ bool is_range1_A = true;
+
+ for( ; key_first != key_end; ++key_first){
+ bool is_range2_A = key_mid == (key_first+key_count) || key_comp(*key_first, *key_mid);
+ first1 = is_range1_A == is_range2_A
+ ? last1 : partial_merge_bufferless(first1, last1, last1 + l_block, &is_range1_A, comp);
+ last1 += l_block;
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, first1, comp));
+ }
+
+ merge_bufferless(is_range1_A ? first1 : last1, first_irr2, last_irr2, comp);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, last_irr2, comp));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// BUFFERED MERGE
+//
+///////////////////////////////////////////////////////////////////////////////
+template<class RandIt, class Compare, class Op, class Buf>
+void op_buffered_merge
+ ( RandIt first, RandIt const middle, RandIt last
+ , Compare comp, Op op
+ , Buf &xbuf)
+{
+ if(first != middle && middle != last && comp(*middle, middle[-1])){
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const len1 = size_type(middle-first);
+ size_type const len2 = size_type(last-middle);
+ if(len1 <= len2){
+ first = boost::movelib::upper_bound(first, middle, *middle, comp);
+ xbuf.move_assign(first, size_type(middle-first));
+ op_merge_with_right_placed
+ (xbuf.data(), xbuf.end(), first, middle, last, comp, op);
+ }
+ else{
+ last = boost::movelib::lower_bound(middle, last, middle[-1], comp);
+ xbuf.move_assign(middle, size_type(last-middle));
+ op_merge_with_left_placed
+ (first, middle, last, xbuf.data(), xbuf.end(), comp, op);
+ }
+ }
+}
+
+template<class RandIt, class Compare, class XBuf>
+void buffered_merge
+ ( RandIt first, RandIt const middle, RandIt last
+ , Compare comp
+ , XBuf &xbuf)
+{
+ op_buffered_merge(first, middle, last, comp, move_op(), xbuf);
+}
+
+// Complexity: 2*distance(first, last)+max_collected^2/2
+//
+// Tries to collect at most n_keys unique elements from [first, last),
+// in the begining of the range, and ordered according to comp
+//
+// Returns the number of collected keys
+template<class RandIt, class Compare, class XBuf>
+typename iterator_traits<RandIt>::size_type
+ collect_unique
+ ( RandIt const first, RandIt const last
+ , typename iterator_traits<RandIt>::size_type const max_collected, Compare comp
+ , XBuf & xbuf)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type h = 0;
+ if(max_collected){
+ ++h; // first key is always here
+ RandIt h0 = first;
+ RandIt u = first; ++u;
+ RandIt search_end = u;
+
+ if(xbuf.capacity() >= max_collected){
+ typename XBuf::iterator const ph0 = xbuf.add(first);
+ while(u != last && h < max_collected){
+ typename XBuf::iterator const r = boost::movelib::lower_bound(ph0, xbuf.end(), *u, comp);
+ //If key not found add it to [h, h+h0)
+ if(r == xbuf.end() || comp(*u, *r) ){
+ RandIt const new_h0 = boost::move(search_end, u, h0);
+ search_end = u;
+ ++search_end;
+ ++h;
+ xbuf.insert(r, u);
+ h0 = new_h0;
+ }
+ ++u;
+ }
+ boost::move_backward(first, h0, h0+h);
+ boost::move(xbuf.data(), xbuf.end(), first);
+ }
+ else{
+ while(u != last && h < max_collected){
+ RandIt const r = boost::movelib::lower_bound(h0, search_end, *u, comp);
+ //If key not found add it to [h, h+h0)
+ if(r == search_end || comp(*u, *r) ){
+ RandIt const new_h0 = rotate_gcd(h0, search_end, u);
+ search_end = u;
+ ++search_end;
+ ++h;
+ rotate_gcd(r+(new_h0-h0), u, search_end);
+ h0 = new_h0;
+ }
+ ++u;
+ }
+ rotate_gcd(first, h0, h0+h);
+ }
+ }
+ return h;
+}
+
+template<class Unsigned>
+Unsigned floor_sqrt(Unsigned const n)
+{
+ Unsigned x = n;
+ Unsigned y = x/2 + (x&1);
+ while (y < x){
+ x = y;
+ y = (x + n / x)/2;
+ }
+ return x;
+}
+
+template<class Unsigned>
+Unsigned ceil_sqrt(Unsigned const n)
+{
+ Unsigned r = floor_sqrt(n);
+ return r + Unsigned((n%r) != 0);
+}
+
+template<class Unsigned>
+Unsigned floor_merge_multiple(Unsigned const n, Unsigned &base, Unsigned &pow)
+{
+ Unsigned s = n;
+ Unsigned p = 0;
+ while(s > AdaptiveSortInsertionSortThreshold){
+ s /= 2;
+ ++p;
+ }
+ base = s;
+ pow = p;
+ return s << p;
+}
+
+template<class Unsigned>
+Unsigned ceil_merge_multiple(Unsigned const n, Unsigned &base, Unsigned &pow)
+{
+ Unsigned fm = floor_merge_multiple(n, base, pow);
+
+ if(fm != n){
+ if(base < AdaptiveSortInsertionSortThreshold){
+ ++base;
+ }
+ else{
+ base = AdaptiveSortInsertionSortThreshold/2 + 1;
+ ++pow;
+ }
+ }
+ return base << pow;
+}
+
+template<class Unsigned>
+Unsigned ceil_sqrt_multiple(Unsigned const n, Unsigned *pbase = 0)
+{
+ Unsigned const r = ceil_sqrt(n);
+ Unsigned pow = 0;
+ Unsigned base = 0;
+ Unsigned const res = ceil_merge_multiple(r, base, pow);
+ if(pbase) *pbase = base;
+ return res;
+}
+
+struct less
+{
+ template<class T>
+ bool operator()(const T &l, const T &r)
+ { return l < r; }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// MERGE BLOCKS
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//#define ADAPTIVE_SORT_MERGE_SLOW_STABLE_SORT_IS_NLOGN
+
+#if defined ADAPTIVE_SORT_MERGE_SLOW_STABLE_SORT_IS_NLOGN
+template<class RandIt, class Compare>
+void slow_stable_sort
+ ( RandIt const first, RandIt const last, Compare comp)
+{
+ boost::movelib::inplace_stable_sort(first, last, comp);
+}
+
+#else //ADAPTIVE_SORT_MERGE_SLOW_STABLE_SORT_IS_NLOGN
+
+template<class RandIt, class Compare>
+void slow_stable_sort
+ ( RandIt const first, RandIt const last, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type L = size_type(last - first);
+ { //Use insertion sort to merge first elements
+ size_type m = 0;
+ while((L - m) > size_type(AdaptiveSortInsertionSortThreshold)){
+ insertion_sort(first+m, first+m+size_type(AdaptiveSortInsertionSortThreshold), comp);
+ m += AdaptiveSortInsertionSortThreshold;
+ }
+ insertion_sort(first+m, last, comp);
+ }
+
+ size_type h = AdaptiveSortInsertionSortThreshold;
+ for(bool do_merge = L > h; do_merge; h*=2){
+ do_merge = (L - h) > h;
+ size_type p0 = 0;
+ if(do_merge){
+ size_type const h_2 = 2*h;
+ while((L-p0) > h_2){
+ merge_bufferless(first+p0, first+p0+h, first+p0+h_2, comp);
+ p0 += h_2;
+ }
+ }
+ if((L-p0) > h){
+ merge_bufferless(first+p0, first+p0+h, last, comp);
+ }
+ }
+}
+
+#endif //ADAPTIVE_SORT_MERGE_SLOW_STABLE_SORT_IS_NLOGN
+
+//Returns new l_block and updates use_buf
+template<class Unsigned>
+Unsigned lblock_for_combine
+ (Unsigned const l_block, Unsigned const n_keys, Unsigned const l_data, bool &use_buf)
+{
+ BOOST_ASSERT(l_data > 1);
+
+ //We need to guarantee lblock >= l_merged/(n_keys/2) keys for the combination.
+ //We have at least 4 keys guaranteed (which are the minimum to merge 2 ranges)
+ //If l_block != 0, then n_keys is already enough to merge all blocks in all
+ //phases as we've found all needed keys for that buffer and length before.
+ //If l_block == 0 then see if half keys can be used as buffer and the rest
+ //as keys guaranteeing that n_keys >= (2*l_merged)/lblock =
+ if(!l_block){
+ //If l_block == 0 then n_keys is power of two
+ //(guaranteed by build_params(...))
+ BOOST_ASSERT(n_keys >= 4);
+ //BOOST_ASSERT(0 == (n_keys &(n_keys-1)));
+
+ //See if half keys are at least 4 and if half keys fulfill
+ Unsigned const new_buf = n_keys/2;
+ Unsigned const new_keys = n_keys-new_buf;
+ use_buf = new_keys >= 4 && new_keys >= l_data/new_buf;
+ if(use_buf){
+ return new_buf;
+ }
+ else{
+ return l_data/n_keys;
+ }
+ }
+ else{
+ use_buf = true;
+ return l_block;
+ }
+}
+
+template<class RandIt, class Compare, class XBuf>
+void stable_sort( RandIt first, RandIt last, Compare comp, XBuf & xbuf)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const len = size_type(last - first);
+ size_type const half_len = len/2 + (len&1);
+ if(std::size_t(xbuf.capacity() - xbuf.size()) >= half_len) {
+ merge_sort(first, last, comp, xbuf.data()+xbuf.size());
+ }
+ else{
+ slow_stable_sort(first, last, comp);
+ }
+}
+
+template<class RandIt, class Comp, class XBuf>
+void unstable_sort( RandIt first, RandIt last
+ , Comp comp
+ , XBuf & xbuf)
+{
+ heap_sort(first, last, comp);(void)xbuf;
+}
+
+template<class RandIt, class Compare, class XBuf>
+void stable_merge
+ ( RandIt first, RandIt const middle, RandIt last
+ , Compare comp
+ , XBuf &xbuf)
+{
+ BOOST_ASSERT(xbuf.empty());
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const len1 = size_type(middle-first);
+ size_type const len2 = size_type(last-middle);
+ size_type const l_min = min_value(len1, len2);
+ if(xbuf.capacity() >= l_min){
+ buffered_merge(first, middle, last, comp, xbuf);
+ xbuf.clear();
+ }
+ else{
+ merge_bufferless(first, middle, last, comp);
+ }
+}
+
+template<class RandIt, class Comp, class XBuf>
+void initialize_keys( RandIt first, RandIt last
+ , Comp comp
+ , XBuf & xbuf)
+{
+ unstable_sort(first, last, comp, xbuf);
+ BOOST_ASSERT(boost::movelib::is_sorted_and_unique(first, last, comp));
+}
+
+template<class RandIt, class U>
+void initialize_keys( RandIt first, RandIt last
+ , less
+ , U &)
+{
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+ std::size_t count = std::size_t(last - first);
+ for(std::size_t i = 0; i != count; ++i){
+ *first = static_cast<value_type>(i);
+ ++first;
+ }
+}
+
+template <class Unsigned>
+Unsigned calculate_total_combined(Unsigned const len, Unsigned const l_prev_merged, Unsigned *pl_irreg_combined = 0)
+{
+ typedef Unsigned size_type;
+
+ size_type const l_combined = 2*l_prev_merged;
+ size_type l_irreg_combined = len%l_combined;
+ size_type l_total_combined = len;
+ if(l_irreg_combined <= l_prev_merged){
+ l_total_combined -= l_irreg_combined;
+ l_irreg_combined = 0;
+ }
+ if(pl_irreg_combined)
+ *pl_irreg_combined = l_irreg_combined;
+ return l_total_combined;
+}
+
+template<class RandItKeys, class KeyCompare, class SizeType, class XBuf>
+void combine_params
+ ( RandItKeys const keys
+ , KeyCompare key_comp
+ , SizeType l_combined
+ , SizeType const l_prev_merged
+ , SizeType const l_block
+ , XBuf & xbuf
+ //Output
+ , SizeType &n_block_a
+ , SizeType &n_block_b
+ , SizeType &l_irreg1
+ , SizeType &l_irreg2
+ //Options
+ , bool do_initialize_keys = true)
+{
+ typedef SizeType size_type;
+
+ //Initial parameters for selection sort blocks
+ l_irreg1 = l_prev_merged%l_block;
+ l_irreg2 = (l_combined-l_irreg1)%l_block;
+ BOOST_ASSERT(((l_combined-l_irreg1-l_irreg2)%l_block) == 0);
+ size_type const n_reg_block = (l_combined-l_irreg1-l_irreg2)/l_block;
+ n_block_a = l_prev_merged/l_block;
+ n_block_b = n_reg_block - n_block_a;
+ BOOST_ASSERT(n_reg_block>=n_block_a);
+
+ //Key initialization
+ if (do_initialize_keys) {
+ initialize_keys(keys, keys + needed_keys_count(n_block_a, n_block_b), key_comp, xbuf);
+ }
+}
+
+
+
+//////////////////////////////////
+//
+// partial_merge
+//
+//////////////////////////////////
+template<class InputIt1, class InputIt2, class OutputIt, class Compare, class Op>
+OutputIt op_partial_merge_impl
+ (InputIt1 &r_first1, InputIt1 const last1, InputIt2 &r_first2, InputIt2 const last2, OutputIt d_first, Compare comp, Op op)
+{
+ InputIt1 first1(r_first1);
+ InputIt2 first2(r_first2);
+ if(first2 != last2 && last1 != first1)
+ while(1){
+ if(comp(*first2, *first1)) {
+ op(first2++, d_first++);
+ if(first2 == last2){
+ break;
+ }
+ }
+ else{
+ op(first1++, d_first++);
+ if(first1 == last1){
+ break;
+ }
+ }
+ }
+ r_first1 = first1;
+ r_first2 = first2;
+ return d_first;
+}
+
+template<class InputIt1, class InputIt2, class OutputIt, class Compare, class Op>
+OutputIt op_partial_merge
+ (InputIt1 &r_first1, InputIt1 const last1, InputIt2 &r_first2, InputIt2 const last2, OutputIt d_first, Compare comp, Op op, bool is_stable)
+{
+ return is_stable ? op_partial_merge_impl(r_first1, last1, r_first2, last2, d_first, comp, op)
+ : op_partial_merge_impl(r_first1, last1, r_first2, last2, d_first, antistable<Compare>(comp), op);
+}
+
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+//
+// op_partial_merge_and_save
+//
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+template<class InputIt1, class InputIt2, class OutputIt, class Compare, class Op>
+OutputIt op_partial_merge_and_swap_impl
+ (InputIt1 &r_first1, InputIt1 const last1, InputIt2 &r_first2, InputIt2 const last2, InputIt2 &r_first_min, OutputIt d_first, Compare comp, Op op)
+{
+ InputIt1 first1(r_first1);
+ InputIt2 first2(r_first2);
+
+ if(first2 != last2 && last1 != first1) {
+ InputIt2 first_min(r_first_min);
+ bool non_empty_ranges = true;
+ do{
+ if(comp(*first_min, *first1)) {
+ op(three_way_t(), first2++, first_min++, d_first++);
+ non_empty_ranges = first2 != last2;
+ }
+ else{
+ op(first1++, d_first++);
+ non_empty_ranges = first1 != last1;
+ }
+ } while(non_empty_ranges);
+ r_first_min = first_min;
+ r_first1 = first1;
+ r_first2 = first2;
+ }
+ return d_first;
+}
+
+template<class RandIt, class InputIt2, class OutputIt, class Compare, class Op>
+OutputIt op_partial_merge_and_swap
+ (RandIt &r_first1, RandIt const last1, InputIt2 &r_first2, InputIt2 const last2, InputIt2 &r_first_min, OutputIt d_first, Compare comp, Op op, bool is_stable)
+{
+ return is_stable ? op_partial_merge_and_swap_impl(r_first1, last1, r_first2, last2, r_first_min, d_first, comp, op)
+ : op_partial_merge_and_swap_impl(r_first1, last1, r_first2, last2, r_first_min, d_first, antistable<Compare>(comp), op);
+}
+
+template<class RandIt1, class RandIt2, class RandItB, class Compare, class Op>
+RandItB op_buffered_partial_merge_and_swap_to_range1_and_buffer
+ ( RandIt1 first1, RandIt1 const last1
+ , RandIt2 &rfirst2, RandIt2 const last2, RandIt2 &rfirst_min
+ , RandItB &rfirstb, Compare comp, Op op )
+{
+ RandItB firstb = rfirstb;
+ RandItB lastb = firstb;
+ RandIt2 first2 = rfirst2;
+
+ //Move to buffer while merging
+ //Three way moves need less moves when op is swap_op so use it
+ //when merging elements from range2 to the destination occupied by range1
+ if(first1 != last1 && first2 != last2){
+ RandIt2 first_min = rfirst_min;
+ op(four_way_t(), first2++, first_min++, first1++, lastb++);
+
+ while(first1 != last1){
+ if(first2 == last2){
+ lastb = op(forward_t(), first1, last1, firstb);
+ break;
+ }
+
+ if(comp(*first_min, *firstb)){
+ op( four_way_t(), first2++, first_min++, first1++, lastb++);
+ }
+ else{
+ op(three_way_t(), firstb++, first1++, lastb++);
+ }
+ }
+ rfirst2 = first2;
+ rfirstb = firstb;
+ rfirst_min = first_min;
+ }
+
+ return lastb;
+}
+
+template<class RandIt1, class RandIt2, class RandItB, class Compare, class Op>
+RandItB op_buffered_partial_merge_to_range1_and_buffer
+ ( RandIt1 first1, RandIt1 const last1
+ , RandIt2 &rfirst2, RandIt2 const last2
+ , RandItB &rfirstb, Compare comp, Op op )
+{
+ RandItB firstb = rfirstb;
+ RandItB lastb = firstb;
+ RandIt2 first2 = rfirst2;
+
+ //Move to buffer while merging
+ //Three way moves need less moves when op is swap_op so use it
+ //when merging elements from range2 to the destination occupied by range1
+ if(first1 != last1 && first2 != last2){
+ op(three_way_t(), first2++, first1++, lastb++);
+
+ while(true){
+ if(first1 == last1){
+ break;
+ }
+ if(first2 == last2){
+ lastb = op(forward_t(), first1, last1, firstb);
+ break;
+ }
+ if (comp(*first2, *firstb)) {
+ op(three_way_t(), first2++, first1++, lastb++);
+ }
+ else {
+ op(three_way_t(), firstb++, first1++, lastb++);
+ }
+ }
+ rfirst2 = first2;
+ rfirstb = firstb;
+ }
+
+ return lastb;
+}
+
+template<class RandIt, class RandItBuf, class Compare, class Op>
+RandIt op_partial_merge_and_save_impl
+ ( RandIt first1, RandIt const last1, RandIt &rfirst2, RandIt last2, RandIt first_min
+ , RandItBuf &buf_first1_in_out, RandItBuf &buf_last1_in_out
+ , Compare comp, Op op
+ )
+{
+ RandItBuf buf_first1 = buf_first1_in_out;
+ RandItBuf buf_last1 = buf_last1_in_out;
+ RandIt first2(rfirst2);
+
+ bool const do_swap = first2 != first_min;
+ if(buf_first1 == buf_last1){
+ //Skip any element that does not need to be moved
+ RandIt new_first1 = skip_until_merge(first1, last1, *first_min, comp);
+ buf_first1 += (new_first1-first1);
+ first1 = new_first1;
+ buf_last1 = do_swap ? op_buffered_partial_merge_and_swap_to_range1_and_buffer(first1, last1, first2, last2, first_min, buf_first1, comp, op)
+ : op_buffered_partial_merge_to_range1_and_buffer (first1, last1, first2, last2, buf_first1, comp, op);
+ first1 = last1;
+ }
+ else{
+ BOOST_ASSERT((last1-first1) == (buf_last1 - buf_first1));
+ }
+
+ //Now merge from buffer
+ first1 = do_swap ? op_partial_merge_and_swap_impl(buf_first1, buf_last1, first2, last2, first_min, first1, comp, op)
+ : op_partial_merge_impl (buf_first1, buf_last1, first2, last2, first1, comp, op);
+ buf_first1_in_out = buf_first1;
+ buf_last1_in_out = buf_last1;
+ rfirst2 = first2;
+ return first1;
+}
+
+template<class RandIt, class RandItBuf, class Compare, class Op>
+RandIt op_partial_merge_and_save
+ ( RandIt first1, RandIt const last1, RandIt &rfirst2, RandIt last2, RandIt first_min
+ , RandItBuf &buf_first1_in_out
+ , RandItBuf &buf_last1_in_out
+ , Compare comp
+ , Op op
+ , bool is_stable)
+{
+ return is_stable
+ ? op_partial_merge_and_save_impl
+ (first1, last1, rfirst2, last2, first_min, buf_first1_in_out, buf_last1_in_out, comp, op)
+ : op_partial_merge_and_save_impl
+ (first1, last1, rfirst2, last2, first_min, buf_first1_in_out, buf_last1_in_out, antistable<Compare>(comp), op)
+ ;
+}
+
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+//
+// op_merge_blocks_with_irreg
+//
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+
+template<class RandItKeys, class KeyCompare, class RandIt, class RandIt2, class OutputIt, class Compare, class Op>
+OutputIt op_merge_blocks_with_irreg
+ ( RandItKeys key_first
+ , RandItKeys key_mid
+ , KeyCompare key_comp
+ , RandIt first_reg
+ , RandIt2 &first_irr
+ , RandIt2 const last_irr
+ , OutputIt dest
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type n_block_left
+ , typename iterator_traits<RandIt>::size_type min_check
+ , typename iterator_traits<RandIt>::size_type max_check
+ , Compare comp, bool const is_stable, Op op)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ for(; n_block_left; --n_block_left, ++key_first, min_check -= min_check != 0, max_check -= max_check != 0){
+ size_type next_key_idx = find_next_block(key_first, key_comp, first_reg, l_block, min_check, max_check, comp);
+ max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left);
+ RandIt const last_reg = first_reg + l_block;
+ RandIt first_min = first_reg + next_key_idx*l_block;
+ RandIt const last_min = first_min + l_block; (void)last_min;
+
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_reg, last_reg, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!next_key_idx || is_sorted(first_min, last_min, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((!next_key_idx || !comp(*first_reg, *first_min )));
+
+ OutputIt orig_dest = dest; (void)orig_dest;
+ dest = next_key_idx ? op_partial_merge_and_swap(first_irr, last_irr, first_reg, last_reg, first_min, dest, comp, op, is_stable)
+ : op_partial_merge (first_irr, last_irr, first_reg, last_reg, dest, comp, op, is_stable);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(orig_dest, dest, comp));
+
+ if(first_reg == dest){
+ dest = next_key_idx ? ::boost::adl_move_swap_ranges(first_min, last_min, first_reg)
+ : last_reg;
+ }
+ else{
+ dest = next_key_idx ? op(three_way_forward_t(), first_reg, last_reg, first_min, dest)
+ : op(forward_t(), first_reg, last_reg, dest);
+ }
+
+ RandItKeys const key_next(key_first + next_key_idx);
+ swap_and_update_key(key_next, key_first, key_mid, last_reg, last_reg, first_min);
+
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(orig_dest, dest, comp));
+ first_reg = last_reg;
+ }
+ return dest;
+}
+
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+//
+// op_merge_blocks_left/right
+//
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class Op>
+void op_merge_blocks_left
+ ( RandItKeys const key_first
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const l_irreg1
+ , typename iterator_traits<RandIt>::size_type const n_block_a
+ , typename iterator_traits<RandIt>::size_type const n_block_b
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp, Op op)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const key_count = needed_keys_count(n_block_a, n_block_b); (void)key_count;
+// BOOST_ASSERT(n_block_a || n_block_b);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted_and_unique(key_first, key_first + key_count, key_comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + key_count, key_comp, key_first[n_block_a]));
+
+ size_type n_block_b_left = n_block_b;
+ size_type n_block_a_left = n_block_a;
+ size_type n_block_left = n_block_b + n_block_a;
+ RandItKeys key_mid(key_first + n_block_a);
+
+ RandIt buffer = first - l_block;
+ RandIt first1 = first;
+ RandIt last1 = first1 + l_irreg1;
+ RandIt first2 = last1;
+ RandIt const irreg2 = first2 + n_block_left*l_block;
+ bool is_range1_A = true;
+
+ RandItKeys key_range2(key_first);
+
+ ////////////////////////////////////////////////////////////////////////////
+ //Process all regular blocks before the irregular B block
+ ////////////////////////////////////////////////////////////////////////////
+ size_type min_check = n_block_a == n_block_left ? 0u : n_block_a;
+ size_type max_check = min_value(min_check+1, n_block_left);
+ for (; n_block_left; --n_block_left, ++key_range2, min_check -= min_check != 0, max_check -= max_check != 0) {
+ size_type const next_key_idx = find_next_block(key_range2, key_comp, first2, l_block, min_check, max_check, comp);
+ max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left);
+ RandIt const first_min = first2 + next_key_idx*l_block;
+ RandIt const last_min = first_min + l_block; (void)last_min;
+ RandIt const last2 = first2 + l_block;
+
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first1, last1, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first2, last2, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_left || is_sorted(first_min, last_min, comp));
+
+ //Check if irregular b block should go here.
+ //If so, break to the special code handling the irregular block
+ if (!n_block_b_left &&
+ ( (l_irreg2 && comp(*irreg2, *first_min)) || (!l_irreg2 && is_range1_A)) ){
+ break;
+ }
+
+ RandItKeys const key_next(key_range2 + next_key_idx);
+ bool const is_range2_A = key_mid == (key_first+key_count) || key_comp(*key_next, *key_mid);
+
+ bool const is_buffer_middle = last1 == buffer;
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT( ( is_buffer_middle && size_type(first2-buffer) == l_block && buffer == last1) ||
+ (!is_buffer_middle && size_type(first1-buffer) == l_block && first2 == last1));
+
+ if(is_range1_A == is_range2_A){
+ BOOST_ASSERT((first1 == last1) || !comp(*first_min, last1[-1]));
+ if(!is_buffer_middle){
+ buffer = op(forward_t(), first1, last1, buffer);
+ }
+ swap_and_update_key(key_next, key_range2, key_mid, first2, last2, first_min);
+ first1 = first2;
+ last1 = last2;
+ }
+ else {
+ RandIt unmerged;
+ RandIt buf_beg;
+ RandIt buf_end;
+ if(is_buffer_middle){
+ buf_end = buf_beg = first2 - (last1-first1);
+ unmerged = op_partial_merge_and_save( first1, last1, first2, last2, first_min
+ , buf_beg, buf_end, comp, op, is_range1_A);
+ }
+ else{
+ buf_beg = first1;
+ buf_end = last1;
+ unmerged = op_partial_merge_and_save
+ (buffer, buffer+(last1-first1), first2, last2, first_min, buf_beg, buf_end, comp, op, is_range1_A);
+ }
+ (void)unmerged;
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first-l_block, unmerged, comp));
+
+ swap_and_update_key( key_next, key_range2, key_mid, first2, last2
+ , last_min - size_type(last2 - first2));
+
+ if(buf_beg != buf_end){ //range2 exhausted: is_buffer_middle for the next iteration
+ first1 = buf_beg;
+ last1 = buf_end;
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(buf_end == (last2-l_block));
+ buffer = last1;
+ }
+ else{ //range1 exhausted: !is_buffer_middle for the next iteration
+ first1 = first2;
+ last1 = last2;
+ buffer = first2 - l_block;
+ is_range1_A = is_range2_A;
+ }
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT( (is_range2_A && n_block_a_left) || (!is_range2_A && n_block_b_left));
+ is_range2_A ? --n_block_a_left : --n_block_b_left;
+ first2 = last2;
+ }
+
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_range2 + n_block_left, key_comp, *key_mid));
+ BOOST_ASSERT(!n_block_b_left);
+
+ ////////////////////////////////////////////////////////////////////////////
+ //Process remaining range 1 left before the irregular B block
+ ////////////////////////////////////////////////////////////////////////////
+ bool const is_buffer_middle = last1 == buffer;
+ RandIt first_irr2 = irreg2;
+ RandIt const last_irr2 = first_irr2 + l_irreg2;
+ if(l_irreg2 && is_range1_A){
+ if(is_buffer_middle){
+ first1 = skip_until_merge(first1, last1, *first_irr2, comp);
+ //Even if we copy backward, no overlapping occurs so use forward copy
+ //that can be faster specially with trivial types
+ RandIt const new_first1 = first2 - (last1 - first1);
+ op(forward_t(), first1, last1, new_first1);
+ first1 = new_first1;
+ last1 = first2;
+ buffer = first1 - l_block;
+ }
+ buffer = op_partial_merge_impl(first1, last1, first_irr2, last_irr2, buffer, comp, op);
+ buffer = op(forward_t(), first1, last1, buffer);
+ }
+ else if(!is_buffer_middle){
+ buffer = op(forward_t(), first1, last1, buffer);
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first-l_block, buffer, comp));
+
+ ////////////////////////////////////////////////////////////////////////////
+ //Process irregular B block and remaining A blocks
+ ////////////////////////////////////////////////////////////////////////////
+ buffer = op_merge_blocks_with_irreg
+ ( key_range2, key_mid, key_comp, first2, first_irr2, last_irr2
+ , buffer, l_block, n_block_left, min_check, max_check, comp, false, op);
+ buffer = op(forward_t(), first_irr2, last_irr2, buffer);(void)buffer;
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first-l_block, buffer, comp));
+}
+
+// first - first element to merge.
+// first[-l_block, 0) - buffer (if use_buf == true)
+// l_block - length of regular blocks. First nblocks are stable sorted by 1st elements and key-coded
+// keys - sequence of keys, in same order as blocks. key<midkey means stream A
+// n_bef_irreg2/n_aft_irreg2 are regular blocks
+// l_irreg2 is a irregular block, that is to be combined after n_bef_irreg2 blocks and before n_aft_irreg2 blocks
+// If l_irreg2==0 then n_aft_irreg2==0 (no irregular blocks).
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+void merge_blocks_left
+ ( RandItKeys const key_first
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const l_irreg1
+ , typename iterator_traits<RandIt>::size_type const n_block_a
+ , typename iterator_traits<RandIt>::size_type const n_block_b
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp
+ , bool const xbuf_used)
+{
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + needed_keys_count(n_block_a, n_block_b), key_comp, key_first[n_block_a]));
+ if(xbuf_used){
+ op_merge_blocks_left
+ (key_first, key_comp, first, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, move_op());
+ }
+ else{
+ op_merge_blocks_left
+ (key_first, key_comp, first, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, swap_op());
+ }
+}
+
+// first - first element to merge.
+// [first+l_block*(n_bef_irreg2+n_aft_irreg2)+l_irreg2, first+l_block*(n_bef_irreg2+n_aft_irreg2+1)+l_irreg2) - buffer
+// l_block - length of regular blocks. First nblocks are stable sorted by 1st elements and key-coded
+// keys - sequence of keys, in same order as blocks. key<midkey means stream A
+// n_bef_irreg2/n_aft_irreg2 are regular blocks
+// l_irreg2 is a irregular block, that is to be combined after n_bef_irreg2 blocks and before n_aft_irreg2 blocks
+// If l_irreg2==0 then n_aft_irreg2==0 (no irregular blocks).
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
+void merge_blocks_right
+ ( RandItKeys const key_first
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const n_block_a
+ , typename iterator_traits<RandIt>::size_type const n_block_b
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp
+ , bool const xbuf_used)
+{
+ merge_blocks_left
+ ( (make_reverse_iterator)(key_first + needed_keys_count(n_block_a, n_block_b))
+ , inverse<KeyCompare>(key_comp)
+ , (make_reverse_iterator)(first + ((n_block_a+n_block_b)*l_block+l_irreg2))
+ , l_block
+ , l_irreg2
+ , n_block_b
+ , n_block_a
+ , 0
+ , inverse<Compare>(comp), xbuf_used);
+}
+
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+//
+// op_merge_blocks_with_buf
+//
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class Op, class RandItBuf>
+void op_merge_blocks_with_buf
+ ( RandItKeys key_first
+ , KeyCompare key_comp
+ , RandIt const first
+ , typename iterator_traits<RandIt>::size_type const l_block
+ , typename iterator_traits<RandIt>::size_type const l_irreg1
+ , typename iterator_traits<RandIt>::size_type const n_block_a
+ , typename iterator_traits<RandIt>::size_type const n_block_b
+ , typename iterator_traits<RandIt>::size_type const l_irreg2
+ , Compare comp
+ , Op op
+ , RandItBuf const buf_first)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const key_count = needed_keys_count(n_block_a, n_block_b); (void)key_count;
+ //BOOST_ASSERT(n_block_a || n_block_b);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted_and_unique(key_first, key_first + key_count, key_comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + key_count, key_comp, key_first[n_block_a]));
+
+ size_type n_block_b_left = n_block_b;
+ size_type n_block_a_left = n_block_a;
+ size_type n_block_left = n_block_b + n_block_a;
+ RandItKeys key_mid(key_first + n_block_a);
+
+ RandItBuf buffer = buf_first;
+ RandItBuf buffer_end = buffer;
+ RandIt first1 = first;
+ RandIt last1 = first1 + l_irreg1;
+ RandIt first2 = last1;
+ RandIt const first_irr2 = first2 + n_block_left*l_block;
+ bool is_range1_A = true;
+
+ RandItKeys key_range2(key_first);
+
+ ////////////////////////////////////////////////////////////////////////////
+ //Process all regular blocks before the irregular B block
+ ////////////////////////////////////////////////////////////////////////////
+ size_type min_check = n_block_a == n_block_left ? 0u : n_block_a;
+ size_type max_check = min_value(min_check+1, n_block_left);
+ for (; n_block_left; --n_block_left, ++key_range2, min_check -= min_check != 0, max_check -= max_check != 0) {
+ size_type const next_key_idx = find_next_block(key_range2, key_comp, first2, l_block, min_check, max_check, comp);
+ max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left);
+ RandIt first_min = first2 + next_key_idx*l_block;
+ RandIt const last_min = first_min + l_block; (void)last_min;
+ RandIt const last2 = first2 + l_block;
+
+ bool const buffer_empty = buffer == buffer_end; (void)buffer_empty;
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(buffer_empty ? is_sorted(first1, last1, comp) : is_sorted(buffer, buffer_end, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first2, last2, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_left || is_sorted(first_min, last_min, comp));
+
+ //Check if irregular b block should go here.
+ //If so, break to the special code handling the irregular block
+ if (!n_block_b_left &&
+ ( (l_irreg2 && comp(*first_irr2, *first_min)) || (!l_irreg2 && is_range1_A)) ){
+ break;
+ }
+
+ RandItKeys const key_next(key_range2 + next_key_idx);
+ bool const is_range2_A = key_mid == (key_first+key_count) || key_comp(*key_next, *key_mid);
+
+ if(is_range1_A == is_range2_A){
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((first1 == last1) || (buffer_empty ? !comp(*first_min, last1[-1]) : !comp(*first_min, buffer_end[-1])));
+ //If buffered, put those elements in place
+ RandIt res = op(forward_t(), buffer, buffer_end, first1);
+ buffer = buffer_end = buf_first;
+ BOOST_ASSERT(buffer_empty || res == last1); (void)res;
+ swap_and_update_key(key_next, key_range2, key_mid, first2, last2, first_min);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first2, last2, comp));
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_min, last_min, comp));
+ first1 = first2;
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, first1, comp));
+ }
+ else {
+ RandIt const unmerged = op_partial_merge_and_save(first1, last1, first2, last2, first_min, buffer, buffer_end, comp, op, is_range1_A);
+ bool const is_range_1_empty = buffer == buffer_end;
+ BOOST_ASSERT(is_range_1_empty || (buffer_end-buffer) == (last1+l_block-unmerged));
+ if(is_range_1_empty){
+ buffer = buffer_end = buf_first;
+ first_min = last_min - (last2 - first2);
+ }
+ else{
+ first_min = last_min;
+ }
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!is_range_1_empty || (last_min-first_min) == (last2-unmerged));
+ swap_and_update_key(key_next, key_range2, key_mid, first2, last2, first_min);
+
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_min, last_min, comp));
+ is_range1_A ^= is_range_1_empty;
+ first1 = unmerged;
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, unmerged, comp));
+ }
+ BOOST_ASSERT( (is_range2_A && n_block_a_left) || (!is_range2_A && n_block_b_left));
+ is_range2_A ? --n_block_a_left : --n_block_b_left;
+ last1 += l_block;
+ first2 = last2;
+ }
+
+ RandIt res = op(forward_t(), buffer, buffer_end, first1); (void)res;
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, res, comp));
+
+ ////////////////////////////////////////////////////////////////////////////
+ //Process irregular B block and remaining A blocks
+ ////////////////////////////////////////////////////////////////////////////
+ RandIt const last_irr2 = first_irr2 + l_irreg2;
+ op(forward_t(), first_irr2, first_irr2+l_irreg2, buf_first);
+ buffer = buf_first;
+ buffer_end = buffer+l_irreg2;
+
+ reverse_iterator<RandItBuf> rbuf_beg(buffer_end);
+ RandIt dest = op_merge_blocks_with_irreg
+ ((make_reverse_iterator)(key_first + n_block_b + n_block_a), (make_reverse_iterator)(key_mid), inverse<KeyCompare>(key_comp)
+ , (make_reverse_iterator)(first_irr2), rbuf_beg
+ , (make_reverse_iterator)(buffer), (make_reverse_iterator)(last_irr2)
+ , l_block, n_block_left, 0, n_block_left
+ , inverse<Compare>(comp), true, op).base();
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(dest, last_irr2, comp));
+
+ buffer_end = rbuf_beg.base();
+ BOOST_ASSERT((dest-last1) == (buffer_end-buffer));
+ op_merge_with_left_placed(is_range1_A ? first1 : last1, last1, dest, buffer, buffer_end, comp, op);
+
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, last_irr2, comp));
+}
+
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+//
+// op_insertion_sort_step_left/right
+//
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+
+template<class RandIt, class Compare, class Op>
+typename iterator_traits<RandIt>::size_type
+ op_insertion_sort_step_left
+ ( RandIt const first
+ , typename iterator_traits<RandIt>::size_type const length
+ , typename iterator_traits<RandIt>::size_type const step
+ , Compare comp, Op op)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const s = min_value<size_type>(step, AdaptiveSortInsertionSortThreshold);
+ size_type m = 0;
+
+ while((length - m) > s){
+ insertion_sort_op(first+m, first+m+s, first+m-s, comp, op);
+ m += s;
+ }
+ insertion_sort_op(first+m, first+length, first+m-s, comp, op);
+ return s;
+}
+
+template<class RandIt, class Compare, class Op>
+void op_merge_right_step_once
+ ( RandIt first_block
+ , typename iterator_traits<RandIt>::size_type const elements_in_blocks
+ , typename iterator_traits<RandIt>::size_type const l_build_buf
+ , Compare comp
+ , Op op)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type restk = elements_in_blocks%(2*l_build_buf);
+ size_type p = elements_in_blocks - restk;
+ BOOST_ASSERT(0 == (p%(2*l_build_buf)));
+
+ if(restk <= l_build_buf){
+ op(backward_t(),first_block+p, first_block+p+restk, first_block+p+restk+l_build_buf);
+ }
+ else{
+ op_merge_right(first_block+p, first_block+p+l_build_buf, first_block+p+restk, first_block+p+restk+l_build_buf, comp, op);
+ }
+ while(p>0){
+ p -= 2*l_build_buf;
+ op_merge_right(first_block+p, first_block+p+l_build_buf, first_block+p+2*l_build_buf, first_block+p+3*l_build_buf, comp, op);
+ }
+}
+
+
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+//
+// insertion_sort_step
+//
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+template<class RandIt, class Compare>
+typename iterator_traits<RandIt>::size_type
+ insertion_sort_step
+ ( RandIt const first
+ , typename iterator_traits<RandIt>::size_type const length
+ , typename iterator_traits<RandIt>::size_type const step
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ size_type const s = min_value<size_type>(step, AdaptiveSortInsertionSortThreshold);
+ size_type m = 0;
+
+ while((length - m) > s){
+ insertion_sort(first+m, first+m+s, comp);
+ m += s;
+ }
+ insertion_sort(first+m, first+length, comp);
+ return s;
+}
+
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+//
+// op_merge_left_step_multiple
+//
+//////////////////////////////////
+//////////////////////////////////
+//////////////////////////////////
+template<class RandIt, class Compare, class Op>
+typename iterator_traits<RandIt>::size_type
+ op_merge_left_step_multiple
+ ( RandIt first_block
+ , typename iterator_traits<RandIt>::size_type const elements_in_blocks
+ , typename iterator_traits<RandIt>::size_type l_merged
+ , typename iterator_traits<RandIt>::size_type const l_build_buf
+ , typename iterator_traits<RandIt>::size_type l_left_space
+ , Compare comp
+ , Op op)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ for(; l_merged < l_build_buf && l_left_space >= l_merged; l_merged*=2){
+ size_type p0=0;
+ RandIt pos = first_block;
+ while((elements_in_blocks - p0) > 2*l_merged) {
+ op_merge_left(pos-l_merged, pos, pos+l_merged, pos+2*l_merged, comp, op);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(pos-l_merged, pos+l_merged, comp));
+ p0 += 2*l_merged;
+ pos = first_block+p0;
+ }
+ if((elements_in_blocks-p0) > l_merged) {
+ op_merge_left(pos-l_merged, pos, pos+l_merged, first_block+elements_in_blocks, comp, op);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(pos-l_merged, pos-l_merged+(first_block+elements_in_blocks-pos), comp));
+ }
+ else {
+ op(forward_t(), pos, first_block+elements_in_blocks, pos-l_merged);
+ BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(pos-l_merged, first_block+elements_in_blocks-l_merged, comp));
+ }
+ first_block -= l_merged;
+ l_left_space -= l_merged;
+ }
+ return l_merged;
+}
+
+
+} //namespace detail_adaptive {
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#define BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
diff --git a/include/boost/move/algo/detail/basic_op.hpp b/include/boost/move/algo/detail/basic_op.hpp
new file mode 100644
index 0000000..ea5faf0
--- /dev/null
+++ b/include/boost/move/algo/detail/basic_op.hpp
@@ -0,0 +1,121 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ALGO_BASIC_OP
+#define BOOST_MOVE_ALGO_BASIC_OP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+
+namespace boost {
+namespace movelib {
+
+struct forward_t{};
+struct backward_t{};
+struct three_way_t{};
+struct three_way_forward_t{};
+struct four_way_t{};
+
+struct move_op
+{
+ template <class SourceIt, class DestinationIt>
+ BOOST_MOVE_FORCEINLINE void operator()(SourceIt source, DestinationIt dest)
+ { *dest = ::boost::move(*source); }
+
+ template <class SourceIt, class DestinationIt>
+ BOOST_MOVE_FORCEINLINE DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
+ { return ::boost::move(first, last, dest_begin); }
+
+ template <class SourceIt, class DestinationIt>
+ BOOST_MOVE_FORCEINLINE DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_last)
+ { return ::boost::move_backward(first, last, dest_last); }
+
+ template <class SourceIt, class DestinationIt1, class DestinationIt2>
+ BOOST_MOVE_FORCEINLINE void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
+ {
+ *dest2it = boost::move(*dest1it);
+ *dest1it = boost::move(*srcit);
+ }
+
+ template <class SourceIt, class DestinationIt1, class DestinationIt2>
+ DestinationIt2 operator()(three_way_forward_t, SourceIt srcit, SourceIt srcitend, DestinationIt1 dest1it, DestinationIt2 dest2it)
+ {
+ //Destination2 range can overlap SourceIt range so avoid boost::move
+ while(srcit != srcitend){
+ this->operator()(three_way_t(), srcit++, dest1it++, dest2it++);
+ }
+ return dest2it;
+ }
+
+ template <class SourceIt, class DestinationIt1, class DestinationIt2, class DestinationIt3>
+ BOOST_MOVE_FORCEINLINE void operator()(four_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it, DestinationIt3 dest3it)
+ {
+ *dest3it = boost::move(*dest2it);
+ *dest2it = boost::move(*dest1it);
+ *dest1it = boost::move(*srcit);
+ }
+};
+
+struct swap_op
+{
+ template <class SourceIt, class DestinationIt>
+ BOOST_MOVE_FORCEINLINE void operator()(SourceIt source, DestinationIt dest)
+ { boost::adl_move_swap(*dest, *source); }
+
+ template <class SourceIt, class DestinationIt>
+ BOOST_MOVE_FORCEINLINE DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
+ { return boost::adl_move_swap_ranges(first, last, dest_begin); }
+
+ template <class SourceIt, class DestinationIt>
+ BOOST_MOVE_FORCEINLINE DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
+ { return boost::adl_move_swap_ranges_backward(first, last, dest_begin); }
+
+ template <class SourceIt, class DestinationIt1, class DestinationIt2>
+ BOOST_MOVE_FORCEINLINE void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
+ {
+ typename ::boost::movelib::iterator_traits<SourceIt>::value_type tmp(boost::move(*dest2it));
+ *dest2it = boost::move(*dest1it);
+ *dest1it = boost::move(*srcit);
+ *srcit = boost::move(tmp);
+ }
+
+ template <class SourceIt, class DestinationIt1, class DestinationIt2>
+ DestinationIt2 operator()(three_way_forward_t, SourceIt srcit, SourceIt srcitend, DestinationIt1 dest1it, DestinationIt2 dest2it)
+ {
+ while(srcit != srcitend){
+ this->operator()(three_way_t(), srcit++, dest1it++, dest2it++);
+ }
+ return dest2it;
+ }
+
+ template <class SourceIt, class DestinationIt1, class DestinationIt2, class DestinationIt3>
+ BOOST_MOVE_FORCEINLINE void operator()(four_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it, DestinationIt3 dest3it)
+ {
+ typename ::boost::movelib::iterator_traits<SourceIt>::value_type tmp(boost::move(*dest3it));
+ *dest3it = boost::move(*dest2it);
+ *dest2it = boost::move(*dest1it);
+ *dest1it = boost::move(*srcit);
+ *srcit = boost::move(tmp);
+ }
+};
+
+
+}} //namespace boost::movelib
+
+#endif //BOOST_MOVE_ALGO_BASIC_OP
diff --git a/include/boost/move/algo/detail/heap_sort.hpp b/include/boost/move/algo/detail/heap_sort.hpp
new file mode 100644
index 0000000..5474d9f
--- /dev/null
+++ b/include/boost/move/algo/detail/heap_sort.hpp
@@ -0,0 +1,111 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2018.
+// 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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_HEAP_SORT_HPP
+#define BOOST_MOVE_DETAIL_HEAP_SORT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/algo/detail/is_sorted.hpp>
+#include <boost/move/utility_core.hpp>
+
+namespace boost { namespace movelib{
+
+template <class RandomAccessIterator, class Compare>
+class heap_sort_helper
+{
+ typedef typename boost::movelib::iterator_traits<RandomAccessIterator>::size_type size_type;
+ typedef typename boost::movelib::iterator_traits<RandomAccessIterator>::value_type value_type;
+
+ static void adjust_heap(RandomAccessIterator first, size_type hole_index, size_type const len, value_type &value, Compare comp)
+ {
+ size_type const top_index = hole_index;
+ size_type second_child = 2 * (hole_index + 1);
+
+ while (second_child < len) {
+ if (comp(*(first + second_child), *(first + (second_child - 1))))
+ second_child--;
+ *(first + hole_index) = boost::move(*(first + second_child));
+ hole_index = second_child;
+ second_child = 2 * (second_child + 1);
+ }
+ if (second_child == len) {
+ *(first + hole_index) = boost::move(*(first + (second_child - 1)));
+ hole_index = second_child - 1;
+ }
+
+ { //push_heap-like ending
+ size_type parent = (hole_index - 1) / 2;
+ while (hole_index > top_index && comp(*(first + parent), value)) {
+ *(first + hole_index) = boost::move(*(first + parent));
+ hole_index = parent;
+ parent = (hole_index - 1) / 2;
+ }
+ *(first + hole_index) = boost::move(value);
+ }
+ }
+
+ static void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+ {
+ size_type const len = size_type(last - first);
+ if (len > 1) {
+ size_type parent = len/2u - 1u;
+
+ do {
+ value_type v(boost::move(*(first + parent)));
+ adjust_heap(first, parent, len, v, comp);
+ }while (parent--);
+ }
+ }
+
+ static void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+ {
+ size_type len = size_type(last - first);
+ while (len > 1) {
+ //move biggest to the safe zone
+ --last;
+ value_type v(boost::move(*last));
+ *last = boost::move(*first);
+ adjust_heap(first, size_type(0), --len, v, comp);
+ }
+ }
+
+ public:
+ static void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+ {
+ make_heap(first, last, comp);
+ sort_heap(first, last, comp);
+ BOOST_ASSERT(boost::movelib::is_sorted(first, last, comp));
+ }
+};
+
+template <class RandomAccessIterator, class Compare>
+BOOST_MOVE_FORCEINLINE void heap_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+{
+ heap_sort_helper<RandomAccessIterator, Compare>::sort(first, last, comp);
+}
+
+}} //namespace boost { namespace movelib{
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_DETAIL_HEAP_SORT_HPP
diff --git a/include/boost/move/algo/detail/insertion_sort.hpp b/include/boost/move/algo/detail/insertion_sort.hpp
new file mode 100644
index 0000000..5c378c3
--- /dev/null
+++ b/include/boost/move/algo/detail/insertion_sort.hpp
@@ -0,0 +1,128 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_INSERT_SORT_HPP
+#define BOOST_MOVE_DETAIL_INSERT_SORT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/algo/move.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/placement_new.hpp>
+#include <boost/move/detail/destruct_n.hpp>
+#include <boost/move/algo/detail/basic_op.hpp>
+#include <boost/move/detail/placement_new.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
+
+namespace boost { namespace movelib{
+
+// @cond
+
+template <class Compare, class ForwardIterator, class BirdirectionalIterator, class Op>
+void insertion_sort_op(ForwardIterator first1, ForwardIterator last1, BirdirectionalIterator first2, Compare comp, Op op)
+{
+ if (first1 != last1){
+ BirdirectionalIterator last2 = first2;
+ op(first1, last2);
+ for (++last2; ++first1 != last1; ++last2){
+ BirdirectionalIterator j2 = last2;
+ BirdirectionalIterator i2 = j2;
+ if (comp(*first1, *--i2)){
+ op(i2, j2);
+ for (--j2; i2 != first2 && comp(*first1, *--i2); --j2) {
+ op(i2, j2);
+ }
+ }
+ op(first1, j2);
+ }
+ }
+}
+
+template <class Compare, class ForwardIterator, class BirdirectionalIterator>
+void insertion_sort_swap(ForwardIterator first1, ForwardIterator last1, BirdirectionalIterator first2, Compare comp)
+{
+ insertion_sort_op(first1, last1, first2, comp, swap_op());
+}
+
+
+template <class Compare, class ForwardIterator, class BirdirectionalIterator>
+void insertion_sort_copy(ForwardIterator first1, ForwardIterator last1, BirdirectionalIterator first2, Compare comp)
+{
+ insertion_sort_op(first1, last1, first2, comp, move_op());
+}
+
+// @endcond
+
+template <class Compare, class BirdirectionalIterator>
+void insertion_sort(BirdirectionalIterator first, BirdirectionalIterator last, Compare comp)
+{
+ typedef typename boost::movelib::iterator_traits<BirdirectionalIterator>::value_type value_type;
+ if (first != last){
+ BirdirectionalIterator i = first;
+ for (++i; i != last; ++i){
+ BirdirectionalIterator j = i;
+ if (comp(*i, *--j)) {
+ value_type tmp(::boost::move(*i));
+ *i = ::boost::move(*j);
+ for (BirdirectionalIterator k = j; k != first && comp(tmp, *--k); --j) {
+ *j = ::boost::move(*k);
+ }
+ *j = ::boost::move(tmp);
+ }
+ }
+ }
+}
+
+template <class Compare, class BirdirectionalIterator, class BirdirectionalRawIterator>
+void insertion_sort_uninitialized_copy
+ (BirdirectionalIterator first1, BirdirectionalIterator const last1
+ , BirdirectionalRawIterator const first2
+ , Compare comp)
+{
+ typedef typename iterator_traits<BirdirectionalIterator>::value_type value_type;
+ if (first1 != last1){
+ BirdirectionalRawIterator last2 = first2;
+ ::new((iterator_to_raw_pointer)(last2), boost_move_new_t()) value_type(::boost::move(*first1));
+ destruct_n<value_type, BirdirectionalRawIterator> d(first2);
+ d.incr();
+ for (++last2; ++first1 != last1; ++last2){
+ BirdirectionalRawIterator j2 = last2;
+ BirdirectionalRawIterator k2 = j2;
+ if (comp(*first1, *--k2)){
+ ::new((iterator_to_raw_pointer)(j2), boost_move_new_t()) value_type(::boost::move(*k2));
+ d.incr();
+ for (--j2; k2 != first2 && comp(*first1, *--k2); --j2)
+ *j2 = ::boost::move(*k2);
+ *j2 = ::boost::move(*first1);
+ }
+ else{
+ ::new((iterator_to_raw_pointer)(j2), boost_move_new_t()) value_type(::boost::move(*first1));
+ d.incr();
+ }
+ }
+ d.release();
+ }
+}
+
+}} //namespace boost { namespace movelib{
+
+#endif //#ifndef BOOST_MOVE_DETAIL_INSERT_SORT_HPP
diff --git a/include/boost/move/algo/detail/is_sorted.hpp b/include/boost/move/algo/detail/is_sorted.hpp
new file mode 100644
index 0000000..d3dccfc
--- /dev/null
+++ b/include/boost/move/algo/detail/is_sorted.hpp
@@ -0,0 +1,55 @@
+#ifndef BOOST_MOVE_DETAIL_IS_SORTED_HPP
+#define BOOST_MOVE_DETAIL_IS_SORTED_HPP
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2018. 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/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+namespace boost {
+namespace movelib {
+
+template<class ForwardIt, class Pred>
+bool is_sorted(ForwardIt const first, ForwardIt last, Pred pred)
+{
+ if (first != last) {
+ ForwardIt next = first, cur(first);
+ while (++next != last) {
+ if (pred(*next, *cur))
+ return false;
+ cur = next;
+ }
+ }
+ return true;
+}
+
+template<class ForwardIt, class Pred>
+bool is_sorted_and_unique(ForwardIt first, ForwardIt last, Pred pred)
+{
+ if (first != last) {
+ ForwardIt next = first;
+ while (++next != last) {
+ if (!pred(*first, *next))
+ return false;
+ first = next;
+ }
+ }
+ return true;
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#endif //BOOST_MOVE_DETAIL_IS_SORTED_HPP
diff --git a/include/boost/move/algo/detail/merge.hpp b/include/boost/move/algo/detail/merge.hpp
new file mode 100644
index 0000000..8607735
--- /dev/null
+++ b/include/boost/move/algo/detail/merge.hpp
@@ -0,0 +1,553 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_MERGE_HPP
+#define BOOST_MOVE_MERGE_HPP
+
+#include <boost/move/algo/move.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/algo/detail/basic_op.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/detail/destruct_n.hpp>
+#include <boost/move/algo/predicate.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace movelib {
+
+// @cond
+
+/*
+template<typename Unsigned>
+inline Unsigned gcd(Unsigned x, Unsigned y)
+{
+ if(0 == ((x &(x-1)) | (y & (y-1)))){
+ return x < y ? x : y;
+ }
+ else{
+ do
+ {
+ Unsigned t = x % y;
+ x = y;
+ y = t;
+ } while (y);
+ return x;
+ }
+}
+*/
+
+//Modified version from "An Optimal In-Place Array Rotation Algorithm", Ching-Kuang Shene
+template<typename Unsigned>
+Unsigned gcd(Unsigned x, Unsigned y)
+{
+ if(0 == ((x &(x-1)) | (y & (y-1)))){
+ return x < y ? x : y;
+ }
+ else{
+ Unsigned z = 1;
+ while((!(x&1)) & (!(y&1))){
+ z <<=1, x>>=1, y>>=1;
+ }
+ while(x && y){
+ if(!(x&1))
+ x >>=1;
+ else if(!(y&1))
+ y >>=1;
+ else if(x >=y)
+ x = (x-y) >> 1;
+ else
+ y = (y-x) >> 1;
+ }
+ return z*(x+y);
+ }
+}
+
+template<typename RandIt>
+RandIt rotate_gcd(RandIt first, RandIt middle, RandIt last)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ if(first == middle)
+ return last;
+ if(middle == last)
+ return first;
+ const size_type middle_pos = size_type(middle - first);
+ RandIt ret = last - middle_pos;
+ if (middle == ret){
+ boost::adl_move_swap_ranges(first, middle, middle);
+ }
+ else{
+ const size_type length = size_type(last - first);
+ for( RandIt it_i(first), it_gcd(it_i + gcd(length, middle_pos))
+ ; it_i != it_gcd
+ ; ++it_i){
+ value_type temp(boost::move(*it_i));
+ RandIt it_j = it_i;
+ RandIt it_k = it_j+middle_pos;
+ do{
+ *it_j = boost::move(*it_k);
+ it_j = it_k;
+ size_type const left = size_type(last - it_j);
+ it_k = left > middle_pos ? it_j + middle_pos : first + (middle_pos - left);
+ } while(it_k != it_i);
+ *it_j = boost::move(temp);
+ }
+ }
+ return ret;
+}
+
+template <class RandIt, class T, class Compare>
+RandIt lower_bound
+ (RandIt first, const RandIt last, const T& key, Compare comp)
+{
+ typedef typename iterator_traits
+ <RandIt>::size_type size_type;
+ size_type len = size_type(last - first);
+ RandIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += step;
+
+ if (comp(*middle, key)) {
+ first = ++middle;
+ len -= step + 1;
+ }
+ else{
+ len = step;
+ }
+ }
+ return first;
+}
+
+template <class RandIt, class T, class Compare>
+RandIt upper_bound
+ (RandIt first, const RandIt last, const T& key, Compare comp)
+{
+ typedef typename iterator_traits
+ <RandIt>::size_type size_type;
+ size_type len = size_type(last - first);
+ RandIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += step;
+
+ if (!comp(key, *middle)) {
+ first = ++middle;
+ len -= step + 1;
+ }
+ else{
+ len = step;
+ }
+ }
+ return first;
+}
+
+
+template<class RandIt, class Compare, class Op>
+void op_merge_left( RandIt buf_first
+ , RandIt first1
+ , RandIt const last1
+ , RandIt const last2
+ , Compare comp
+ , Op op)
+{
+ for(RandIt first2=last1; first2 != last2; ++buf_first){
+ if(first1 == last1){
+ op(forward_t(), first2, last2, buf_first);
+ return;
+ }
+ else if(comp(*first2, *first1)){
+ op(first2, buf_first);
+ ++first2;
+ }
+ else{
+ op(first1, buf_first);
+ ++first1;
+ }
+ }
+ if(buf_first != first1){//In case all remaining elements are in the same place
+ //(e.g. buffer is exactly the size of the second half
+ //and all elements from the second half are less)
+ op(forward_t(), first1, last1, buf_first);
+ }
+}
+
+// [buf_first, first1) -> buffer
+// [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
+// Elements from buffer are moved to [last2 - (first1-buf_first), last2)
+// Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
+template<class RandIt, class Compare>
+void merge_left
+ (RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
+{
+ op_merge_left(buf_first, first1, last1, last2, comp, move_op());
+}
+
+// [buf_first, first1) -> buffer
+// [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
+// Elements from buffer are swapped to [last2 - (first1-buf_first), last2)
+// Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
+template<class RandIt, class Compare>
+void swap_merge_left
+ (RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
+{
+ op_merge_left(buf_first, first1, last1, last2, comp, swap_op());
+}
+
+template<class RandIt, class Compare, class Op>
+void op_merge_right
+ (RandIt const first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp, Op op)
+{
+ RandIt const first2 = last1;
+ while(first1 != last1){
+ if(last2 == first2){
+ op(backward_t(), first1, last1, buf_last);
+ return;
+ }
+ --last2;
+ --last1;
+ --buf_last;
+ if(comp(*last2, *last1)){
+ op(last1, buf_last);
+ ++last2;
+ }
+ else{
+ op(last2, buf_last);
+ ++last1;
+ }
+ }
+ if(last2 != buf_last){ //In case all remaining elements are in the same place
+ //(e.g. buffer is exactly the size of the first half
+ //and all elements from the second half are less)
+ op(backward_t(), first2, last2, buf_last);
+ }
+}
+
+// [last2, buf_last) - buffer
+// [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
+// Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
+template<class RandIt, class Compare>
+void merge_right
+ (RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
+{
+ op_merge_right(first1, last1, last2, buf_last, comp, move_op());
+}
+
+// [last2, buf_last) - buffer
+// [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
+// Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
+template<class RandIt, class Compare>
+void swap_merge_right
+ (RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
+{
+ op_merge_right(first1, last1, last2, buf_last, comp, swap_op());
+}
+
+//Complexity: min(len1,len2)^2 + max(len1,len2)
+template<class RandIt, class Compare>
+void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp)
+{
+ if((middle - first) < (last - middle)){
+ while(first != middle){
+ RandIt const old_last1 = middle;
+ middle = boost::movelib::lower_bound(middle, last, *first, comp);
+ first = rotate_gcd(first, old_last1, middle);
+ if(middle == last){
+ break;
+ }
+ do{
+ ++first;
+ } while(first != middle && !comp(*middle, *first));
+ }
+ }
+ else{
+ while(middle != last){
+ RandIt p = boost::movelib::upper_bound(first, middle, last[-1], comp);
+ last = rotate_gcd(p, middle, last);
+ middle = p;
+ if(middle == first){
+ break;
+ }
+ --p;
+ do{
+ --last;
+ } while(middle != last && !comp(last[-1], *p));
+ }
+ }
+}
+
+static const std::size_t MergeBufferlessONLogNRotationThreshold = 32;
+
+template <class RandIt, class Distance, class Compare>
+void merge_bufferless_ONlogN_recursive
+ (RandIt first, RandIt middle, RandIt last, Distance len1, Distance len2, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ while(1) {
+ //trivial cases
+ if (!len2) {
+ return;
+ }
+ else if (!len1) {
+ return;
+ }
+ else if (size_type(len1 | len2) == 1u) {
+ if (comp(*middle, *first))
+ adl_move_swap(*first, *middle);
+ return;
+ }
+ else if(size_type(len1+len2) < MergeBufferlessONLogNRotationThreshold){
+ merge_bufferless_ON2(first, middle, last, comp);
+ return;
+ }
+
+ RandIt first_cut = first;
+ RandIt second_cut = middle;
+ Distance len11 = 0;
+ Distance len22 = 0;
+ if (len1 > len2) {
+ len11 = len1 / 2;
+ first_cut += len11;
+ second_cut = boost::movelib::lower_bound(middle, last, *first_cut, comp);
+ len22 = size_type(second_cut - middle);
+ }
+ else {
+ len22 = len2 / 2;
+ second_cut += len22;
+ first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp);
+ len11 = size_type(first_cut - first);
+ }
+ RandIt new_middle = rotate_gcd(first_cut, middle, second_cut);
+
+ //Avoid one recursive call doing a manual tail call elimination on the biggest range
+ const Distance len_internal = len11+len22;
+ if( len_internal < (len1 + len2 - len_internal) ) {
+ merge_bufferless_ONlogN_recursive(first, first_cut, new_middle, len11, len22, comp);
+ first = new_middle;
+ middle = second_cut;
+ len1 -= len11;
+ len2 -= len22;
+ }
+ else {
+ merge_bufferless_ONlogN_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
+ middle = first_cut;
+ last = new_middle;
+ len1 = len11;
+ len2 = len22;
+ }
+ }
+}
+
+//Complexity: NlogN
+template<class RandIt, class Compare>
+void merge_bufferless_ONlogN(RandIt first, RandIt middle, RandIt last, Compare comp)
+{
+ merge_bufferless_ONlogN_recursive
+ (first, middle, last, middle - first, last - middle, comp);
+}
+
+template<class RandIt, class Compare>
+void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
+{
+ #define BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
+ #ifdef BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
+ merge_bufferless_ONlogN(first, middle, last, comp);
+ #else
+ merge_bufferless_ON2(first, middle, last, comp);
+ #endif //BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
+}
+
+// [r_first, r_last) are already in the right part of the destination range.
+template <class Compare, class InputIterator, class InputOutIterator, class Op>
+void op_merge_with_right_placed
+ ( InputIterator first, InputIterator last
+ , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
+ , Compare comp, Op op)
+{
+ BOOST_ASSERT((last - first) == (r_first - dest_first));
+ while ( first != last ) {
+ if (r_first == r_last) {
+ InputOutIterator end = op(forward_t(), first, last, dest_first);
+ BOOST_ASSERT(end == r_last);
+ (void)end;
+ return;
+ }
+ else if (comp(*r_first, *first)) {
+ op(r_first, dest_first);
+ ++r_first;
+ }
+ else {
+ op(first, dest_first);
+ ++first;
+ }
+ ++dest_first;
+ }
+ // Remaining [r_first, r_last) already in the correct place
+}
+
+template <class Compare, class InputIterator, class InputOutIterator>
+void swap_merge_with_right_placed
+ ( InputIterator first, InputIterator last
+ , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
+ , Compare comp)
+{
+ op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, swap_op());
+}
+
+// [first, last) are already in the right part of the destination range.
+template <class Compare, class Op, class BidirIterator, class BidirOutIterator>
+void op_merge_with_left_placed
+ ( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
+ , BidirIterator const r_first, BidirIterator r_last
+ , Compare comp, Op op)
+{
+ BOOST_ASSERT((dest_last - last) == (r_last - r_first));
+ while( r_first != r_last ) {
+ if(first == last) {
+ BidirOutIterator res = op(backward_t(), r_first, r_last, dest_last);
+ BOOST_ASSERT(last == res);
+ (void)res;
+ return;
+ }
+ --r_last;
+ --last;
+ if(comp(*r_last, *last)){
+ ++r_last;
+ --dest_last;
+ op(last, dest_last);
+ }
+ else{
+ ++last;
+ --dest_last;
+ op(r_last, dest_last);
+ }
+ }
+ // Remaining [first, last) already in the correct place
+}
+
+// @endcond
+
+// [irst, last) are already in the right part of the destination range.
+template <class Compare, class BidirIterator, class BidirOutIterator>
+void merge_with_left_placed
+ ( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
+ , BidirIterator const r_first, BidirIterator r_last
+ , Compare comp)
+{
+ op_merge_with_left_placed(first, last, dest_last, r_first, r_last, comp, move_op());
+}
+
+// [r_first, r_last) are already in the right part of the destination range.
+template <class Compare, class InputIterator, class InputOutIterator>
+void merge_with_right_placed
+ ( InputIterator first, InputIterator last
+ , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
+ , Compare comp)
+{
+ op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, move_op());
+}
+
+// [r_first, r_last) are already in the right part of the destination range.
+// [dest_first, r_first) is uninitialized memory
+template <class Compare, class InputIterator, class InputOutIterator>
+void uninitialized_merge_with_right_placed
+ ( InputIterator first, InputIterator last
+ , InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
+ , Compare comp)
+{
+ BOOST_ASSERT((last - first) == (r_first - dest_first));
+ typedef typename iterator_traits<InputOutIterator>::value_type value_type;
+ InputOutIterator const original_r_first = r_first;
+
+ destruct_n<value_type, InputOutIterator> d(dest_first);
+
+ while ( first != last && dest_first != original_r_first ) {
+ if (r_first == r_last) {
+ for(; dest_first != original_r_first; ++dest_first, ++first){
+ ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
+ d.incr();
+ }
+ d.release();
+ InputOutIterator end = ::boost::move(first, last, original_r_first);
+ BOOST_ASSERT(end == r_last);
+ (void)end;
+ return;
+ }
+ else if (comp(*r_first, *first)) {
+ ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*r_first));
+ d.incr();
+ ++r_first;
+ }
+ else {
+ ::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
+ d.incr();
+ ++first;
+ }
+ ++dest_first;
+ }
+ d.release();
+ merge_with_right_placed(first, last, original_r_first, r_first, r_last, comp);
+}
+
+/*
+// [r_first, r_last) are already in the right part of the destination range.
+// [dest_first, r_first) is uninitialized memory
+template <class Compare, class BidirOutIterator, class BidirIterator>
+void uninitialized_merge_with_left_placed
+ ( BidirOutIterator dest_first, BidirOutIterator r_first, BidirOutIterator r_last
+ , BidirIterator first, BidirIterator last
+ , Compare comp)
+{
+ BOOST_ASSERT((last - first) == (r_last - r_first));
+ typedef typename iterator_traits<BidirOutIterator>::value_type value_type;
+ BidirOutIterator const original_r_last = r_last;
+
+ destruct_n<value_type> d(&*dest_last);
+
+ while ( first != last && dest_first != original_r_first ) {
+ if (r_first == r_last) {
+ for(; dest_first != original_r_first; ++dest_first, ++first){
+ ::new(&*dest_first) value_type(::boost::move(*first));
+ d.incr();
+ }
+ d.release();
+ BidirOutIterator end = ::boost::move(first, last, original_r_first);
+ BOOST_ASSERT(end == r_last);
+ (void)end;
+ return;
+ }
+ else if (comp(*r_first, *first)) {
+ ::new(&*dest_first) value_type(::boost::move(*r_first));
+ d.incr();
+ ++r_first;
+ }
+ else {
+ ::new(&*dest_first) value_type(::boost::move(*first));
+ d.incr();
+ ++first;
+ }
+ ++dest_first;
+ }
+ d.release();
+ merge_with_right_placed(first, last, original_r_first, r_first, r_last, comp);
+}
+*/
+
+} //namespace movelib {
+} //namespace boost {
+
+#endif //#define BOOST_MOVE_MERGE_HPP
diff --git a/include/boost/move/algo/detail/merge_sort.hpp b/include/boost/move/algo/detail/merge_sort.hpp
new file mode 100644
index 0000000..62d185a
--- /dev/null
+++ b/include/boost/move/algo/detail/merge_sort.hpp
@@ -0,0 +1,139 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP
+#define BOOST_MOVE_DETAIL_MERGE_SORT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/algo/move.hpp>
+#include <boost/move/algo/detail/merge.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/detail/destruct_n.hpp>
+#include <boost/move/algo/detail/insertion_sort.hpp>
+#include <cassert>
+
+namespace boost {
+namespace movelib {
+
+// @cond
+
+static const unsigned MergeSortInsertionSortThreshold = 16;
+
+template <class RandIt, class Compare>
+void inplace_stable_sort(RandIt first, RandIt last, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ if (size_type(last - first) <= size_type(MergeSortInsertionSortThreshold)) {
+ insertion_sort(first, last, comp);
+ return;
+ }
+ RandIt middle = first + (last - first) / 2;
+ inplace_stable_sort(first, middle, comp);
+ inplace_stable_sort(middle, last, comp);
+ merge_bufferless_ONlogN_recursive
+ (first, middle, last, size_type(middle - first), size_type(last - middle), comp);
+}
+
+// @endcond
+
+template<class RandIt, class RandIt2, class Compare>
+void merge_sort_copy( RandIt first, RandIt last
+ , RandIt2 dest, Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+
+ size_type const count = size_type(last - first);
+ if(count <= MergeSortInsertionSortThreshold){
+ insertion_sort_copy(first, last, dest, comp);
+ }
+ else{
+ size_type const half = count/2;
+ merge_sort_copy(first + half, last , dest+half , comp);
+ merge_sort_copy(first , first + half, first + half, comp);
+ merge_with_right_placed
+ ( first + half, first + half + half
+ , dest, dest+half, dest + count
+ , comp);
+ }
+}
+
+template<class RandIt, class RandItRaw, class Compare>
+void merge_sort_uninitialized_copy( RandIt first, RandIt last
+ , RandItRaw uninitialized
+ , Compare comp)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ size_type const count = size_type(last - first);
+ if(count <= MergeSortInsertionSortThreshold){
+ insertion_sort_uninitialized_copy(first, last, uninitialized, comp);
+ }
+ else{
+ size_type const half = count/2;
+ merge_sort_uninitialized_copy(first + half, last, uninitialized + half, comp);
+ destruct_n<value_type, RandItRaw> d(uninitialized+half);
+ d.incr(count-half);
+ merge_sort_copy(first, first + half, first + half, comp);
+ uninitialized_merge_with_right_placed
+ ( first + half, first + half + half
+ , uninitialized, uninitialized+half, uninitialized+count
+ , comp);
+ d.release();
+ }
+}
+
+template<class RandIt, class RandItRaw, class Compare>
+void merge_sort( RandIt first, RandIt last, Compare comp
+ , RandItRaw uninitialized)
+{
+ typedef typename iterator_traits<RandIt>::size_type size_type;
+ typedef typename iterator_traits<RandIt>::value_type value_type;
+
+ size_type const count = size_type(last - first);
+ if(count <= MergeSortInsertionSortThreshold){
+ insertion_sort(first, last, comp);
+ }
+ else{
+ size_type const half = count/2;
+ size_type const rest = count - half;
+ RandIt const half_it = first + half;
+ RandIt const rest_it = first + rest;
+
+ merge_sort_uninitialized_copy(half_it, last, uninitialized, comp);
+ destruct_n<value_type, RandItRaw> d(uninitialized);
+ d.incr(rest);
+ merge_sort_copy(first, half_it, rest_it, comp);
+ merge_with_right_placed
+ ( uninitialized, uninitialized + rest
+ , first, rest_it, last, antistable<Compare>(comp));
+ }
+}
+
+}} //namespace boost { namespace movelib{
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP
diff --git a/include/boost/move/algo/detail/pdqsort.hpp b/include/boost/move/algo/detail/pdqsort.hpp
new file mode 100644
index 0000000..b6a1278
--- /dev/null
+++ b/include/boost/move/algo/detail/pdqsort.hpp
@@ -0,0 +1,334 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Orson Peters 2017.
+// (C) Copyright Ion Gaztanaga 2017-2018.
+// 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.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// This implementation of Pattern-defeating quicksort (pdqsort) was written
+// by Orson Peters, and discussed in the Boost mailing list:
+// http://boost.2283326.n4.nabble.com/sort-pdqsort-td4691031.html
+//
+// This implementation is the adaptation by Ion Gaztanaga of code originally in GitHub
+// with permission from the author to relicense it under the Boost Software License
+// (see the Boost mailing list for details).
+//
+// The original copyright statement is pasted here for completeness:
+//
+// pdqsort.h - Pattern-defeating quicksort.
+// Copyright (c) 2015 Orson Peters
+// This software is provided 'as-is', without any express or implied warranty. In no event will the
+// authors be held liable for any damages arising from the use of this software.
+// Permission is granted to anyone to use this software for any purpose, including commercial
+// applications, and to alter it and redistribute it freely, subject to the following restrictions:
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the
+// original software. If you use this software in a product, an acknowledgment in the product
+// documentation would be appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as
+// being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_ALGO_PDQSORT_HPP
+#define BOOST_MOVE_ALGO_PDQSORT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/algo/detail/insertion_sort.hpp>
+#include <boost/move/algo/detail/heap_sort.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+
+#include <boost/move/adl_move_swap.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace movelib {
+
+namespace pdqsort_detail {
+
+ //A simple pair implementation to avoid including <utility>
+ template<class T1, class T2>
+ struct pair
+ {
+ pair()
+ {}
+
+ pair(const T1 &t1, const T2 &t2)
+ : first(t1), second(t2)
+ {}
+
+ T1 first;
+ T2 second;
+ };
+
+ enum {
+ // Partitions below this size are sorted using insertion sort.
+ insertion_sort_threshold = 24,
+
+ // Partitions above this size use Tukey's ninther to select the pivot.
+ ninther_threshold = 128,
+
+ // When we detect an already sorted partition, attempt an insertion sort that allows this
+ // amount of element moves before giving up.
+ partial_insertion_sort_limit = 8,
+
+ // Must be multiple of 8 due to loop unrolling, and < 256 to fit in unsigned char.
+ block_size = 64,
+
+ // Cacheline size, assumes power of two.
+ cacheline_size = 64
+
+ };
+
+ // Returns floor(log2(n)), assumes n > 0.
+ template<class Unsigned>
+ Unsigned log2(Unsigned n) {
+ Unsigned log = 0;
+ while (n >>= 1) ++log;
+ return log;
+ }
+
+ // Attempts to use insertion sort on [begin, end). Will return false if more than
+ // partial_insertion_sort_limit elements were moved, and abort sorting. Otherwise it will
+ // successfully sort and return true.
+ template<class Iter, class Compare>
+ inline bool partial_insertion_sort(Iter begin, Iter end, Compare comp) {
+ typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
+ typedef typename boost::movelib::iterator_traits<Iter>::size_type size_type;
+ if (begin == end) return true;
+
+ size_type limit = 0;
+ for (Iter cur = begin + 1; cur != end; ++cur) {
+ if (limit > partial_insertion_sort_limit) return false;
+
+ Iter sift = cur;
+ Iter sift_1 = cur - 1;
+
+ // Compare first so we can avoid 2 moves for an element already positioned correctly.
+ if (comp(*sift, *sift_1)) {
+ T tmp = boost::move(*sift);
+
+ do { *sift-- = boost::move(*sift_1); }
+ while (sift != begin && comp(tmp, *--sift_1));
+
+ *sift = boost::move(tmp);
+ limit += size_type(cur - sift);
+ }
+ }
+
+ return true;
+ }
+
+ template<class Iter, class Compare>
+ inline void sort2(Iter a, Iter b, Compare comp) {
+ if (comp(*b, *a)) boost::adl_move_iter_swap(a, b);
+ }
+
+ // Sorts the elements *a, *b and *c using comparison function comp.
+ template<class Iter, class Compare>
+ inline void sort3(Iter a, Iter b, Iter c, Compare comp) {
+ sort2(a, b, comp);
+ sort2(b, c, comp);
+ sort2(a, b, comp);
+ }
+
+ // Partitions [begin, end) around pivot *begin using comparison function comp. Elements equal
+ // to the pivot are put in the right-hand partition. Returns the position of the pivot after
+ // partitioning and whether the passed sequence already was correctly partitioned. Assumes the
+ // pivot is a median of at least 3 elements and that [begin, end) is at least
+ // insertion_sort_threshold long.
+ template<class Iter, class Compare>
+ pdqsort_detail::pair<Iter, bool> partition_right(Iter begin, Iter end, Compare comp) {
+ typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
+
+ // Move pivot into local for speed.
+ T pivot(boost::move(*begin));
+
+ Iter first = begin;
+ Iter last = end;
+
+ // Find the first element greater than or equal than the pivot (the median of 3 guarantees
+ // this exists).
+ while (comp(*++first, pivot));
+
+ // Find the first element strictly smaller than the pivot. We have to guard this search if
+ // there was no element before *first.
+ if (first - 1 == begin) while (first < last && !comp(*--last, pivot));
+ else while ( !comp(*--last, pivot));
+
+ // If the first pair of elements that should be swapped to partition are the same element,
+ // the passed in sequence already was correctly partitioned.
+ bool already_partitioned = first >= last;
+
+ // Keep swapping pairs of elements that are on the wrong side of the pivot. Previously
+ // swapped pairs guard the searches, which is why the first iteration is special-cased
+ // above.
+ while (first < last) {
+ boost::adl_move_iter_swap(first, last);
+ while (comp(*++first, pivot));
+ while (!comp(*--last, pivot));
+ }
+
+ // Put the pivot in the right place.
+ Iter pivot_pos = first - 1;
+ *begin = boost::move(*pivot_pos);
+ *pivot_pos = boost::move(pivot);
+
+ return pdqsort_detail::pair<Iter, bool>(pivot_pos, already_partitioned);
+ }
+
+ // Similar function to the one above, except elements equal to the pivot are put to the left of
+ // the pivot and it doesn't check or return if the passed sequence already was partitioned.
+ // Since this is rarely used (the many equal case), and in that case pdqsort already has O(n)
+ // performance, no block quicksort is applied here for simplicity.
+ template<class Iter, class Compare>
+ inline Iter partition_left(Iter begin, Iter end, Compare comp) {
+ typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
+
+ T pivot(boost::move(*begin));
+ Iter first = begin;
+ Iter last = end;
+
+ while (comp(pivot, *--last));
+
+ if (last + 1 == end) while (first < last && !comp(pivot, *++first));
+ else while ( !comp(pivot, *++first));
+
+ while (first < last) {
+ boost::adl_move_iter_swap(first, last);
+ while (comp(pivot, *--last));
+ while (!comp(pivot, *++first));
+ }
+
+ Iter pivot_pos = last;
+ *begin = boost::move(*pivot_pos);
+ *pivot_pos = boost::move(pivot);
+
+ return pivot_pos;
+ }
+
+
+ template<class Iter, class Compare>
+ void pdqsort_loop( Iter begin, Iter end, Compare comp
+ , typename boost::movelib::iterator_traits<Iter>::size_type bad_allowed
+ , bool leftmost = true)
+ {
+ typedef typename boost::movelib::iterator_traits<Iter>::size_type size_type;
+
+ // Use a while loop for tail recursion elimination.
+ while (true) {
+ size_type size = size_type(end - begin);
+
+ // Insertion sort is faster for small arrays.
+ if (size < insertion_sort_threshold) {
+ insertion_sort(begin, end, comp);
+ return;
+ }
+
+ // Choose pivot as median of 3 or pseudomedian of 9.
+ size_type s2 = size / 2;
+ if (size > ninther_threshold) {
+ sort3(begin, begin + s2, end - 1, comp);
+ sort3(begin + 1, begin + (s2 - 1), end - 2, comp);
+ sort3(begin + 2, begin + (s2 + 1), end - 3, comp);
+ sort3(begin + (s2 - 1), begin + s2, begin + (s2 + 1), comp);
+ boost::adl_move_iter_swap(begin, begin + s2);
+ } else sort3(begin + s2, begin, end - 1, comp);
+
+ // If *(begin - 1) is the end of the right partition of a previous partition operation
+ // there is no element in [begin, end) that is smaller than *(begin - 1). Then if our
+ // pivot compares equal to *(begin - 1) we change strategy, putting equal elements in
+ // the left partition, greater elements in the right partition. We do not have to
+ // recurse on the left partition, since it's sorted (all equal).
+ if (!leftmost && !comp(*(begin - 1), *begin)) {
+ begin = partition_left(begin, end, comp) + 1;
+ continue;
+ }
+
+ // Partition and get results.
+ pdqsort_detail::pair<Iter, bool> part_result = partition_right(begin, end, comp);
+ Iter pivot_pos = part_result.first;
+ bool already_partitioned = part_result.second;
+
+ // Check for a highly unbalanced partition.
+ size_type l_size = size_type(pivot_pos - begin);
+ size_type r_size = size_type(end - (pivot_pos + 1));
+ bool highly_unbalanced = l_size < size / 8 || r_size < size / 8;
+
+ // If we got a highly unbalanced partition we shuffle elements to break many patterns.
+ if (highly_unbalanced) {
+ // If we had too many bad partitions, switch to heapsort to guarantee O(n log n).
+ if (--bad_allowed == 0) {
+ boost::movelib::heap_sort(begin, end, comp);
+ return;
+ }
+
+ if (l_size >= insertion_sort_threshold) {
+ boost::adl_move_iter_swap(begin, begin + l_size / 4);
+ boost::adl_move_iter_swap(pivot_pos - 1, pivot_pos - l_size / 4);
+
+ if (l_size > ninther_threshold) {
+ boost::adl_move_iter_swap(begin + 1, begin + (l_size / 4 + 1));
+ boost::adl_move_iter_swap(begin + 2, begin + (l_size / 4 + 2));
+ boost::adl_move_iter_swap(pivot_pos - 2, pivot_pos - (l_size / 4 + 1));
+ boost::adl_move_iter_swap(pivot_pos - 3, pivot_pos - (l_size / 4 + 2));
+ }
+ }
+
+ if (r_size >= insertion_sort_threshold) {
+ boost::adl_move_iter_swap(pivot_pos + 1, pivot_pos + (1 + r_size / 4));
+ boost::adl_move_iter_swap(end - 1, end - r_size / 4);
+
+ if (r_size > ninther_threshold) {
+ boost::adl_move_iter_swap(pivot_pos + 2, pivot_pos + (2 + r_size / 4));
+ boost::adl_move_iter_swap(pivot_pos + 3, pivot_pos + (3 + r_size / 4));
+ boost::adl_move_iter_swap(end - 2, end - (1 + r_size / 4));
+ boost::adl_move_iter_swap(end - 3, end - (2 + r_size / 4));
+ }
+ }
+ } else {
+ // If we were decently balanced and we tried to sort an already partitioned
+ // sequence try to use insertion sort.
+ if (already_partitioned && partial_insertion_sort(begin, pivot_pos, comp)
+ && partial_insertion_sort(pivot_pos + 1, end, comp)) return;
+ }
+
+ // Sort the left partition first using recursion and do tail recursion elimination for
+ // the right-hand partition.
+ pdqsort_loop<Iter, Compare>(begin, pivot_pos, comp, bad_allowed, leftmost);
+ begin = pivot_pos + 1;
+ leftmost = false;
+ }
+ }
+}
+
+
+template<class Iter, class Compare>
+void pdqsort(Iter begin, Iter end, Compare comp)
+{
+ if (begin == end) return;
+ typedef typename boost::movelib::iterator_traits<Iter>::size_type size_type;
+ pdqsort_detail::pdqsort_loop<Iter, Compare>(begin, end, comp, pdqsort_detail::log2(size_type(end - begin)));
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //BOOST_MOVE_ALGO_PDQSORT_HPP
diff --git a/include/boost/move/algo/detail/set_difference.hpp b/include/boost/move/algo/detail/set_difference.hpp
new file mode 100644
index 0000000..51d0475
--- /dev/null
+++ b/include/boost/move/algo/detail/set_difference.hpp
@@ -0,0 +1,207 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_SET_DIFFERENCE_HPP
+#define BOOST_MOVE_SET_DIFFERENCE_HPP
+
+#include <boost/move/algo/move.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/utility_core.hpp>
+
+namespace boost {
+
+namespace move_detail{
+
+template<class InputIt, class OutputIt>
+OutputIt copy(InputIt first, InputIt last, OutputIt result)
+{
+ while (first != last) {
+ *result++ = *first;
+ ++result;
+ ++first;
+ }
+ return result;
+}
+
+} //namespace move_detail{
+
+namespace movelib {
+
+//Moves the elements from the sorted range [first1, last1) which are not found in the sorted
+//range [first2, last2) to the range beginning at result.
+//The resulting range is also sorted. Equivalent elements are treated individually,
+//that is, if some element is found m times in [first1, last1) and n times in [first2, last2),
+//it will be moved to result exactly max(m-n, 0) times.
+//The resulting range cannot overlap with either of the input ranges.
+template<class InputIt1, class InputIt2,
+ class OutputIt, class Compare>
+OutputIt set_difference
+ (InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt result, Compare comp)
+{
+ while (first1 != last1) {
+ if (first2 == last2)
+ return boost::move_detail::copy(first1, last1, result);
+
+ if (comp(*first1, *first2)) {
+ *result = *first1;
+ ++result;
+ ++first1;
+ }
+ else {
+ if (!comp(*first2, *first1)) {
+ ++first1;
+ }
+ ++first2;
+ }
+ }
+ return result;
+}
+
+//Moves the elements from the sorted range [first1, last1) which are not found in the sorted
+//range [first2, last2) to the range beginning at first1 (in place operation in range1).
+//The resulting range is also sorted. Equivalent elements are treated individually,
+//that is, if some element is found m times in [first1, last1) and n times in [first2, last2),
+//it will be moved to result exactly max(m-n, 0) times.
+template<class InputOutputIt1, class InputIt2, class Compare>
+InputOutputIt1 inplace_set_difference
+ (InputOutputIt1 first1, InputOutputIt1 last1, InputIt2 first2, InputIt2 last2, Compare comp )
+{
+ while (first1 != last1) {
+ //Skip copying from range 1 if no element has to be skipped
+ if (first2 == last2){
+ return last1;
+ }
+ else if (comp(*first1, *first2)){
+ ++first1;
+ }
+ else{
+ if (!comp(*first2, *first1)) {
+ InputOutputIt1 result = first1;
+ //An element from range 1 must be skipped, no longer an inplace operation
+ return boost::movelib::set_difference
+ ( boost::make_move_iterator(++first1)
+ , boost::make_move_iterator(last1)
+ , ++first2, last2, result, comp);
+ }
+ ++first2;
+ }
+ }
+ return first1;
+}
+
+//Moves the elements from the sorted range [first1, last1) which are not found in the sorted
+//range [first2, last2) to the range beginning at first1.
+//The resulting range is also sorted. Equivalent elements from range 1 are moved past to end
+//of the result,
+//that is, if some element is found m times in [first1, last1) and n times in [first2, last2),
+//it will be moved to result exactly max(m-n, 0) times.
+//The resulting range cannot overlap with either of the input ranges.
+template<class ForwardIt1, class InputIt2,
+ class OutputIt, class Compare>
+OutputIt set_unique_difference
+ (ForwardIt1 first1, ForwardIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt result, Compare comp)
+{
+ while (first1 != last1) {
+ if (first2 == last2){
+ //unique_copy-like sequence with forward iterators but don't write i
+ //to result before comparing as moving *i could alter the value in i.
+ ForwardIt1 i = first1;
+ while (++first1 != last1) {
+ if (comp(*i, *first1)) {
+ *result = *i;
+ ++result;
+ i = first1;
+ }
+ }
+ *result = *i;
+ ++result;
+ break;
+ }
+
+ if (comp(*first1, *first2)) {
+ //Skip equivalent elements in range1 but don't write i
+ //to result before comparing as moving *i could alter the value in i.
+ ForwardIt1 i = first1;
+ while (++first1 != last1) {
+ if (comp(*i, *first1)) {
+ break;
+ }
+ }
+ *result = *i;
+ ++result;
+ }
+ else {
+ if (comp(*first2, *first1)) {
+ ++first2;
+ }
+ else{
+ ++first1;
+ }
+ }
+ }
+ return result;
+}
+
+//Moves the elements from the sorted range [first1, last1) which are not found in the sorted
+//range [first2, last2) to the range beginning at first1 (in place operation in range1).
+//The resulting range is also sorted. Equivalent elements are treated individually,
+//that is, if some element is found m times in [first1, last1) and n times in [first2, last2),
+//it will be moved to result exactly max(m-n, 0) times.
+template<class ForwardOutputIt1, class ForwardIt2, class Compare>
+ForwardOutputIt1 inplace_set_unique_difference
+ (ForwardOutputIt1 first1, ForwardOutputIt1 last1, ForwardIt2 first2, ForwardIt2 last2, Compare comp )
+{
+ while (first1 != last1) {
+ //Skip copying from range 1 if no element has to be skipped
+ if (first2 == last2){
+ //unique-like algorithm for the remaining range 1
+ ForwardOutputIt1 result = first1;
+ while (++first1 != last1) {
+ if (comp(*result, *first1) && ++result != first1) {
+ *result = boost::move(*first1);
+ }
+ }
+ return ++result;
+ }
+ else if (comp(*first2, *first1)) {
+ ++first2;
+ }
+ else if (comp(*first1, *first2)){
+ //skip any adjacent equivalent elementin range 1
+ ForwardOutputIt1 result = first1;
+ if (++first1 != last1 && !comp(*result, *first1)) {
+ //Some elements from range 1 must be skipped, no longer an inplace operation
+ while (++first1 != last1 && !comp(*result, *first1)){}
+ return boost::movelib::set_unique_difference
+ ( boost::make_move_iterator(first1)
+ , boost::make_move_iterator(last1)
+ , first2, last2, ++result, comp);
+ }
+ }
+ else{
+ ForwardOutputIt1 result = first1;
+ //Some elements from range 1 must be skipped, no longer an inplace operation
+ while (++first1 != last1 && !comp(*result, *first1)){}
+ //An element from range 1 must be skipped, no longer an inplace operation
+ return boost::movelib::set_unique_difference
+ ( boost::make_move_iterator(first1)
+ , boost::make_move_iterator(last1)
+ , first2, last2, result, comp);
+ }
+ }
+ return first1;
+}
+
+
+
+} //namespace movelib {
+} //namespace boost {
+
+#endif //#define BOOST_MOVE_SET_DIFFERENCE_HPP
diff --git a/include/boost/move/algo/move.hpp b/include/boost/move/algo/move.hpp
new file mode 100644
index 0000000..2390877
--- /dev/null
+++ b/include/boost/move/algo/move.hpp
@@ -0,0 +1,156 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_ALGO_MOVE_HPP
+#define BOOST_MOVE_ALGO_MOVE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+ //! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last -
+ //! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first),
+ //! performs *(result + n) = ::boost::move (*(first + n)).
+ //!
+ //! <b>Effects</b>: result + (last - first).
+ //!
+ //! <b>Requires</b>: result shall not be in the range [first,last).
+ //!
+ //! <b>Complexity</b>: Exactly last - first move assignments.
+ template <typename I, // I models InputIterator
+ typename O> // O models OutputIterator
+ O move(I f, I l, O result)
+ {
+ while (f != l) {
+ *result = ::boost::move(*f);
+ ++f; ++result;
+ }
+ return result;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_backward
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ //! <b>Effects</b>: Moves elements in the range [first,last) into the range
+ //! [result - (last-first),result) starting from last - 1 and proceeding to
+ //! first. For each positive integer n <= (last - first),
+ //! performs *(result - n) = ::boost::move(*(last - n)).
+ //!
+ //! <b>Requires</b>: result shall not be in the range [first,last).
+ //!
+ //! <b>Returns</b>: result - (last - first).
+ //!
+ //! <b>Complexity</b>: Exactly last - first assignments.
+ template <typename I, // I models BidirectionalIterator
+ typename O> // O models BidirectionalIterator
+ O move_backward(I f, I l, O result)
+ {
+ while (f != l) {
+ --l; --result;
+ *result = ::boost::move(*l);
+ }
+ return result;
+ }
+
+#else
+
+ using ::std::move_backward;
+
+#endif //!defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; first != last; ++result, ++first)
+//! new (static_cast<void*>(&*result))
+//! typename iterator_traits<ForwardIterator>::value_type(boost::move(*first));
+//! \endcode
+//!
+//! <b>Returns</b>: result
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+F uninitialized_move(I f, I l, F r
+ /// @cond
+// ,typename ::boost::move_detail::enable_if<has_move_emulation_enabled<typename boost::movelib::iterator_traits<I>::value_type> >::type* = 0
+ /// @endcond
+ )
+{
+ typedef typename boost::movelib::iterator_traits<I>::value_type input_value_type;
+
+ F back = r;
+ BOOST_TRY{
+ while (f != l) {
+ void * const addr = static_cast<void*>(::boost::move_detail::addressof(*r));
+ ::new(addr) input_value_type(::boost::move(*f));
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ boost::movelib::iterator_to_raw_pointer(back)->~input_value_type();
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+/// @cond
+/*
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+F uninitialized_move(I f, I l, F r,
+ typename ::boost::move_detail::disable_if<has_move_emulation_enabled<typename boost::movelib::iterator_traits<I>::value_type> >::type* = 0)
+{
+ return std::uninitialized_copy(f, l, r);
+}
+*/
+
+/// @endcond
+
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_ALGO_MOVE_HPP
diff --git a/include/boost/move/algo/predicate.hpp b/include/boost/move/algo/predicate.hpp
new file mode 100644
index 0000000..0287d66
--- /dev/null
+++ b/include/boost/move/algo/predicate.hpp
@@ -0,0 +1,86 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ALGO_PREDICATE_HPP
+#define BOOST_MOVE_ALGO_PREDICATE_HPP
+
+#include <boost/move/algo/move.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/algo/detail/basic_op.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/detail/destruct_n.hpp>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace movelib {
+
+template<class Comp>
+struct antistable
+{
+ explicit antistable(Comp &comp)
+ : m_comp(comp)
+ {}
+
+ template<class U, class V>
+ bool operator()(const U &u, const V & v)
+ { return !m_comp(v, u); }
+
+ private:
+ antistable & operator=(const antistable &);
+ Comp &m_comp;
+};
+
+template <class Comp>
+class negate
+{
+ public:
+ negate()
+ {}
+
+ explicit negate(Comp comp)
+ : m_comp(comp)
+ {}
+
+ template <class T1, class T2>
+ bool operator()(const T1& l, const T2& r)
+ {
+ return !m_comp(l, r);
+ }
+
+ private:
+ Comp m_comp;
+};
+
+
+template <class Comp>
+class inverse
+{
+ public:
+ inverse()
+ {}
+
+ explicit inverse(Comp comp)
+ : m_comp(comp)
+ {}
+
+ template <class T1, class T2>
+ bool operator()(const T1& l, const T2& r)
+ {
+ return m_comp(r, l);
+ }
+
+ private:
+ Comp m_comp;
+};
+
+} //namespace movelib {
+} //namespace boost {
+
+#endif //#define BOOST_MOVE_ALGO_PREDICATE_HPP
diff --git a/include/boost/move/algo/unique.hpp b/include/boost/move/algo/unique.hpp
new file mode 100644
index 0000000..8022a65
--- /dev/null
+++ b/include/boost/move/algo/unique.hpp
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_ALGO_UNIQUE_HPP
+#define BOOST_MOVE_ALGO_UNIQUE_HPP
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/utility_core.hpp>
+
+namespace boost {
+namespace movelib {
+
+//! <b>Requires</b>: The comparison function shall be an equivalence relation. The type of *first shall satisfy
+//! the MoveAssignable requirements
+//!
+//! <b>Effects</b>: For a nonempty range, eliminates all but the first element from every consecutive group
+//! of equivalent elements referred to by the iterator i in the range [first + 1, last) for which the
+//! following conditions hold: pred(*(i - 1), *i) != false.
+//!
+//! <b>Returns</b>: The end of the resulting range.
+//!
+//! <b>Complexity</b>: For nonempty ranges, exactly (last - first) - 1 applications of the corresponding predicate.
+template<class ForwardIterator, class BinaryPredicate>
+ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred)
+{
+ if (first != last) {
+ ForwardIterator next(first);
+ ++next;
+ for (; next != last; ++next, ++first) {
+ if (pred(*first, *next)) { //Find first equal element
+ while (++next != last)
+ if (!pred(*first, *next))
+ *++first = ::boost::move(*next);
+ break;
+ }
+ }
+ ++first;
+ }
+ return first;
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#define BOOST_MOVE_ALGO_UNIQUE_HPP
diff --git a/include/boost/move/algorithm.hpp b/include/boost/move/algorithm.hpp
new file mode 100644
index 0000000..825d771
--- /dev/null
+++ b/include/boost/move/algorithm.hpp
@@ -0,0 +1,167 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_ALGORITHM_HPP
+#define BOOST_MOVE_ALGORITHM_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/algo/move.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+
+#include <algorithm> //copy, copy_backward
+#include <memory> //uninitialized_copy
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_copy_or_move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+namespace move_detail {
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F uninitialized_move_move_iterator(I f, I l, F r
+// ,typename ::boost::move_detail::enable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0
+)
+{
+ return ::boost::uninitialized_move(f, l, r);
+}
+/*
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+F uninitialized_move_move_iterator(I f, I l, F r,
+ typename ::boost::move_detail::disable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0)
+{
+ return std::uninitialized_copy(f.base(), l.base(), r);
+}
+*/
+} //namespace move_detail {
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F uninitialized_copy_or_move(I f, I l, F r,
+ typename ::boost::move_detail::enable_if< move_detail::is_move_iterator<I> >::type* = 0)
+{
+ return ::boost::move_detail::uninitialized_move_move_iterator(f, l, r);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_or_move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+namespace move_detail {
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F move_move_iterator(I f, I l, F r
+// ,typename ::boost::move_detail::enable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0
+)
+{
+ return ::boost::move(f, l, r);
+}
+/*
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+F move_move_iterator(I f, I l, F r,
+ typename ::boost::move_detail::disable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0)
+{
+ return std::copy(f.base(), l.base(), r);
+}
+*/
+
+} //namespace move_detail {
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F copy_or_move(I f, I l, F r,
+ typename ::boost::move_detail::enable_if< move_detail::is_move_iterator<I> >::type* = 0)
+{
+ return ::boost::move_detail::move_move_iterator(f, l, r);
+}
+
+/// @endcond
+
+//! <b>Effects</b>:
+//! \code
+//! for (; first != last; ++result, ++first)
+//! new (static_cast<void*>(&*result))
+//! typename iterator_traits<ForwardIterator>::value_type(*first);
+//! \endcode
+//!
+//! <b>Returns</b>: result
+//!
+//! <b>Note</b>: This function is provided because
+//! <i>std::uninitialized_copy</i> from some STL implementations
+//! is not compatible with <i>move_iterator</i>
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F uninitialized_copy_or_move(I f, I l, F r
+ /// @cond
+ ,typename ::boost::move_detail::disable_if< move_detail::is_move_iterator<I> >::type* = 0
+ /// @endcond
+ )
+{
+ return std::uninitialized_copy(f, l, r);
+}
+
+//! <b>Effects</b>:
+//! \code
+//! for (; first != last; ++result, ++first)
+//! *result = *first;
+//! \endcode
+//!
+//! <b>Returns</b>: result
+//!
+//! <b>Note</b>: This function is provided because
+//! <i>std::uninitialized_copy</i> from some STL implementations
+//! is not compatible with <i>move_iterator</i>
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F copy_or_move(I f, I l, F r
+ /// @cond
+ ,typename ::boost::move_detail::disable_if< move_detail::is_move_iterator<I> >::type* = 0
+ /// @endcond
+ )
+{
+ return std::copy(f, l, r);
+}
+
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_ALGORITHM_HPP
diff --git a/include/boost/move/core.hpp b/include/boost/move/core.hpp
new file mode 100644
index 0000000..c0f5be5
--- /dev/null
+++ b/include/boost/move/core.hpp
@@ -0,0 +1,490 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+//! This header implements macros to define movable classes and
+//! move-aware functions
+
+#ifndef BOOST_MOVE_CORE_HPP
+#define BOOST_MOVE_CORE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+
+// @cond
+
+//boost_move_no_copy_constructor_or_assign typedef
+//used to detect noncopyable types for other Boost libraries.
+#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
+ private:\
+ TYPE(TYPE &);\
+ TYPE& operator=(TYPE &);\
+ public:\
+ typedef int boost_move_no_copy_constructor_or_assign; \
+ private:\
+ //
+#else
+ #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
+ public:\
+ TYPE(TYPE const &) = delete;\
+ TYPE& operator=(TYPE const &) = delete;\
+ public:\
+ typedef int boost_move_no_copy_constructor_or_assign; \
+ private:\
+ //
+#endif //BOOST_NO_CXX11_DELETED_FUNCTIONS
+
+// @endcond
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #include <boost/move/detail/type_traits.hpp>
+
+ #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) reinterpret_cast<RV_TYPE>(ARG)
+
+ //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers
+ #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
+
+ namespace boost {
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // struct rv
+ //
+ //////////////////////////////////////////////////////////////////////////////
+ template <class T>
+ class rv
+ : public ::boost::move_detail::if_c
+ < ::boost::move_detail::is_class<T>::value
+ , T
+ , ::boost::move_detail::nat
+ >::type
+ {
+ rv();
+ ~rv() throw();
+ rv(rv const&);
+ void operator=(rv const&);
+ } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS;
+
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // is_rv
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ namespace move_detail {
+
+ template <class T>
+ struct is_rv
+ //Derive from integral constant because some Boost code assummes it has
+ //a "type" internal typedef
+ : integral_constant<bool, ::boost::move_detail::is_rv_impl<T>::value >
+ {};
+
+ template <class T>
+ struct is_not_rv
+ {
+ static const bool value = !is_rv<T>::value;
+ };
+
+ } //namespace move_detail {
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // has_move_emulation_enabled
+ //
+ //////////////////////////////////////////////////////////////////////////////
+ template<class T>
+ struct has_move_emulation_enabled
+ : ::boost::move_detail::has_move_emulation_enabled_impl<T>
+ {};
+
+ template<class T>
+ struct has_move_emulation_disabled
+ {
+ static const bool value = !::boost::move_detail::has_move_emulation_enabled_impl<T>::value;
+ };
+
+ } //namespace boost {
+
+ #define BOOST_RV_REF(TYPE)\
+ ::boost::rv< TYPE >& \
+ //
+
+ #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
+ ::boost::rv< TYPE<ARG1, ARG2> >& \
+ //
+
+ #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
+ ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
+ //
+
+ #define BOOST_RV_REF_BEG\
+ ::boost::rv< \
+ //
+
+ #define BOOST_RV_REF_END\
+ >& \
+ //
+
+ #define BOOST_RV_REF_BEG_IF_CXX11 \
+ \
+ //
+
+ #define BOOST_RV_REF_END_IF_CXX11 \
+ \
+ //
+
+ #define BOOST_FWD_REF(TYPE)\
+ const TYPE & \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF(TYPE)\
+ const ::boost::rv< TYPE >& \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_BEG \
+ const ::boost::rv< \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_END \
+ >& \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
+ const ::boost::rv< TYPE<ARG1, ARG2> >& \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
+ const ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
+ //
+
+ #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
+ const ::boost::rv< TYPE >& \
+ //
+
+ namespace boost {
+ namespace move_detail {
+
+ template <class Ret, class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < ::boost::move_detail::is_lvalue_reference<Ret>::value ||
+ !::boost::has_move_emulation_enabled<T>::value
+ , T&>::type
+ move_return(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class Ret, class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < !::boost::move_detail::is_lvalue_reference<Ret>::value &&
+ ::boost::has_move_emulation_enabled<T>::value
+ , ::boost::rv<T>&>::type
+ move_return(T& x) BOOST_NOEXCEPT
+ {
+ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x));
+ }
+
+ template <class Ret, class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < !::boost::move_detail::is_lvalue_reference<Ret>::value &&
+ ::boost::has_move_emulation_enabled<T>::value
+ , ::boost::rv<T>&>::type
+ move_return(::boost::rv<T>& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ } //namespace move_detail {
+ } //namespace boost {
+
+ #define BOOST_MOVE_RET(RET_TYPE, REF)\
+ boost::move_detail::move_return< RET_TYPE >(REF)
+ //
+
+ #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \
+ ::boost::move((BASE_TYPE&)(ARG))
+ //
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // BOOST_MOVABLE_BUT_NOT_COPYABLE
+ //
+ //////////////////////////////////////////////////////////////////////////////
+ #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
+ BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
+ public:\
+ BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
+ { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
+ BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
+ { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
+ private:\
+ //
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // BOOST_COPYABLE_AND_MOVABLE
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
+ public:\
+ BOOST_MOVE_FORCEINLINE TYPE& operator=(TYPE &t)\
+ { this->operator=(const_cast<const TYPE&>(t)); return *this;}\
+ public:\
+ BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
+ { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
+ BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
+ { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
+ private:\
+ //
+
+ #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
+ public:\
+ BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
+ { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
+ BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
+ { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
+ private:\
+ //
+
+ namespace boost{
+ namespace move_detail{
+
+ template< class T>
+ struct forward_type
+ { typedef const T &type; };
+
+ template< class T>
+ struct forward_type< boost::rv<T> >
+ { typedef T type; };
+
+ }}
+
+#else //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ //! This macro marks a type as movable but not copyable, disabling copy construction
+ //! and assignment. The user will need to write a move constructor/assignment as explained
+ //! in the documentation to fully write a movable but not copyable class.
+ #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
+ BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
+ public:\
+ typedef int boost_move_emulation_t;\
+ private:\
+ //
+
+ //! This macro marks a type as copyable and movable.
+ //! The user will need to write a move constructor/assignment and a copy assignment
+ //! as explained in the documentation to fully write a copyable and movable class.
+ #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
+ //
+
+ #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
+ //
+ #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ namespace boost {
+
+ //!This trait yields to a compile-time true boolean if T was marked as
+ //!BOOST_MOVABLE_BUT_NOT_COPYABLE or BOOST_COPYABLE_AND_MOVABLE and
+ //!rvalue references are not available on the platform. False otherwise.
+ template<class T>
+ struct has_move_emulation_enabled
+ {
+ static const bool value = false;
+ };
+
+ template<class T>
+ struct has_move_emulation_disabled
+ {
+ static const bool value = true;
+ };
+
+ } //namespace boost{
+
+ //!This macro is used to achieve portable syntax in move
+ //!constructors and assignments for classes marked as
+ //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE
+ #define BOOST_RV_REF(TYPE)\
+ TYPE && \
+ //
+
+ //!This macro is used to achieve portable syntax in move
+ //!constructors and assignments for template classes marked as
+ //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE.
+ //!As macros have problems with comma-separated template arguments,
+ //!the template argument must be preceded with BOOST_RV_REF_BEG
+ //!and ended with BOOST_RV_REF_END
+ #define BOOST_RV_REF_BEG\
+ \
+ //
+
+ //!This macro is used to achieve portable syntax in move
+ //!constructors and assignments for template classes marked as
+ //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE.
+ //!As macros have problems with comma-separated template arguments,
+ //!the template argument must be preceded with BOOST_RV_REF_BEG
+ //!and ended with BOOST_RV_REF_END
+ #define BOOST_RV_REF_END\
+ && \
+ //
+
+ //!This macro expands to BOOST_RV_REF_BEG if BOOST_NO_CXX11_RVALUE_REFERENCES
+ //!is not defined, empty otherwise
+ #define BOOST_RV_REF_BEG_IF_CXX11 \
+ BOOST_RV_REF_BEG \
+ //
+
+ //!This macro expands to BOOST_RV_REF_END if BOOST_NO_CXX11_RVALUE_REFERENCES
+ //!is not defined, empty otherwise
+ #define BOOST_RV_REF_END_IF_CXX11 \
+ BOOST_RV_REF_END \
+ //
+
+ //!This macro is used to achieve portable syntax in copy
+ //!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE.
+ #define BOOST_COPY_ASSIGN_REF(TYPE)\
+ const TYPE & \
+ //
+
+ //! This macro is used to implement portable perfect forwarding
+ //! as explained in the documentation.
+ #define BOOST_FWD_REF(TYPE)\
+ TYPE && \
+ //
+
+ #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
+ TYPE<ARG1, ARG2> && \
+ //
+
+ #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
+ TYPE<ARG1, ARG2, ARG3> && \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_BEG \
+ const \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_END \
+ & \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
+ const TYPE<ARG1, ARG2> & \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
+ const TYPE<ARG1, ARG2, ARG3>& \
+ //
+
+ #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
+ const TYPE & \
+ //
+
+ #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ //!This macro is used to achieve portable move return semantics.
+ //!The C++11 Standard allows implicit move returns when the object to be returned
+ //!is designated by a lvalue and:
+ //! - The criteria for elision of a copy operation are met OR
+ //! - The criteria would be met save for the fact that the source object is a function parameter
+ //!
+ //!For C++11 conforming compilers this macros only yields to REF:
+ //! <code>return BOOST_MOVE_RET(RET_TYPE, REF);</code> -> <code>return REF;</code>
+ //!
+ //!For compilers without rvalue references
+ //!this macro does an explicit move if the move emulation is activated
+ //!and the return type (RET_TYPE) is not a reference.
+ //!
+ //!For non-conforming compilers with rvalue references like Visual 2010 & 2012,
+ //!an explicit move is performed if RET_TYPE is not a reference.
+ //!
+ //! <b>Caution</b>: When using this macro in non-conforming or C++03
+ //!compilers, a move will be performed even if the C++11 standard does not allow it
+ //!(e.g. returning a static variable). The user is responsible for using this macro
+ //!only to return local objects that met C++11 criteria.
+ #define BOOST_MOVE_RET(RET_TYPE, REF)\
+ REF
+ //
+
+ #else //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #include <boost/move/detail/meta_utils.hpp>
+
+ namespace boost {
+ namespace move_detail {
+
+ template <class Ret, class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < ::boost::move_detail::is_lvalue_reference<Ret>::value
+ , T&>::type
+ move_return(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class Ret, class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < !::boost::move_detail::is_lvalue_reference<Ret>::value
+ , Ret && >::type
+ move_return(T&& t) BOOST_NOEXCEPT
+ {
+ return static_cast< Ret&& >(t);
+ }
+
+ } //namespace move_detail {
+ } //namespace boost {
+
+ #define BOOST_MOVE_RET(RET_TYPE, REF)\
+ boost::move_detail::move_return< RET_TYPE >(REF)
+ //
+
+ #endif //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ //!This macro is used to achieve portable optimal move constructors.
+ //!
+ //!When implementing the move constructor, in C++03 compilers the moved-from argument must be
+ //!cast to the base type before calling `::boost::move()` due to rvalue reference limitations.
+ //!
+ //!In C++11 compilers the cast from a rvalue reference of a derived type to a rvalue reference of
+ //!a base type is implicit.
+ #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \
+ ::boost::move((BASE_TYPE&)(ARG))
+ //
+
+ namespace boost {
+ namespace move_detail {
+
+ template< class T> struct forward_type { typedef T type; };
+
+ }}
+
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_CORE_HPP
diff --git a/include/boost/move/default_delete.hpp b/include/boost/move/default_delete.hpp
new file mode 100644
index 0000000..31ae67a
--- /dev/null
+++ b/include/boost/move/default_delete.hpp
@@ -0,0 +1,217 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_DEFAULT_DELETE_HPP_INCLUDED
+#define BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+#include <boost/move/detail/unique_ptr_meta_utils.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/static_assert.hpp>
+
+#include <cstddef> //For std::size_t,std::nullptr_t
+
+//!\file
+//! Describes the default deleter (destruction policy) of <tt>unique_ptr</tt>: <tt>default_delete</tt>.
+
+namespace boost{
+// @cond
+namespace move_upd {
+
+namespace bmupmu = ::boost::move_upmu;
+
+////////////////////////////////////////
+//// enable_def_del
+////////////////////////////////////////
+
+//compatible with a pointer type T*:
+//When either Y* is convertible to T*
+//Y is U[N] and T is U cv []
+template<class U, class T>
+struct def_del_compatible_cond
+ : bmupmu::is_convertible<U*, T*>
+{};
+
+template<class U, class T, std::size_t N>
+struct def_del_compatible_cond<U[N], T[]>
+ : def_del_compatible_cond<U[], T[]>
+{};
+
+template<class U, class T, class Type = bmupmu::nat>
+struct enable_def_del
+ : bmupmu::enable_if_c<def_del_compatible_cond<U, T>::value, Type>
+{};
+
+////////////////////////////////////////
+//// enable_defdel_call
+////////////////////////////////////////
+
+//When 2nd is T[N], 1st(*)[N] shall be convertible to T(*)[N];
+//When 2nd is T[], 1st(*)[] shall be convertible to T(*)[];
+//Otherwise, 1st* shall be convertible to 2nd*.
+
+template<class U, class T, class Type = bmupmu::nat>
+struct enable_defdel_call
+ : public enable_def_del<U, T, Type>
+{};
+
+template<class U, class T, class Type>
+struct enable_defdel_call<U, T[], Type>
+ : public enable_def_del<U[], T[], Type>
+{};
+
+template<class U, class T, class Type, std::size_t N>
+struct enable_defdel_call<U, T[N], Type>
+ : public enable_def_del<U[N], T[N], Type>
+{};
+
+////////////////////////////////////////
+//// Some bool literal zero conversion utilities
+////////////////////////////////////////
+
+struct bool_conversion {int for_bool; int for_arg(); };
+typedef int bool_conversion::* explicit_bool_arg;
+
+#if !defined(BOOST_NO_CXX11_NULLPTR) && !defined(BOOST_NO_CXX11_DECLTYPE)
+ typedef decltype(nullptr) nullptr_type;
+#elif !defined(BOOST_NO_CXX11_NULLPTR)
+ typedef std::nullptr_t nullptr_type;
+#else
+ typedef int (bool_conversion::*nullptr_type)();
+#endif
+
+template<bool B>
+struct is_array_del
+{};
+
+template<class T>
+void call_delete(T *p, is_array_del<true>)
+{
+ delete [] p;
+}
+
+template<class T>
+void call_delete(T *p, is_array_del<false>)
+{
+ delete p;
+}
+
+} //namespace move_upd {
+// @endcond
+
+namespace movelib {
+
+namespace bmupd = boost::move_upd;
+namespace bmupmu = ::boost::move_upmu;
+
+//!The class template <tt>default_delete</tt> serves as the default deleter
+//!(destruction policy) for the class template <tt>unique_ptr</tt>.
+//!
+//! \tparam T The type to be deleted. It may be an incomplete type
+template <class T>
+struct default_delete
+{
+ //! Default constructor.
+ //!
+ BOOST_CONSTEXPR default_delete()
+ //Avoid "defaulted on its first declaration must not have an exception-specification" error for GCC 4.6
+ #if !defined(BOOST_GCC) || (BOOST_GCC < 40600 && BOOST_GCC >= 40700) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ BOOST_NOEXCEPT
+ #endif
+ #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ = default;
+ #else
+ {};
+ #endif
+
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ //! Trivial copy constructor
+ //!
+ default_delete(const default_delete&) BOOST_NOEXCEPT = default;
+ //! Trivial assignment
+ //!
+ default_delete &operator=(const default_delete&) BOOST_NOEXCEPT = default;
+ #else
+ typedef typename bmupmu::remove_extent<T>::type element_type;
+ #endif
+
+ //! <b>Effects</b>: Constructs a default_delete object from another <tt>default_delete<U></tt> object.
+ //!
+ //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
+ //! - If T is not an array type and U* is implicitly convertible to T*.
+ //! - If T is an array type and U* is a more CV qualified pointer to remove_extent<T>::type.
+ template <class U>
+ default_delete(const default_delete<U>&
+ BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_def_del<U BOOST_MOVE_I T>::type* =0)
+ ) BOOST_NOEXCEPT
+ {
+ //If T is not an array type, U derives from T
+ //and T has no virtual destructor, then you have a problem
+ BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
+ }
+
+ //! <b>Effects</b>: Constructs a default_delete object from another <tt>default_delete<U></tt> object.
+ //!
+ //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
+ //! - If T is not an array type and U* is implicitly convertible to T*.
+ //! - If T is an array type and U* is a more CV qualified pointer to remove_extent<T>::type.
+ template <class U>
+ BOOST_MOVE_DOC1ST(default_delete&,
+ typename bmupd::enable_def_del<U BOOST_MOVE_I T BOOST_MOVE_I default_delete &>::type)
+ operator=(const default_delete<U>&) BOOST_NOEXCEPT
+ {
+ //If T is not an array type, U derives from T
+ //and T has no virtual destructor, then you have a problem
+ BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
+ return *this;
+ }
+
+ //! <b>Effects</b>: if T is not an array type, calls <tt>delete</tt> on static_cast<T*>(ptr),
+ //! otherwise calls <tt>delete[]</tt> on static_cast<remove_extent<T>::type*>(ptr).
+ //!
+ //! <b>Remarks</b>: If U is an incomplete type, the program is ill-formed.
+ //! This operator shall not participate in overload resolution unless:
+ //! - T is not an array type and U* is convertible to T*, OR
+ //! - T is an array type, and remove_cv<U>::type is the same type as
+ //! remove_cv<remove_extent<T>::type>::type and U* is convertible to remove_extent<T>::type*.
+ template <class U>
+ BOOST_MOVE_DOC1ST(void, typename bmupd::enable_defdel_call<U BOOST_MOVE_I T BOOST_MOVE_I void>::type)
+ operator()(U* ptr) const BOOST_NOEXCEPT
+ {
+ //U must be a complete type
+ BOOST_STATIC_ASSERT(sizeof(U) > 0);
+ //If T is not an array type, U derives from T
+ //and T has no virtual destructor, then you have a problem
+ BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
+ element_type * const p = static_cast<element_type*>(ptr);
+ move_upd::call_delete(p, move_upd::is_array_del<bmupmu::is_array<T>::value>());
+ }
+
+ //! <b>Effects</b>: Same as <tt>(*this)(static_cast<element_type*>(nullptr))</tt>.
+ //!
+ void operator()(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) const BOOST_NOEXCEPT
+ { BOOST_STATIC_ASSERT(sizeof(element_type) > 0); }
+};
+
+} //namespace movelib {
+} //namespace boost{
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED
diff --git a/include/boost/move/detail/config_begin.hpp b/include/boost/move/detail/config_begin.hpp
new file mode 100644
index 0000000..637eb15
--- /dev/null
+++ b/include/boost/move/detail/config_begin.hpp
@@ -0,0 +1,21 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONFIG_HPP
+#include <boost/config.hpp>
+#endif
+
+#ifdef BOOST_MSVC
+# pragma warning (push)
+# pragma warning (disable : 4324) // structure was padded due to __declspec(align())
+# pragma warning (disable : 4675) // "function": resolved overload was found by argument-dependent lookup
+# pragma warning (disable : 4996) // "function": was declared deprecated (_CRT_SECURE_NO_DEPRECATE/_SCL_SECURE_NO_WARNINGS)
+# pragma warning (disable : 4714) // "function": marked as __forceinline not inlined
+# pragma warning (disable : 4127) // conditional expression is constant
+#endif
diff --git a/include/boost/move/detail/config_end.hpp b/include/boost/move/detail/config_end.hpp
new file mode 100644
index 0000000..71a99e9
--- /dev/null
+++ b/include/boost/move/detail/config_end.hpp
@@ -0,0 +1,12 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+#if defined BOOST_MSVC
+# pragma warning (pop)
+#endif
diff --git a/include/boost/move/detail/destruct_n.hpp b/include/boost/move/detail/destruct_n.hpp
new file mode 100644
index 0000000..9f60fc2
--- /dev/null
+++ b/include/boost/move/detail/destruct_n.hpp
@@ -0,0 +1,66 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
+#define BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <cstddef>
+
+namespace boost {
+namespace movelib{
+
+template<class T, class RandItUninit>
+class destruct_n
+{
+ public:
+ explicit destruct_n(RandItUninit raw)
+ : m_ptr(raw), m_size()
+ {}
+
+ void incr()
+ {
+ ++m_size;
+ }
+
+ void incr(std::size_t n)
+ {
+ m_size += n;
+ }
+
+ void release()
+ {
+ m_size = 0u;
+ }
+
+ ~destruct_n()
+ {
+ while(m_size--){
+ m_ptr[m_size].~T();
+ }
+ }
+ private:
+ RandItUninit m_ptr;
+ std::size_t m_size;
+};
+
+}} //namespace boost { namespace movelib{
+
+#endif //#ifndef BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
diff --git a/include/boost/move/detail/fwd_macros.hpp b/include/boost/move/detail/fwd_macros.hpp
new file mode 100644
index 0000000..a5df5f1
--- /dev/null
+++ b/include/boost/move/detail/fwd_macros.hpp
@@ -0,0 +1,881 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_DETAIL_FWD_MACROS_HPP
+#define BOOST_MOVE_DETAIL_FWD_MACROS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/workaround.hpp>
+
+namespace boost {
+namespace move_detail {
+
+template <typename T> struct unvoid { typedef T type; };
+template <> struct unvoid<void> { struct type { }; };
+template <> struct unvoid<const void> { struct type { }; };
+
+} //namespace move_detail {
+} //namespace boost {
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+namespace boost {
+namespace move_detail {
+
+ template<class T>
+ struct mref;
+
+ template<class T>
+ struct mref<T &>
+ {
+ explicit mref(T &t) : t_(t){}
+ T &t_;
+ T & get() { return t_; }
+ };
+
+ template<class T>
+ struct mref
+ {
+ explicit mref(T &&t) : t_(t) {}
+ T &t_;
+ T &&get() { return ::boost::move(t_); }
+ };
+
+} //namespace move_detail {
+} //namespace boost {
+
+#endif //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
+#endif //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+//BOOST_MOVE_REPEATN(MACRO)
+#define BOOST_MOVE_REPEAT(x, MACRO) BOOST_MOVE_REPEAT_I(x,MACRO)
+#define BOOST_MOVE_REPEAT_I(x, MACRO) BOOST_MOVE_REPEAT##x(MACRO)
+#define BOOST_MOVE_REPEAT0(MACRO)
+#define BOOST_MOVE_REPEAT1(MACRO) MACRO
+#define BOOST_MOVE_REPEAT2(MACRO) BOOST_MOVE_REPEAT1(MACRO), MACRO
+#define BOOST_MOVE_REPEAT3(MACRO) BOOST_MOVE_REPEAT2(MACRO), MACRO
+#define BOOST_MOVE_REPEAT4(MACRO) BOOST_MOVE_REPEAT3(MACRO), MACRO
+#define BOOST_MOVE_REPEAT5(MACRO) BOOST_MOVE_REPEAT4(MACRO), MACRO
+#define BOOST_MOVE_REPEAT6(MACRO) BOOST_MOVE_REPEAT5(MACRO), MACRO
+#define BOOST_MOVE_REPEAT7(MACRO) BOOST_MOVE_REPEAT6(MACRO), MACRO
+#define BOOST_MOVE_REPEAT8(MACRO) BOOST_MOVE_REPEAT7(MACRO), MACRO
+#define BOOST_MOVE_REPEAT9(MACRO) BOOST_MOVE_REPEAT8(MACRO), MACRO
+#define BOOST_MOVE_REPEAT10(MACRO) BOOST_MOVE_REPEAT9(MACRO), MACRO
+#define BOOST_MOVE_REPEAT11(MACRO) BOOST_MOVE_REPEAT10(MACRO), MACRO
+#define BOOST_MOVE_REPEAT12(MACRO) BOOST_MOVE_REPEAT11(MACRO), MACRO
+#define BOOST_MOVE_REPEAT13(MACRO) BOOST_MOVE_REPEAT12(MACRO), MACRO
+
+//BOOST_MOVE_FWDN
+#define BOOST_MOVE_FWD0
+#define BOOST_MOVE_FWD1 ::boost::forward<P0>(p0)
+#define BOOST_MOVE_FWD2 BOOST_MOVE_FWD1, ::boost::forward<P1>(p1)
+#define BOOST_MOVE_FWD3 BOOST_MOVE_FWD2, ::boost::forward<P2>(p2)
+#define BOOST_MOVE_FWD4 BOOST_MOVE_FWD3, ::boost::forward<P3>(p3)
+#define BOOST_MOVE_FWD5 BOOST_MOVE_FWD4, ::boost::forward<P4>(p4)
+#define BOOST_MOVE_FWD6 BOOST_MOVE_FWD5, ::boost::forward<P5>(p5)
+#define BOOST_MOVE_FWD7 BOOST_MOVE_FWD6, ::boost::forward<P6>(p6)
+#define BOOST_MOVE_FWD8 BOOST_MOVE_FWD7, ::boost::forward<P7>(p7)
+#define BOOST_MOVE_FWD9 BOOST_MOVE_FWD8, ::boost::forward<P8>(p8)
+
+//BOOST_MOVE_FWDQN
+#define BOOST_MOVE_FWDQ0
+#define BOOST_MOVE_FWDQ1 ::boost::forward<Q0>(q0)
+#define BOOST_MOVE_FWDQ2 BOOST_MOVE_FWDQ1, ::boost::forward<Q1>(q1)
+#define BOOST_MOVE_FWDQ3 BOOST_MOVE_FWDQ2, ::boost::forward<Q2>(q2)
+#define BOOST_MOVE_FWDQ4 BOOST_MOVE_FWDQ3, ::boost::forward<Q3>(q3)
+#define BOOST_MOVE_FWDQ5 BOOST_MOVE_FWDQ4, ::boost::forward<Q4>(q4)
+#define BOOST_MOVE_FWDQ6 BOOST_MOVE_FWDQ5, ::boost::forward<Q5>(q5)
+#define BOOST_MOVE_FWDQ7 BOOST_MOVE_FWDQ6, ::boost::forward<Q6>(q6)
+#define BOOST_MOVE_FWDQ8 BOOST_MOVE_FWDQ7, ::boost::forward<Q7>(q7)
+#define BOOST_MOVE_FWDQ9 BOOST_MOVE_FWDQ8, ::boost::forward<Q8>(q8)
+
+//BOOST_MOVE_TMPL_GETN
+#define BOOST_MOVE_TMPL_GET0
+#define BOOST_MOVE_TMPL_GET1 p.template get<0>()
+#define BOOST_MOVE_TMPL_GET2 BOOST_MOVE_TMPL_GET1, p.template get<1>()
+#define BOOST_MOVE_TMPL_GET3 BOOST_MOVE_TMPL_GET2, p.template get<2>()
+#define BOOST_MOVE_TMPL_GET4 BOOST_MOVE_TMPL_GET3, p.template get<3>()
+#define BOOST_MOVE_TMPL_GET5 BOOST_MOVE_TMPL_GET4, p.template get<4>()
+#define BOOST_MOVE_TMPL_GET6 BOOST_MOVE_TMPL_GET5, p.template get<5>()
+#define BOOST_MOVE_TMPL_GET7 BOOST_MOVE_TMPL_GET6, p.template get<6>()
+#define BOOST_MOVE_TMPL_GET8 BOOST_MOVE_TMPL_GET7, p.template get<7>()
+#define BOOST_MOVE_TMPL_GET9 BOOST_MOVE_TMPL_GET8, p.template get<8>()
+
+//BOOST_MOVE_TMPL_GETQN
+#define BOOST_MOVE_TMPL_GETQ0
+#define BOOST_MOVE_TMPL_GETQ1 q.template get<0>()
+#define BOOST_MOVE_TMPL_GETQ2 BOOST_MOVE_TMPL_GETQ1, q.template get<1>()
+#define BOOST_MOVE_TMPL_GETQ3 BOOST_MOVE_TMPL_GETQ2, q.template get<2>()
+#define BOOST_MOVE_TMPL_GETQ4 BOOST_MOVE_TMPL_GETQ3, q.template get<3>()
+#define BOOST_MOVE_TMPL_GETQ5 BOOST_MOVE_TMPL_GETQ4, q.template get<4>()
+#define BOOST_MOVE_TMPL_GETQ6 BOOST_MOVE_TMPL_GETQ5, q.template get<5>()
+#define BOOST_MOVE_TMPL_GETQ7 BOOST_MOVE_TMPL_GETQ6, q.template get<6>()
+#define BOOST_MOVE_TMPL_GETQ8 BOOST_MOVE_TMPL_GETQ7, q.template get<7>()
+#define BOOST_MOVE_TMPL_GETQ9 BOOST_MOVE_TMPL_GETQ8, q.template get<8>()
+
+//BOOST_MOVE_GET_IDXN
+#define BOOST_MOVE_GET_IDX0
+#define BOOST_MOVE_GET_IDX1 get<0>(p)
+#define BOOST_MOVE_GET_IDX2 BOOST_MOVE_GET_IDX1, get<1>(p)
+#define BOOST_MOVE_GET_IDX3 BOOST_MOVE_GET_IDX2, get<2>(p)
+#define BOOST_MOVE_GET_IDX4 BOOST_MOVE_GET_IDX3, get<3>(p)
+#define BOOST_MOVE_GET_IDX5 BOOST_MOVE_GET_IDX4, get<4>(p)
+#define BOOST_MOVE_GET_IDX6 BOOST_MOVE_GET_IDX5, get<5>(p)
+#define BOOST_MOVE_GET_IDX7 BOOST_MOVE_GET_IDX6, get<6>(p)
+#define BOOST_MOVE_GET_IDX8 BOOST_MOVE_GET_IDX7, get<7>(p)
+#define BOOST_MOVE_GET_IDX9 BOOST_MOVE_GET_IDX8, get<8>(p)
+
+//BOOST_MOVE_GET_IDXQN
+#define BOOST_MOVE_GET_IDXQ0
+#define BOOST_MOVE_GET_IDXQ1 get<0>(q)
+#define BOOST_MOVE_GET_IDXQ2 BOOST_MOVE_GET_IDXQ1, get<1>(q)
+#define BOOST_MOVE_GET_IDXQ3 BOOST_MOVE_GET_IDXQ2, get<2>(q)
+#define BOOST_MOVE_GET_IDXQ4 BOOST_MOVE_GET_IDXQ3, get<3>(q)
+#define BOOST_MOVE_GET_IDXQ5 BOOST_MOVE_GET_IDXQ4, get<4>(q)
+#define BOOST_MOVE_GET_IDXQ6 BOOST_MOVE_GET_IDXQ5, get<5>(q)
+#define BOOST_MOVE_GET_IDXQ7 BOOST_MOVE_GET_IDXQ6, get<6>(q)
+#define BOOST_MOVE_GET_IDXQ8 BOOST_MOVE_GET_IDXQ7, get<7>(q)
+#define BOOST_MOVE_GET_IDXQ9 BOOST_MOVE_GET_IDXQ8, get<8>(q)
+
+//BOOST_MOVE_ARGN
+#define BOOST_MOVE_ARG0
+#define BOOST_MOVE_ARG1 p0
+#define BOOST_MOVE_ARG2 BOOST_MOVE_ARG1, p1
+#define BOOST_MOVE_ARG3 BOOST_MOVE_ARG2, p2
+#define BOOST_MOVE_ARG4 BOOST_MOVE_ARG3, p3
+#define BOOST_MOVE_ARG5 BOOST_MOVE_ARG4, p4
+#define BOOST_MOVE_ARG6 BOOST_MOVE_ARG5, p5
+#define BOOST_MOVE_ARG7 BOOST_MOVE_ARG6, p6
+#define BOOST_MOVE_ARG8 BOOST_MOVE_ARG7, p7
+#define BOOST_MOVE_ARG9 BOOST_MOVE_ARG8, p8
+
+//BOOST_MOVE_ARGQN
+#define BOOST_MOVE_ARGQ0
+#define BOOST_MOVE_ARGQ1 q0
+#define BOOST_MOVE_ARGQ2 BOOST_MOVE_ARGQ1, q1
+#define BOOST_MOVE_ARGQ3 BOOST_MOVE_ARGQ2, q2
+#define BOOST_MOVE_ARGQ4 BOOST_MOVE_ARGQ3, q3
+#define BOOST_MOVE_ARGQ5 BOOST_MOVE_ARGQ4, q4
+#define BOOST_MOVE_ARGQ6 BOOST_MOVE_ARGQ5, q5
+#define BOOST_MOVE_ARGQ7 BOOST_MOVE_ARGQ6, q6
+#define BOOST_MOVE_ARGQ8 BOOST_MOVE_ARGQ7, q7
+#define BOOST_MOVE_ARGQ9 BOOST_MOVE_ARGQ8, q8
+
+//BOOST_MOVE_DECLVALN
+#define BOOST_MOVE_DECLVAL0
+#define BOOST_MOVE_DECLVAL1 ::boost::move_detail::declval<P0>()
+#define BOOST_MOVE_DECLVAL2 BOOST_MOVE_DECLVAL1, ::boost::move_detail::declval<P1>()
+#define BOOST_MOVE_DECLVAL3 BOOST_MOVE_DECLVAL2, ::boost::move_detail::declval<P2>()
+#define BOOST_MOVE_DECLVAL4 BOOST_MOVE_DECLVAL3, ::boost::move_detail::declval<P3>()
+#define BOOST_MOVE_DECLVAL5 BOOST_MOVE_DECLVAL4, ::boost::move_detail::declval<P4>()
+#define BOOST_MOVE_DECLVAL6 BOOST_MOVE_DECLVAL5, ::boost::move_detail::declval<P5>()
+#define BOOST_MOVE_DECLVAL7 BOOST_MOVE_DECLVAL6, ::boost::move_detail::declval<P6>()
+#define BOOST_MOVE_DECLVAL8 BOOST_MOVE_DECLVAL7, ::boost::move_detail::declval<P7>()
+#define BOOST_MOVE_DECLVAL9 BOOST_MOVE_DECLVAL8, ::boost::move_detail::declval<P8>()
+
+//BOOST_MOVE_DECLVALQN
+#define BOOST_MOVE_DECLVALQ0
+#define BOOST_MOVE_DECLVALQ1 ::boost::move_detail::declval<Q0>()
+#define BOOST_MOVE_DECLVALQ2 BOOST_MOVE_DECLVALQ1, ::boost::move_detail::declval<Q1>()
+#define BOOST_MOVE_DECLVALQ3 BOOST_MOVE_DECLVALQ2, ::boost::move_detail::declval<Q2>()
+#define BOOST_MOVE_DECLVALQ4 BOOST_MOVE_DECLVALQ3, ::boost::move_detail::declval<Q3>()
+#define BOOST_MOVE_DECLVALQ5 BOOST_MOVE_DECLVALQ4, ::boost::move_detail::declval<Q4>()
+#define BOOST_MOVE_DECLVALQ6 BOOST_MOVE_DECLVALQ5, ::boost::move_detail::declval<Q5>()
+#define BOOST_MOVE_DECLVALQ7 BOOST_MOVE_DECLVALQ6, ::boost::move_detail::declval<Q6>()
+#define BOOST_MOVE_DECLVALQ8 BOOST_MOVE_DECLVALQ7, ::boost::move_detail::declval<Q7>()
+#define BOOST_MOVE_DECLVALQ9 BOOST_MOVE_DECLVALQ8, ::boost::move_detail::declval<Q8>()
+
+#ifdef BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
+ #define BOOST_MOVE_MREF(T) ::boost::move_detail::mref<T>
+ #define BOOST_MOVE_MFWD(N) ::boost::forward<P##N>(this->m_p##N.get())
+ #define BOOST_MOVE_MFWDQ(N) ::boost::forward<Q##N>(this->m_q##N.get())
+#else
+ #define BOOST_MOVE_MREF(T) BOOST_FWD_REF(T)
+ #define BOOST_MOVE_MFWD(N) ::boost::forward<P##N>(this->m_p##N)
+ #define BOOST_MOVE_MFWDQ(N) ::boost::forward<Q##N>(this->m_q##N)
+#endif
+#define BOOST_MOVE_MITFWD(N) *this->m_p##N
+#define BOOST_MOVE_MINC(N) ++this->m_p##N
+#define BOOST_MOVE_MITFWDQ(N) *this->m_q##N
+#define BOOST_MOVE_MINCQ(N) ++this->m_q##N
+
+
+//BOOST_MOVE_MFWDN
+#define BOOST_MOVE_MFWD0
+#define BOOST_MOVE_MFWD1 BOOST_MOVE_MFWD(0)
+#define BOOST_MOVE_MFWD2 BOOST_MOVE_MFWD1, BOOST_MOVE_MFWD(1)
+#define BOOST_MOVE_MFWD3 BOOST_MOVE_MFWD2, BOOST_MOVE_MFWD(2)
+#define BOOST_MOVE_MFWD4 BOOST_MOVE_MFWD3, BOOST_MOVE_MFWD(3)
+#define BOOST_MOVE_MFWD5 BOOST_MOVE_MFWD4, BOOST_MOVE_MFWD(4)
+#define BOOST_MOVE_MFWD6 BOOST_MOVE_MFWD5, BOOST_MOVE_MFWD(5)
+#define BOOST_MOVE_MFWD7 BOOST_MOVE_MFWD6, BOOST_MOVE_MFWD(6)
+#define BOOST_MOVE_MFWD8 BOOST_MOVE_MFWD7, BOOST_MOVE_MFWD(7)
+#define BOOST_MOVE_MFWD9 BOOST_MOVE_MFWD8, BOOST_MOVE_MFWD(8)
+
+//BOOST_MOVE_MFWDN
+#define BOOST_MOVE_MFWDQ0
+#define BOOST_MOVE_MFWDQ1 BOOST_MOVE_MFWDQ(0)
+#define BOOST_MOVE_MFWDQ2 BOOST_MOVE_MFWDQ1, BOOST_MOVE_MFWDQ(1)
+#define BOOST_MOVE_MFWDQ3 BOOST_MOVE_MFWDQ2, BOOST_MOVE_MFWDQ(2)
+#define BOOST_MOVE_MFWDQ4 BOOST_MOVE_MFWDQ3, BOOST_MOVE_MFWDQ(3)
+#define BOOST_MOVE_MFWDQ5 BOOST_MOVE_MFWDQ4, BOOST_MOVE_MFWDQ(4)
+#define BOOST_MOVE_MFWDQ6 BOOST_MOVE_MFWDQ5, BOOST_MOVE_MFWDQ(5)
+#define BOOST_MOVE_MFWDQ7 BOOST_MOVE_MFWDQ6, BOOST_MOVE_MFWDQ(6)
+#define BOOST_MOVE_MFWDQ8 BOOST_MOVE_MFWDQ7, BOOST_MOVE_MFWDQ(7)
+#define BOOST_MOVE_MFWDQ9 BOOST_MOVE_MFWDQ8, BOOST_MOVE_MFWDQ(8)
+
+//BOOST_MOVE_MINCN
+#define BOOST_MOVE_MINC0
+#define BOOST_MOVE_MINC1 BOOST_MOVE_MINC(0)
+#define BOOST_MOVE_MINC2 BOOST_MOVE_MINC1, BOOST_MOVE_MINC(1)
+#define BOOST_MOVE_MINC3 BOOST_MOVE_MINC2, BOOST_MOVE_MINC(2)
+#define BOOST_MOVE_MINC4 BOOST_MOVE_MINC3, BOOST_MOVE_MINC(3)
+#define BOOST_MOVE_MINC5 BOOST_MOVE_MINC4, BOOST_MOVE_MINC(4)
+#define BOOST_MOVE_MINC6 BOOST_MOVE_MINC5, BOOST_MOVE_MINC(5)
+#define BOOST_MOVE_MINC7 BOOST_MOVE_MINC6, BOOST_MOVE_MINC(6)
+#define BOOST_MOVE_MINC8 BOOST_MOVE_MINC7, BOOST_MOVE_MINC(7)
+#define BOOST_MOVE_MINC9 BOOST_MOVE_MINC8, BOOST_MOVE_MINC(8)
+
+//BOOST_MOVE_MINCQN
+#define BOOST_MOVE_MINCQ0
+#define BOOST_MOVE_MINCQ1 BOOST_MOVE_MINCQ(0)
+#define BOOST_MOVE_MINCQ2 BOOST_MOVE_MINCQ1, BOOST_MOVE_MINCQ(1)
+#define BOOST_MOVE_MINCQ3 BOOST_MOVE_MINCQ2, BOOST_MOVE_MINCQ(2)
+#define BOOST_MOVE_MINCQ4 BOOST_MOVE_MINCQ3, BOOST_MOVE_MINCQ(3)
+#define BOOST_MOVE_MINCQ5 BOOST_MOVE_MINCQ4, BOOST_MOVE_MINCQ(4)
+#define BOOST_MOVE_MINCQ6 BOOST_MOVE_MINCQ5, BOOST_MOVE_MINCQ(5)
+#define BOOST_MOVE_MINCQ7 BOOST_MOVE_MINCQ6, BOOST_MOVE_MINCQ(6)
+#define BOOST_MOVE_MINCQ8 BOOST_MOVE_MINCQ7, BOOST_MOVE_MINCQ(7)
+#define BOOST_MOVE_MINCQ9 BOOST_MOVE_MINCQ8, BOOST_MOVE_MINCQ(8)
+
+//BOOST_MOVE_MITFWDN
+#define BOOST_MOVE_MITFWD0
+#define BOOST_MOVE_MITFWD1 BOOST_MOVE_MITFWD(0)
+#define BOOST_MOVE_MITFWD2 BOOST_MOVE_MITFWD1, BOOST_MOVE_MITFWD(1)
+#define BOOST_MOVE_MITFWD3 BOOST_MOVE_MITFWD2, BOOST_MOVE_MITFWD(2)
+#define BOOST_MOVE_MITFWD4 BOOST_MOVE_MITFWD3, BOOST_MOVE_MITFWD(3)
+#define BOOST_MOVE_MITFWD5 BOOST_MOVE_MITFWD4, BOOST_MOVE_MITFWD(4)
+#define BOOST_MOVE_MITFWD6 BOOST_MOVE_MITFWD5, BOOST_MOVE_MITFWD(5)
+#define BOOST_MOVE_MITFWD7 BOOST_MOVE_MITFWD6, BOOST_MOVE_MITFWD(6)
+#define BOOST_MOVE_MITFWD8 BOOST_MOVE_MITFWD7, BOOST_MOVE_MITFWD(7)
+#define BOOST_MOVE_MITFWD9 BOOST_MOVE_MITFWD8, BOOST_MOVE_MITFWD(8)
+
+//BOOST_MOVE_MITFWDQN
+#define BOOST_MOVE_MITFWDQ0
+#define BOOST_MOVE_MITFWDQ1 BOOST_MOVE_MITFWDQ(0)
+#define BOOST_MOVE_MITFWDQ2 BOOST_MOVE_MITFWDQ1, BOOST_MOVE_MITFWDQ(1)
+#define BOOST_MOVE_MITFWDQ3 BOOST_MOVE_MITFWDQ2, BOOST_MOVE_MITFWDQ(2)
+#define BOOST_MOVE_MITFWDQ4 BOOST_MOVE_MITFWDQ3, BOOST_MOVE_MITFWDQ(3)
+#define BOOST_MOVE_MITFWDQ5 BOOST_MOVE_MITFWDQ4, BOOST_MOVE_MITFWDQ(4)
+#define BOOST_MOVE_MITFWDQ6 BOOST_MOVE_MITFWDQ5, BOOST_MOVE_MITFWDQ(5)
+#define BOOST_MOVE_MITFWDQ7 BOOST_MOVE_MITFWDQ6, BOOST_MOVE_MITFWDQ(6)
+#define BOOST_MOVE_MITFWDQ8 BOOST_MOVE_MITFWDQ7, BOOST_MOVE_MITFWDQ(7)
+#define BOOST_MOVE_MITFWDQ9 BOOST_MOVE_MITFWDQ8, BOOST_MOVE_MITFWDQ(8)
+
+//BOOST_MOVE_FWD_INITN
+#define BOOST_MOVE_FWD_INIT0
+#define BOOST_MOVE_FWD_INIT1 m_p0(::boost::forward<P0>(p0))
+#define BOOST_MOVE_FWD_INIT2 BOOST_MOVE_FWD_INIT1, m_p1(::boost::forward<P1>(p1))
+#define BOOST_MOVE_FWD_INIT3 BOOST_MOVE_FWD_INIT2, m_p2(::boost::forward<P2>(p2))
+#define BOOST_MOVE_FWD_INIT4 BOOST_MOVE_FWD_INIT3, m_p3(::boost::forward<P3>(p3))
+#define BOOST_MOVE_FWD_INIT5 BOOST_MOVE_FWD_INIT4, m_p4(::boost::forward<P4>(p4))
+#define BOOST_MOVE_FWD_INIT6 BOOST_MOVE_FWD_INIT5, m_p5(::boost::forward<P5>(p5))
+#define BOOST_MOVE_FWD_INIT7 BOOST_MOVE_FWD_INIT6, m_p6(::boost::forward<P6>(p6))
+#define BOOST_MOVE_FWD_INIT8 BOOST_MOVE_FWD_INIT7, m_p7(::boost::forward<P7>(p7))
+#define BOOST_MOVE_FWD_INIT9 BOOST_MOVE_FWD_INIT8, m_p8(::boost::forward<P8>(p8))
+
+//BOOST_MOVE_FWD_INITQN
+#define BOOST_MOVE_FWD_INITQ0
+#define BOOST_MOVE_FWD_INITQ1 m_q0(::boost::forward<Q0>(q0))
+#define BOOST_MOVE_FWD_INITQ2 BOOST_MOVE_FWD_INITQ1, m_q1(::boost::forward<Q1>(q1))
+#define BOOST_MOVE_FWD_INITQ3 BOOST_MOVE_FWD_INITQ2, m_q2(::boost::forward<Q2>(q2))
+#define BOOST_MOVE_FWD_INITQ4 BOOST_MOVE_FWD_INITQ3, m_q3(::boost::forward<Q3>(q3))
+#define BOOST_MOVE_FWD_INITQ5 BOOST_MOVE_FWD_INITQ4, m_q4(::boost::forward<Q4>(q4))
+#define BOOST_MOVE_FWD_INITQ6 BOOST_MOVE_FWD_INITQ5, m_q5(::boost::forward<Q5>(q5))
+#define BOOST_MOVE_FWD_INITQ7 BOOST_MOVE_FWD_INITQ6, m_q6(::boost::forward<Q6>(q6))
+#define BOOST_MOVE_FWD_INITQ8 BOOST_MOVE_FWD_INITQ7, m_q7(::boost::forward<Q7>(q7))
+#define BOOST_MOVE_FWD_INITQ9 BOOST_MOVE_FWD_INITQ8, m_q8(::boost::forward<Q8>(q8))
+
+//BOOST_MOVE_VAL_INITN
+#define BOOST_MOVE_VAL_INIT0
+#define BOOST_MOVE_VAL_INIT1 m_p0(p0)
+#define BOOST_MOVE_VAL_INIT2 BOOST_MOVE_VAL_INIT1, m_p1(p1)
+#define BOOST_MOVE_VAL_INIT3 BOOST_MOVE_VAL_INIT2, m_p2(p2)
+#define BOOST_MOVE_VAL_INIT4 BOOST_MOVE_VAL_INIT3, m_p3(p3)
+#define BOOST_MOVE_VAL_INIT5 BOOST_MOVE_VAL_INIT4, m_p4(p4)
+#define BOOST_MOVE_VAL_INIT6 BOOST_MOVE_VAL_INIT5, m_p5(p5)
+#define BOOST_MOVE_VAL_INIT7 BOOST_MOVE_VAL_INIT6, m_p6(p6)
+#define BOOST_MOVE_VAL_INIT8 BOOST_MOVE_VAL_INIT7, m_p7(p7)
+#define BOOST_MOVE_VAL_INIT9 BOOST_MOVE_VAL_INIT8, m_p8(p8)
+
+//BOOST_MOVE_VAL_INITQN
+#define BOOST_MOVE_VAL_INITQ0
+#define BOOST_MOVE_VAL_INITQ1 m_q0(q0)
+#define BOOST_MOVE_VAL_INITQ2 BOOST_MOVE_VAL_INITQ1, m_q1(q1)
+#define BOOST_MOVE_VAL_INITQ3 BOOST_MOVE_VAL_INITQ2, m_q2(q2)
+#define BOOST_MOVE_VAL_INITQ4 BOOST_MOVE_VAL_INITQ3, m_q3(q3)
+#define BOOST_MOVE_VAL_INITQ5 BOOST_MOVE_VAL_INITQ4, m_q4(q4)
+#define BOOST_MOVE_VAL_INITQ6 BOOST_MOVE_VAL_INITQ5, m_q5(q5)
+#define BOOST_MOVE_VAL_INITQ7 BOOST_MOVE_VAL_INITQ6, m_q6(q6)
+#define BOOST_MOVE_VAL_INITQ8 BOOST_MOVE_VAL_INITQ7, m_q7(q7)
+#define BOOST_MOVE_VAL_INITQ9 BOOST_MOVE_VAL_INITQ8, m_q8(q8)
+
+//BOOST_MOVE_UREFN
+#define BOOST_MOVE_UREF0
+#define BOOST_MOVE_UREF1 BOOST_FWD_REF(P0) p0
+#define BOOST_MOVE_UREF2 BOOST_MOVE_UREF1, BOOST_FWD_REF(P1) p1
+#define BOOST_MOVE_UREF3 BOOST_MOVE_UREF2, BOOST_FWD_REF(P2) p2
+#define BOOST_MOVE_UREF4 BOOST_MOVE_UREF3, BOOST_FWD_REF(P3) p3
+#define BOOST_MOVE_UREF5 BOOST_MOVE_UREF4, BOOST_FWD_REF(P4) p4
+#define BOOST_MOVE_UREF6 BOOST_MOVE_UREF5, BOOST_FWD_REF(P5) p5
+#define BOOST_MOVE_UREF7 BOOST_MOVE_UREF6, BOOST_FWD_REF(P6) p6
+#define BOOST_MOVE_UREF8 BOOST_MOVE_UREF7, BOOST_FWD_REF(P7) p7
+#define BOOST_MOVE_UREF9 BOOST_MOVE_UREF8, BOOST_FWD_REF(P8) p8
+
+//BOOST_MOVE_UREFQN
+#define BOOST_MOVE_UREFQ0
+#define BOOST_MOVE_UREFQ1 BOOST_FWD_REF(Q0) q0
+#define BOOST_MOVE_UREFQ2 BOOST_MOVE_UREFQ1, BOOST_FWD_REF(Q1) q1
+#define BOOST_MOVE_UREFQ3 BOOST_MOVE_UREFQ2, BOOST_FWD_REF(Q2) q2
+#define BOOST_MOVE_UREFQ4 BOOST_MOVE_UREFQ3, BOOST_FWD_REF(Q3) q3
+#define BOOST_MOVE_UREFQ5 BOOST_MOVE_UREFQ4, BOOST_FWD_REF(Q4) q4
+#define BOOST_MOVE_UREFQ6 BOOST_MOVE_UREFQ5, BOOST_FWD_REF(Q5) q5
+#define BOOST_MOVE_UREFQ7 BOOST_MOVE_UREFQ6, BOOST_FWD_REF(Q6) q6
+#define BOOST_MOVE_UREFQ8 BOOST_MOVE_UREFQ7, BOOST_FWD_REF(Q7) q7
+#define BOOST_MOVE_UREFQ9 BOOST_MOVE_UREFQ8, BOOST_FWD_REF(Q8) q8
+
+//BOOST_MOVE_VALN
+#define BOOST_MOVE_VAL0
+#define BOOST_MOVE_VAL1 BOOST_FWD_REF(P0) p0
+#define BOOST_MOVE_VAL2 BOOST_MOVE_VAL1, BOOST_FWD_REF(P1) p1
+#define BOOST_MOVE_VAL3 BOOST_MOVE_VAL2, BOOST_FWD_REF(P2) p2
+#define BOOST_MOVE_VAL4 BOOST_MOVE_VAL3, BOOST_FWD_REF(P3) p3
+#define BOOST_MOVE_VAL5 BOOST_MOVE_VAL4, BOOST_FWD_REF(P4) p4
+#define BOOST_MOVE_VAL6 BOOST_MOVE_VAL5, BOOST_FWD_REF(P5) p5
+#define BOOST_MOVE_VAL7 BOOST_MOVE_VAL6, BOOST_FWD_REF(P6) p6
+#define BOOST_MOVE_VAL8 BOOST_MOVE_VAL7, BOOST_FWD_REF(P7) p7
+#define BOOST_MOVE_VAL9 BOOST_MOVE_VAL8, BOOST_FWD_REF(P8) p8
+
+//BOOST_MOVE_VALQN
+#define BOOST_MOVE_VALQ0
+#define BOOST_MOVE_VALQ1 BOOST_FWD_REF(Q0) q0
+#define BOOST_MOVE_VALQ2 BOOST_MOVE_VALQ1, BOOST_FWD_REF(Q1) q1
+#define BOOST_MOVE_VALQ3 BOOST_MOVE_VALQ2, BOOST_FWD_REF(Q2) q2
+#define BOOST_MOVE_VALQ4 BOOST_MOVE_VALQ3, BOOST_FWD_REF(Q3) q3
+#define BOOST_MOVE_VALQ5 BOOST_MOVE_VALQ4, BOOST_FWD_REF(Q4) q4
+#define BOOST_MOVE_VALQ6 BOOST_MOVE_VALQ5, BOOST_FWD_REF(Q5) q5
+#define BOOST_MOVE_VALQ7 BOOST_MOVE_VALQ6, BOOST_FWD_REF(Q6) q6
+#define BOOST_MOVE_VALQ8 BOOST_MOVE_VALQ7, BOOST_FWD_REF(Q7) q7
+#define BOOST_MOVE_VALQ9 BOOST_MOVE_VALQ8, BOOST_FWD_REF(Q8) q8
+
+
+#define BOOST_MOVE_UNVOIDCREF(T) const typename boost::move_detail::unvoid<T>::type&
+//BOOST_MOVE_CREFN
+#define BOOST_MOVE_CREF0
+#define BOOST_MOVE_CREF1 BOOST_MOVE_UNVOIDCREF(P0) p0
+#define BOOST_MOVE_CREF2 BOOST_MOVE_CREF1, BOOST_MOVE_UNVOIDCREF(P1) p1
+#define BOOST_MOVE_CREF3 BOOST_MOVE_CREF2, BOOST_MOVE_UNVOIDCREF(P2) p2
+#define BOOST_MOVE_CREF4 BOOST_MOVE_CREF3, BOOST_MOVE_UNVOIDCREF(P3) p3
+#define BOOST_MOVE_CREF5 BOOST_MOVE_CREF4, BOOST_MOVE_UNVOIDCREF(P4) p4
+#define BOOST_MOVE_CREF6 BOOST_MOVE_CREF5, BOOST_MOVE_UNVOIDCREF(P5) p5
+#define BOOST_MOVE_CREF7 BOOST_MOVE_CREF6, BOOST_MOVE_UNVOIDCREF(P6) p6
+#define BOOST_MOVE_CREF8 BOOST_MOVE_CREF7, BOOST_MOVE_UNVOIDCREF(P7) p7
+#define BOOST_MOVE_CREF9 BOOST_MOVE_CREF8, BOOST_MOVE_UNVOIDCREF(P8) p8
+
+//BOOST_MOVE_CREFQN
+#define BOOST_MOVE_CREFQ0
+#define BOOST_MOVE_CREFQ1 BOOST_MOVE_UNVOIDCREF(Q0) q0
+#define BOOST_MOVE_CREFQ2 BOOST_MOVE_CREFQ1, BOOST_MOVE_UNVOIDCREF(Q1) q1
+#define BOOST_MOVE_CREFQ3 BOOST_MOVE_CREFQ2, BOOST_MOVE_UNVOIDCREF(Q2) q2
+#define BOOST_MOVE_CREFQ4 BOOST_MOVE_CREFQ3, BOOST_MOVE_UNVOIDCREF(Q3) q3
+#define BOOST_MOVE_CREFQ5 BOOST_MOVE_CREFQ4, BOOST_MOVE_UNVOIDCREF(Q4) q4
+#define BOOST_MOVE_CREFQ6 BOOST_MOVE_CREFQ5, BOOST_MOVE_UNVOIDCREF(Q5) q5
+#define BOOST_MOVE_CREFQ7 BOOST_MOVE_CREFQ6, BOOST_MOVE_UNVOIDCREF(Q6) q6
+#define BOOST_MOVE_CREFQ8 BOOST_MOVE_CREFQ7, BOOST_MOVE_UNVOIDCREF(Q7) q7
+#define BOOST_MOVE_CREFQ9 BOOST_MOVE_CREFQ8, BOOST_MOVE_UNVOIDCREF(Q8) q8
+
+//BOOST_MOVE_CLASSN
+#define BOOST_MOVE_CLASS0
+#define BOOST_MOVE_CLASS1 class P0
+#define BOOST_MOVE_CLASS2 BOOST_MOVE_CLASS1, class P1
+#define BOOST_MOVE_CLASS3 BOOST_MOVE_CLASS2, class P2
+#define BOOST_MOVE_CLASS4 BOOST_MOVE_CLASS3, class P3
+#define BOOST_MOVE_CLASS5 BOOST_MOVE_CLASS4, class P4
+#define BOOST_MOVE_CLASS6 BOOST_MOVE_CLASS5, class P5
+#define BOOST_MOVE_CLASS7 BOOST_MOVE_CLASS6, class P6
+#define BOOST_MOVE_CLASS8 BOOST_MOVE_CLASS7, class P7
+#define BOOST_MOVE_CLASS9 BOOST_MOVE_CLASS8, class P8
+
+//BOOST_MOVE_CLASSQN
+#define BOOST_MOVE_CLASSQ0
+#define BOOST_MOVE_CLASSQ1 class Q0
+#define BOOST_MOVE_CLASSQ2 BOOST_MOVE_CLASSQ1, class Q1
+#define BOOST_MOVE_CLASSQ3 BOOST_MOVE_CLASSQ2, class Q2
+#define BOOST_MOVE_CLASSQ4 BOOST_MOVE_CLASSQ3, class Q3
+#define BOOST_MOVE_CLASSQ5 BOOST_MOVE_CLASSQ4, class Q4
+#define BOOST_MOVE_CLASSQ6 BOOST_MOVE_CLASSQ5, class Q5
+#define BOOST_MOVE_CLASSQ7 BOOST_MOVE_CLASSQ6, class Q6
+#define BOOST_MOVE_CLASSQ8 BOOST_MOVE_CLASSQ7, class Q7
+#define BOOST_MOVE_CLASSQ9 BOOST_MOVE_CLASSQ8, class Q8
+
+//BOOST_MOVE_CLASSDFLTN
+#define BOOST_MOVE_CLASSDFLT0
+#define BOOST_MOVE_CLASSDFLT1 class P0 = void
+#define BOOST_MOVE_CLASSDFLT2 BOOST_MOVE_CLASSDFLT1, class P1 = void
+#define BOOST_MOVE_CLASSDFLT3 BOOST_MOVE_CLASSDFLT2, class P2 = void
+#define BOOST_MOVE_CLASSDFLT4 BOOST_MOVE_CLASSDFLT3, class P3 = void
+#define BOOST_MOVE_CLASSDFLT5 BOOST_MOVE_CLASSDFLT4, class P4 = void
+#define BOOST_MOVE_CLASSDFLT6 BOOST_MOVE_CLASSDFLT5, class P5 = void
+#define BOOST_MOVE_CLASSDFLT7 BOOST_MOVE_CLASSDFLT6, class P6 = void
+#define BOOST_MOVE_CLASSDFLT8 BOOST_MOVE_CLASSDFLT7, class P7 = void
+#define BOOST_MOVE_CLASSDFLT9 BOOST_MOVE_CLASSDFLT8, class P8 = void
+
+//BOOST_MOVE_CLASSDFLTQN
+#define BOOST_MOVE_CLASSDFLTQ0
+#define BOOST_MOVE_CLASSDFLTQ1 class Q0 = void
+#define BOOST_MOVE_CLASSDFLTQ2 BOOST_MOVE_CLASSDFLTQ1, class Q1 = void
+#define BOOST_MOVE_CLASSDFLTQ3 BOOST_MOVE_CLASSDFLTQ2, class Q2 = void
+#define BOOST_MOVE_CLASSDFLTQ4 BOOST_MOVE_CLASSDFLTQ3, class Q3 = void
+#define BOOST_MOVE_CLASSDFLTQ5 BOOST_MOVE_CLASSDFLTQ4, class Q4 = void
+#define BOOST_MOVE_CLASSDFLTQ6 BOOST_MOVE_CLASSDFLTQ5, class Q5 = void
+#define BOOST_MOVE_CLASSDFLTQ7 BOOST_MOVE_CLASSDFLTQ6, class Q6 = void
+#define BOOST_MOVE_CLASSDFLTQ8 BOOST_MOVE_CLASSDFLTQ7, class Q7 = void
+#define BOOST_MOVE_CLASSDFLTQ9 BOOST_MOVE_CLASSDFLTQ8, class Q8 = void
+
+//BOOST_MOVE_LAST_TARGN
+#define BOOST_MOVE_LAST_TARG0 void
+#define BOOST_MOVE_LAST_TARG1 P0
+#define BOOST_MOVE_LAST_TARG2 P1
+#define BOOST_MOVE_LAST_TARG3 P2
+#define BOOST_MOVE_LAST_TARG4 P3
+#define BOOST_MOVE_LAST_TARG5 P4
+#define BOOST_MOVE_LAST_TARG6 P5
+#define BOOST_MOVE_LAST_TARG7 P6
+#define BOOST_MOVE_LAST_TARG8 P7
+#define BOOST_MOVE_LAST_TARG9 P8
+
+//BOOST_MOVE_LAST_TARGQN
+#define BOOST_MOVE_LAST_TARGQ0 void
+#define BOOST_MOVE_LAST_TARGQ1 Q0
+#define BOOST_MOVE_LAST_TARGQ2 Q1
+#define BOOST_MOVE_LAST_TARGQ3 Q2
+#define BOOST_MOVE_LAST_TARGQ4 Q3
+#define BOOST_MOVE_LAST_TARGQ5 Q4
+#define BOOST_MOVE_LAST_TARGQ6 Q5
+#define BOOST_MOVE_LAST_TARGQ7 Q6
+#define BOOST_MOVE_LAST_TARGQ8 Q7
+#define BOOST_MOVE_LAST_TARGQ9 Q8
+
+
+//BOOST_MOVE_TARGN
+#define BOOST_MOVE_TARG0
+#define BOOST_MOVE_TARG1 P0
+#define BOOST_MOVE_TARG2 BOOST_MOVE_TARG1, P1
+#define BOOST_MOVE_TARG3 BOOST_MOVE_TARG2, P2
+#define BOOST_MOVE_TARG4 BOOST_MOVE_TARG3, P3
+#define BOOST_MOVE_TARG5 BOOST_MOVE_TARG4, P4
+#define BOOST_MOVE_TARG6 BOOST_MOVE_TARG5, P5
+#define BOOST_MOVE_TARG7 BOOST_MOVE_TARG6, P6
+#define BOOST_MOVE_TARG8 BOOST_MOVE_TARG7, P7
+#define BOOST_MOVE_TARG9 BOOST_MOVE_TARG8, P8
+
+//BOOST_MOVE_TARGQN
+#define BOOST_MOVE_TARGQ0
+#define BOOST_MOVE_TARGQ1 Q0
+#define BOOST_MOVE_TARGQ2 BOOST_MOVE_TARGQ1, Q1
+#define BOOST_MOVE_TARGQ3 BOOST_MOVE_TARGQ2, Q2
+#define BOOST_MOVE_TARGQ4 BOOST_MOVE_TARGQ3, Q3
+#define BOOST_MOVE_TARGQ5 BOOST_MOVE_TARGQ4, Q4
+#define BOOST_MOVE_TARGQ6 BOOST_MOVE_TARGQ5, Q5
+#define BOOST_MOVE_TARGQ7 BOOST_MOVE_TARGQ6, Q6
+#define BOOST_MOVE_TARGQ8 BOOST_MOVE_TARGQ7, Q7
+#define BOOST_MOVE_TARGQ9 BOOST_MOVE_TARGQ8, Q8
+
+//BOOST_MOVE_FWD_TN
+#define BOOST_MOVE_FWD_T0
+#define BOOST_MOVE_FWD_T1 typename ::boost::move_detail::forward_type<P0>::type
+#define BOOST_MOVE_FWD_T2 BOOST_MOVE_FWD_T1, typename ::boost::move_detail::forward_type<P1>::type
+#define BOOST_MOVE_FWD_T3 BOOST_MOVE_FWD_T2, typename ::boost::move_detail::forward_type<P2>::type
+#define BOOST_MOVE_FWD_T4 BOOST_MOVE_FWD_T3, typename ::boost::move_detail::forward_type<P3>::type
+#define BOOST_MOVE_FWD_T5 BOOST_MOVE_FWD_T4, typename ::boost::move_detail::forward_type<P4>::type
+#define BOOST_MOVE_FWD_T6 BOOST_MOVE_FWD_T5, typename ::boost::move_detail::forward_type<P5>::type
+#define BOOST_MOVE_FWD_T7 BOOST_MOVE_FWD_T6, typename ::boost::move_detail::forward_type<P6>::type
+#define BOOST_MOVE_FWD_T8 BOOST_MOVE_FWD_T7, typename ::boost::move_detail::forward_type<P7>::type
+#define BOOST_MOVE_FWD_T9 BOOST_MOVE_FWD_T8, typename ::boost::move_detail::forward_type<P8>::type
+
+//BOOST_MOVE_FWD_TQN
+#define BOOST_MOVE_FWD_TQ0
+#define BOOST_MOVE_FWD_TQ1 typename ::boost::move_detail::forward_type<Q0>::type
+#define BOOST_MOVE_FWD_TQ2 BOOST_MOVE_FWD_TQ1, typename ::boost::move_detail::forward_type<Q1>::type
+#define BOOST_MOVE_FWD_TQ3 BOOST_MOVE_FWD_TQ2, typename ::boost::move_detail::forward_type<Q2>::type
+#define BOOST_MOVE_FWD_TQ4 BOOST_MOVE_FWD_TQ3, typename ::boost::move_detail::forward_type<Q3>::type
+#define BOOST_MOVE_FWD_TQ5 BOOST_MOVE_FWD_TQ4, typename ::boost::move_detail::forward_type<Q4>::type
+#define BOOST_MOVE_FWD_TQ6 BOOST_MOVE_FWD_TQ5, typename ::boost::move_detail::forward_type<Q5>::type
+#define BOOST_MOVE_FWD_TQ7 BOOST_MOVE_FWD_TQ6, typename ::boost::move_detail::forward_type<Q6>::type
+#define BOOST_MOVE_FWD_TQ8 BOOST_MOVE_FWD_TQ7, typename ::boost::move_detail::forward_type<Q7>::type
+#define BOOST_MOVE_FWD_TQ9 BOOST_MOVE_FWD_TQ8, typename ::boost::move_detail::forward_type<Q8>::type
+
+//BOOST_MOVE_MREFX
+#define BOOST_MOVE_MREF0
+#define BOOST_MOVE_MREF1 BOOST_MOVE_MREF(P0) m_p0;
+#define BOOST_MOVE_MREF2 BOOST_MOVE_MREF1 BOOST_MOVE_MREF(P1) m_p1;
+#define BOOST_MOVE_MREF3 BOOST_MOVE_MREF2 BOOST_MOVE_MREF(P2) m_p2;
+#define BOOST_MOVE_MREF4 BOOST_MOVE_MREF3 BOOST_MOVE_MREF(P3) m_p3;
+#define BOOST_MOVE_MREF5 BOOST_MOVE_MREF4 BOOST_MOVE_MREF(P4) m_p4;
+#define BOOST_MOVE_MREF6 BOOST_MOVE_MREF5 BOOST_MOVE_MREF(P5) m_p5;
+#define BOOST_MOVE_MREF7 BOOST_MOVE_MREF6 BOOST_MOVE_MREF(P6) m_p6;
+#define BOOST_MOVE_MREF8 BOOST_MOVE_MREF7 BOOST_MOVE_MREF(P7) m_p7;
+#define BOOST_MOVE_MREF9 BOOST_MOVE_MREF8 BOOST_MOVE_MREF(P8) m_p8;
+
+//BOOST_MOVE_MREFQX
+#define BOOST_MOVE_MREFQ0
+#define BOOST_MOVE_MREFQ1 BOOST_MOVE_MREFQ(Q0) m_q0;
+#define BOOST_MOVE_MREFQ2 BOOST_MOVE_MREFQ1 BOOST_MOVE_MREFQ(Q1) m_q1;
+#define BOOST_MOVE_MREFQ3 BOOST_MOVE_MREFQ2 BOOST_MOVE_MREFQ(Q2) m_q2;
+#define BOOST_MOVE_MREFQ4 BOOST_MOVE_MREFQ3 BOOST_MOVE_MREFQ(Q3) m_q3;
+#define BOOST_MOVE_MREFQ5 BOOST_MOVE_MREFQ4 BOOST_MOVE_MREFQ(Q4) m_q4;
+#define BOOST_MOVE_MREFQ6 BOOST_MOVE_MREFQ5 BOOST_MOVE_MREFQ(Q5) m_q5;
+#define BOOST_MOVE_MREFQ7 BOOST_MOVE_MREFQ6 BOOST_MOVE_MREFQ(Q6) m_q6;
+#define BOOST_MOVE_MREFQ8 BOOST_MOVE_MREFQ7 BOOST_MOVE_MREFQ(Q7) m_q7;
+#define BOOST_MOVE_MREFQ9 BOOST_MOVE_MREFQ8 BOOST_MOVE_MREFQ(Q8) m_q8;
+
+//BOOST_MOVE_MEMBX
+#define BOOST_MOVE_MEMB0
+#define BOOST_MOVE_MEMB1 P0 m_p0;
+#define BOOST_MOVE_MEMB2 BOOST_MOVE_MEMB1 P1 m_p1;
+#define BOOST_MOVE_MEMB3 BOOST_MOVE_MEMB2 P2 m_p2;
+#define BOOST_MOVE_MEMB4 BOOST_MOVE_MEMB3 P3 m_p3;
+#define BOOST_MOVE_MEMB5 BOOST_MOVE_MEMB4 P4 m_p4;
+#define BOOST_MOVE_MEMB6 BOOST_MOVE_MEMB5 P5 m_p5;
+#define BOOST_MOVE_MEMB7 BOOST_MOVE_MEMB6 P6 m_p6;
+#define BOOST_MOVE_MEMB8 BOOST_MOVE_MEMB7 P7 m_p7;
+#define BOOST_MOVE_MEMB9 BOOST_MOVE_MEMB8 P8 m_p8;
+
+//BOOST_MOVE_MEMBQX
+#define BOOST_MOVE_MEMBQ0
+#define BOOST_MOVE_MEMBQ1 Q0 m_q0;
+#define BOOST_MOVE_MEMBQ2 BOOST_MOVE_MEMBQ1 Q1 m_q1;
+#define BOOST_MOVE_MEMBQ3 BOOST_MOVE_MEMBQ2 Q2 m_q2;
+#define BOOST_MOVE_MEMBQ4 BOOST_MOVE_MEMBQ3 Q3 m_q3;
+#define BOOST_MOVE_MEMBQ5 BOOST_MOVE_MEMBQ4 Q4 m_q4;
+#define BOOST_MOVE_MEMBQ6 BOOST_MOVE_MEMBQ5 Q5 m_q5;
+#define BOOST_MOVE_MEMBQ7 BOOST_MOVE_MEMBQ6 Q6 m_q6;
+#define BOOST_MOVE_MEMBQ8 BOOST_MOVE_MEMBQ7 Q7 m_q7;
+#define BOOST_MOVE_MEMBQ9 BOOST_MOVE_MEMBQ8 Q8 m_q8;
+
+//BOOST_MOVE_TMPL_LTN
+#define BOOST_MOVE_TMPL_LT0
+#define BOOST_MOVE_TMPL_LT1 template<
+#define BOOST_MOVE_TMPL_LT2 BOOST_MOVE_TMPL_LT1
+#define BOOST_MOVE_TMPL_LT3 BOOST_MOVE_TMPL_LT1
+#define BOOST_MOVE_TMPL_LT4 BOOST_MOVE_TMPL_LT1
+#define BOOST_MOVE_TMPL_LT5 BOOST_MOVE_TMPL_LT1
+#define BOOST_MOVE_TMPL_LT6 BOOST_MOVE_TMPL_LT1
+#define BOOST_MOVE_TMPL_LT7 BOOST_MOVE_TMPL_LT1
+#define BOOST_MOVE_TMPL_LT8 BOOST_MOVE_TMPL_LT1
+#define BOOST_MOVE_TMPL_LT9 BOOST_MOVE_TMPL_LT1
+
+//BOOST_MOVE_LTN
+#define BOOST_MOVE_LT0
+#define BOOST_MOVE_LT1 <
+#define BOOST_MOVE_LT2 BOOST_MOVE_LT1
+#define BOOST_MOVE_LT3 BOOST_MOVE_LT1
+#define BOOST_MOVE_LT4 BOOST_MOVE_LT1
+#define BOOST_MOVE_LT5 BOOST_MOVE_LT1
+#define BOOST_MOVE_LT6 BOOST_MOVE_LT1
+#define BOOST_MOVE_LT7 BOOST_MOVE_LT1
+#define BOOST_MOVE_LT8 BOOST_MOVE_LT1
+#define BOOST_MOVE_LT9 BOOST_MOVE_LT1
+
+//BOOST_MOVE_GTN
+#define BOOST_MOVE_GT0
+#define BOOST_MOVE_GT1 >
+#define BOOST_MOVE_GT2 BOOST_MOVE_GT1
+#define BOOST_MOVE_GT3 BOOST_MOVE_GT1
+#define BOOST_MOVE_GT4 BOOST_MOVE_GT1
+#define BOOST_MOVE_GT5 BOOST_MOVE_GT1
+#define BOOST_MOVE_GT6 BOOST_MOVE_GT1
+#define BOOST_MOVE_GT7 BOOST_MOVE_GT1
+#define BOOST_MOVE_GT8 BOOST_MOVE_GT1
+#define BOOST_MOVE_GT9 BOOST_MOVE_GT1
+
+//BOOST_MOVE_LPN
+#define BOOST_MOVE_LP0
+#define BOOST_MOVE_LP1 (
+#define BOOST_MOVE_LP2 BOOST_MOVE_LP1
+#define BOOST_MOVE_LP3 BOOST_MOVE_LP1
+#define BOOST_MOVE_LP4 BOOST_MOVE_LP1
+#define BOOST_MOVE_LP5 BOOST_MOVE_LP1
+#define BOOST_MOVE_LP6 BOOST_MOVE_LP1
+#define BOOST_MOVE_LP7 BOOST_MOVE_LP1
+#define BOOST_MOVE_LP8 BOOST_MOVE_LP1
+#define BOOST_MOVE_LP9 BOOST_MOVE_LP1
+
+//BOOST_MOVE_RPN
+#define BOOST_MOVE_RP0
+#define BOOST_MOVE_RP1 )
+#define BOOST_MOVE_RP2 BOOST_MOVE_RP1
+#define BOOST_MOVE_RP3 BOOST_MOVE_RP1
+#define BOOST_MOVE_RP4 BOOST_MOVE_RP1
+#define BOOST_MOVE_RP5 BOOST_MOVE_RP1
+#define BOOST_MOVE_RP6 BOOST_MOVE_RP1
+#define BOOST_MOVE_RP7 BOOST_MOVE_RP1
+#define BOOST_MOVE_RP8 BOOST_MOVE_RP1
+#define BOOST_MOVE_RP9 BOOST_MOVE_RP1
+
+//BOOST_MOVE_IN
+#define BOOST_MOVE_I0
+#define BOOST_MOVE_I1 ,
+#define BOOST_MOVE_I2 BOOST_MOVE_I1
+#define BOOST_MOVE_I3 BOOST_MOVE_I1
+#define BOOST_MOVE_I4 BOOST_MOVE_I1
+#define BOOST_MOVE_I5 BOOST_MOVE_I1
+#define BOOST_MOVE_I6 BOOST_MOVE_I1
+#define BOOST_MOVE_I7 BOOST_MOVE_I1
+#define BOOST_MOVE_I8 BOOST_MOVE_I1
+#define BOOST_MOVE_I9 BOOST_MOVE_I1
+
+//BOOST_MOVE_BOOL
+# define BOOST_MOVE_BOOL(x) BOOST_MOVE_BOOL_I(x)
+# define BOOST_MOVE_BOOL_I(x) BOOST_MOVE_BOOL##x
+# define BOOST_MOVE_BOOL0 0
+# define BOOST_MOVE_BOOL1 1
+# define BOOST_MOVE_BOOL2 1
+# define BOOST_MOVE_BOOL3 1
+# define BOOST_MOVE_BOOL4 1
+# define BOOST_MOVE_BOOL5 1
+# define BOOST_MOVE_BOOL6 1
+# define BOOST_MOVE_BOOL7 1
+# define BOOST_MOVE_BOOL8 1
+# define BOOST_MOVE_BOOL9 1
+
+//BOOST_MOVE_I_IF
+#define BOOST_MOVE_I_IF(x) BOOST_MOVE_I_IF_I (BOOST_MOVE_BOOL(x))
+#define BOOST_MOVE_I_IF_I(x) BOOST_MOVE_I_IF_I2(x)
+#define BOOST_MOVE_I_IF_I2(x) BOOST_MOVE_IF_I_##x
+#define BOOST_MOVE_IF_I_0
+#define BOOST_MOVE_IF_I_1 ,
+
+//BOOST_MOVE_IF
+#define BOOST_MOVE_IF(cond, t, f) BOOST_MOVE_IF_I(cond, t, f)
+#define BOOST_MOVE_IF_I(cond, t, f) BOOST_MOVE_IIF(BOOST_MOVE_BOOL(cond), t, f)
+
+#define BOOST_MOVE_IIF(bit, t, f) BOOST_MOVE_IIF_I(bit, t, f)
+#define BOOST_MOVE_IIF_I(bit, t, f) BOOST_MOVE_IIF_##bit(t, f)
+#define BOOST_MOVE_IIF_0(t, f) f
+#define BOOST_MOVE_IIF_1(t, f) t
+
+/*
+#define BOOST_MOVE_IIF(bit, t, f) BOOST_MOVE_IIF_OO((bit, t, f))
+#define BOOST_MOVE_IIF_OO(par) BOOST_MOVE_IIF_I ## par
+#define BOOST_MOVE_IIF_I(bit, t, f) BOOST_MOVE_IIF_II(BOOST_MOVE_IIF_ ## bit(t, f))
+#define BOOST_MOVE_IIF_II(id) id
+#define BOOST_MOVE_IIF_0(t, f) f
+#define BOOST_MOVE_IIF_1(t, f) t
+*/
+
+//BOOST_MOVE_COLON
+#define BOOST_MOVE_COLON0
+#define BOOST_MOVE_COLON1 :
+#define BOOST_MOVE_COLON2 BOOST_MOVE_COLON1
+#define BOOST_MOVE_COLON3 BOOST_MOVE_COLON1
+#define BOOST_MOVE_COLON4 BOOST_MOVE_COLON1
+#define BOOST_MOVE_COLON5 BOOST_MOVE_COLON1
+#define BOOST_MOVE_COLON6 BOOST_MOVE_COLON1
+#define BOOST_MOVE_COLON7 BOOST_MOVE_COLON1
+#define BOOST_MOVE_COLON8 BOOST_MOVE_COLON1
+#define BOOST_MOVE_COLON9 BOOST_MOVE_COLON1
+
+//BOOST_MOVE_BITOR
+#define BOOST_MOVE_BITOR(x,y) BOOST_MOVE_BITOR_I(x,y)
+#define BOOST_MOVE_BITOR_I(x,y) BOOST_MOVE_BITOR##x##y
+#define BOOST_MOVE_BITOR00 0
+#define BOOST_MOVE_BITOR01 1
+#define BOOST_MOVE_BITOR10 1
+#define BOOST_MOVE_BITOR11 1
+
+//BOOST_MOVE_OR
+#define BOOST_MOVE_OR(x, y) BOOST_MOVE_OR_I(x, y)
+#define BOOST_MOVE_OR_I(x, y) BOOST_MOVE_BITOR(BOOST_MOVE_BOOL(x), BOOST_MOVE_BOOL(y))
+
+//BOOST_MOVE_BITAND
+#define BOOST_MOVE_BITAND(x,y) BOOST_MOVE_BITAND_I(x,y)
+#define BOOST_MOVE_BITAND_I(x,y) BOOST_MOVE_BITAND##x##y
+#define BOOST_MOVE_BITAND00 0
+#define BOOST_MOVE_BITAND01 0
+#define BOOST_MOVE_BITAND10 0
+#define BOOST_MOVE_BITAND11 1
+
+//BOOST_MOVE_AND
+#define BOOST_MOVE_AND(x, y) BOOST_MOVE_AND_I(x, y)
+#define BOOST_MOVE_AND_I(x, y) BOOST_MOVE_BITAND(BOOST_MOVE_BOOL(x), BOOST_MOVE_BOOL(y))
+
+//BOOST_MOVE_DEC
+#define BOOST_MOVE_DEC(x) BOOST_MOVE_DEC_I(x)
+#define BOOST_MOVE_DEC_I(x) BOOST_MOVE_DEC##x
+#define BOOST_MOVE_DEC1 0
+#define BOOST_MOVE_DEC2 1
+#define BOOST_MOVE_DEC3 2
+#define BOOST_MOVE_DEC4 3
+#define BOOST_MOVE_DEC5 4
+#define BOOST_MOVE_DEC6 5
+#define BOOST_MOVE_DEC7 6
+#define BOOST_MOVE_DEC8 7
+#define BOOST_MOVE_DEC9 8
+#define BOOST_MOVE_DEC10 9
+#define BOOST_MOVE_DEC11 10
+#define BOOST_MOVE_DEC12 11
+#define BOOST_MOVE_DEC13 12
+#define BOOST_MOVE_DEC14 13
+
+//BOOST_MOVE_SUB
+#define BOOST_MOVE_SUB(x, y) BOOST_MOVE_SUB_I(x,y)
+#define BOOST_MOVE_SUB_I(x, y) BOOST_MOVE_SUB##y(x)
+#define BOOST_MOVE_SUB0(x) x
+#define BOOST_MOVE_SUB1(x) BOOST_MOVE_DEC(x)
+#define BOOST_MOVE_SUB2(x) BOOST_MOVE_SUB1(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB3(x) BOOST_MOVE_SUB2(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB4(x) BOOST_MOVE_SUB3(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB5(x) BOOST_MOVE_SUB4(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB6(x) BOOST_MOVE_SUB5(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB7(x) BOOST_MOVE_SUB6(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB8(x) BOOST_MOVE_SUB7(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB9(x) BOOST_MOVE_SUB8(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB10(x) BOOST_MOVE_SUB9(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB11(x) BOOST_MOVE_SUB10(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB12(x) BOOST_MOVE_SUB11(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB13(x) BOOST_MOVE_SUB12(BOOST_MOVE_DEC(x))
+#define BOOST_MOVE_SUB14(x) BOOST_MOVE_SUB13(BOOST_MOVE_DEC(x))
+
+//BOOST_MOVE_INC
+#define BOOST_MOVE_INC(x) BOOST_MOVE_INC_I(x)
+#define BOOST_MOVE_INC_I(x) BOOST_MOVE_INC##x
+#define BOOST_MOVE_INC0 1
+#define BOOST_MOVE_INC1 2
+#define BOOST_MOVE_INC2 3
+#define BOOST_MOVE_INC3 4
+#define BOOST_MOVE_INC4 5
+#define BOOST_MOVE_INC5 6
+#define BOOST_MOVE_INC6 7
+#define BOOST_MOVE_INC7 8
+#define BOOST_MOVE_INC8 9
+#define BOOST_MOVE_INC9 10
+#define BOOST_MOVE_INC10 11
+#define BOOST_MOVE_INC11 12
+#define BOOST_MOVE_INC12 13
+#define BOOST_MOVE_INC13 14
+
+//BOOST_MOVE_ADD
+#define BOOST_MOVE_ADD(x, y) BOOST_MOVE_ADD_I(x,y)
+#define BOOST_MOVE_ADD_I(x, y) BOOST_MOVE_ADD##y(x)
+#define BOOST_MOVE_ADD0(x) x
+#define BOOST_MOVE_ADD1(x) BOOST_MOVE_INC(x)
+#define BOOST_MOVE_ADD2(x) BOOST_MOVE_ADD1(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD3(x) BOOST_MOVE_ADD2(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD4(x) BOOST_MOVE_ADD3(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD5(x) BOOST_MOVE_ADD4(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD6(x) BOOST_MOVE_ADD5(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD7(x) BOOST_MOVE_ADD6(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD8(x) BOOST_MOVE_ADD7(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD9(x) BOOST_MOVE_ADD8(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD10(x) BOOST_MOVE_ADD9(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD11(x) BOOST_MOVE_ADD10(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD12(x) BOOST_MOVE_ADD11(BOOST_MOVE_INC(x))
+#define BOOST_MOVE_ADD13(x) BOOST_MOVE_ADD12(BOOST_MOVE_INC(x))
+
+//BOOST_MOVE_ITERATE_2TON
+#define BOOST_MOVE_ITERATE_2TO2(MACROFUNC) MACROFUNC(2)
+#define BOOST_MOVE_ITERATE_2TO3(MACROFUNC) BOOST_MOVE_ITERATE_2TO2(MACROFUNC) MACROFUNC(3)
+#define BOOST_MOVE_ITERATE_2TO4(MACROFUNC) BOOST_MOVE_ITERATE_2TO3(MACROFUNC) MACROFUNC(4)
+#define BOOST_MOVE_ITERATE_2TO5(MACROFUNC) BOOST_MOVE_ITERATE_2TO4(MACROFUNC) MACROFUNC(5)
+#define BOOST_MOVE_ITERATE_2TO6(MACROFUNC) BOOST_MOVE_ITERATE_2TO5(MACROFUNC) MACROFUNC(6)
+#define BOOST_MOVE_ITERATE_2TO7(MACROFUNC) BOOST_MOVE_ITERATE_2TO6(MACROFUNC) MACROFUNC(7)
+#define BOOST_MOVE_ITERATE_2TO8(MACROFUNC) BOOST_MOVE_ITERATE_2TO7(MACROFUNC) MACROFUNC(8)
+#define BOOST_MOVE_ITERATE_2TO9(MACROFUNC) BOOST_MOVE_ITERATE_2TO8(MACROFUNC) MACROFUNC(9)
+
+//BOOST_MOVE_ITERATE_1TON
+#define BOOST_MOVE_ITERATE_1TO1(MACROFUNC) MACROFUNC(1)
+#define BOOST_MOVE_ITERATE_1TO2(MACROFUNC) BOOST_MOVE_ITERATE_1TO1(MACROFUNC) MACROFUNC(2)
+#define BOOST_MOVE_ITERATE_1TO3(MACROFUNC) BOOST_MOVE_ITERATE_1TO2(MACROFUNC) MACROFUNC(3)
+#define BOOST_MOVE_ITERATE_1TO4(MACROFUNC) BOOST_MOVE_ITERATE_1TO3(MACROFUNC) MACROFUNC(4)
+#define BOOST_MOVE_ITERATE_1TO5(MACROFUNC) BOOST_MOVE_ITERATE_1TO4(MACROFUNC) MACROFUNC(5)
+#define BOOST_MOVE_ITERATE_1TO6(MACROFUNC) BOOST_MOVE_ITERATE_1TO5(MACROFUNC) MACROFUNC(6)
+#define BOOST_MOVE_ITERATE_1TO7(MACROFUNC) BOOST_MOVE_ITERATE_1TO6(MACROFUNC) MACROFUNC(7)
+#define BOOST_MOVE_ITERATE_1TO8(MACROFUNC) BOOST_MOVE_ITERATE_1TO7(MACROFUNC) MACROFUNC(8)
+#define BOOST_MOVE_ITERATE_1TO9(MACROFUNC) BOOST_MOVE_ITERATE_1TO8(MACROFUNC) MACROFUNC(9)
+
+//BOOST_MOVE_ITERATE_0TON
+#define BOOST_MOVE_ITERATE_0TO0(MACROFUNC) MACROFUNC(0)
+#define BOOST_MOVE_ITERATE_0TO1(MACROFUNC) BOOST_MOVE_ITERATE_0TO0(MACROFUNC) MACROFUNC(1)
+#define BOOST_MOVE_ITERATE_0TO2(MACROFUNC) BOOST_MOVE_ITERATE_0TO1(MACROFUNC) MACROFUNC(2)
+#define BOOST_MOVE_ITERATE_0TO3(MACROFUNC) BOOST_MOVE_ITERATE_0TO2(MACROFUNC) MACROFUNC(3)
+#define BOOST_MOVE_ITERATE_0TO4(MACROFUNC) BOOST_MOVE_ITERATE_0TO3(MACROFUNC) MACROFUNC(4)
+#define BOOST_MOVE_ITERATE_0TO5(MACROFUNC) BOOST_MOVE_ITERATE_0TO4(MACROFUNC) MACROFUNC(5)
+#define BOOST_MOVE_ITERATE_0TO6(MACROFUNC) BOOST_MOVE_ITERATE_0TO5(MACROFUNC) MACROFUNC(6)
+#define BOOST_MOVE_ITERATE_0TO7(MACROFUNC) BOOST_MOVE_ITERATE_0TO6(MACROFUNC) MACROFUNC(7)
+#define BOOST_MOVE_ITERATE_0TO8(MACROFUNC) BOOST_MOVE_ITERATE_0TO7(MACROFUNC) MACROFUNC(8)
+#define BOOST_MOVE_ITERATE_0TO9(MACROFUNC) BOOST_MOVE_ITERATE_0TO8(MACROFUNC) MACROFUNC(9)
+
+//BOOST_MOVE_ITERATE_NTON
+#define BOOST_MOVE_ITERATE_1TO1(MACROFUNC) MACROFUNC(1)
+#define BOOST_MOVE_ITERATE_2TO2(MACROFUNC) MACROFUNC(2)
+#define BOOST_MOVE_ITERATE_3TO3(MACROFUNC) MACROFUNC(3)
+#define BOOST_MOVE_ITERATE_4TO4(MACROFUNC) MACROFUNC(4)
+#define BOOST_MOVE_ITERATE_5TO5(MACROFUNC) MACROFUNC(5)
+#define BOOST_MOVE_ITERATE_6TO6(MACROFUNC) MACROFUNC(6)
+#define BOOST_MOVE_ITERATE_7TO7(MACROFUNC) MACROFUNC(7)
+#define BOOST_MOVE_ITERATE_8TO8(MACROFUNC) MACROFUNC(8)
+#define BOOST_MOVE_ITERATE_9TO9(MACROFUNC) MACROFUNC(9)
+
+//BOOST_MOVE_ITER2D_0TOMAX
+#define BOOST_MOVE_ITER2DLOW_0TOMAX0(MACROFUNC2D, M) MACROFUNC2D(M, 0)
+#define BOOST_MOVE_ITER2DLOW_0TOMAX1(MACROFUNC2D, M) BOOST_MOVE_ITER2DLOW_0TOMAX0(MACROFUNC2D, M) MACROFUNC2D(M, 1)
+#define BOOST_MOVE_ITER2DLOW_0TOMAX2(MACROFUNC2D, M) BOOST_MOVE_ITER2DLOW_0TOMAX1(MACROFUNC2D, M) MACROFUNC2D(M, 2)
+#define BOOST_MOVE_ITER2DLOW_0TOMAX3(MACROFUNC2D, M) BOOST_MOVE_ITER2DLOW_0TOMAX2(MACROFUNC2D, M) MACROFUNC2D(M, 3)
+#define BOOST_MOVE_ITER2DLOW_0TOMAX4(MACROFUNC2D, M) BOOST_MOVE_ITER2DLOW_0TOMAX3(MACROFUNC2D, M) MACROFUNC2D(M, 4)
+#define BOOST_MOVE_ITER2DLOW_0TOMAX5(MACROFUNC2D, M) BOOST_MOVE_ITER2DLOW_0TOMAX4(MACROFUNC2D, M) MACROFUNC2D(M, 5)
+#define BOOST_MOVE_ITER2DLOW_0TOMAX6(MACROFUNC2D, M) BOOST_MOVE_ITER2DLOW_0TOMAX5(MACROFUNC2D, M) MACROFUNC2D(M, 6)
+#define BOOST_MOVE_ITER2DLOW_0TOMAX7(MACROFUNC2D, M) BOOST_MOVE_ITER2DLOW_0TOMAX6(MACROFUNC2D, M) MACROFUNC2D(M, 7)
+#define BOOST_MOVE_ITER2DLOW_0TOMAX8(MACROFUNC2D, M) BOOST_MOVE_ITER2DLOW_0TOMAX7(MACROFUNC2D, M) MACROFUNC2D(M, 8)
+#define BOOST_MOVE_ITER2DLOW_0TOMAX9(MACROFUNC2D, M) BOOST_MOVE_ITER2DLOW_0TOMAX8(MACROFUNC2D, M) MACROFUNC2D(M, 9)
+
+#define BOOST_MOVE_ITER2D_0TOMAX0(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 0)
+#define BOOST_MOVE_ITER2D_0TOMAX1(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX0(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 1)
+#define BOOST_MOVE_ITER2D_0TOMAX2(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX1(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 2)
+#define BOOST_MOVE_ITER2D_0TOMAX3(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX2(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 3)
+#define BOOST_MOVE_ITER2D_0TOMAX4(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX3(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 4)
+#define BOOST_MOVE_ITER2D_0TOMAX5(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX4(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 5)
+#define BOOST_MOVE_ITER2D_0TOMAX6(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX5(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 6)
+#define BOOST_MOVE_ITER2D_0TOMAX7(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX6(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 7)
+#define BOOST_MOVE_ITER2D_0TOMAX8(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX7(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 8)
+#define BOOST_MOVE_ITER2D_0TOMAX9(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX8(MAX, MACROFUNC2D) BOOST_MOVE_ITER2DLOW_0TOMAX##MAX(MACROFUNC2D, 9)
+
+#define BOOST_MOVE_ITER2D_0TOMAX(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX_I (MAX, MACROFUNC2D)
+#define BOOST_MOVE_ITER2D_0TOMAX_I(MAX, MACROFUNC2D) BOOST_MOVE_ITER2D_0TOMAX##MAX(MAX, MACROFUNC2D)
+
+
+
+
+//BOOST_MOVE_CAT
+#define BOOST_MOVE_CAT(a, b) BOOST_MOVE_CAT_I(a, b)
+#define BOOST_MOVE_CAT_I(a, b) a ## b
+//# define BOOST_MOVE_CAT_I(a, b) BOOST_MOVE_CAT_II(~, a ## b)
+//# define BOOST_MOVE_CAT_II(p, res) res
+
+#endif //#ifndef BOOST_MOVE_DETAIL_FWD_MACROS_HPP
diff --git a/include/boost/move/detail/iterator_to_raw_pointer.hpp b/include/boost/move/detail/iterator_to_raw_pointer.hpp
new file mode 100644
index 0000000..97ee3a6
--- /dev/null
+++ b/include/boost/move/detail/iterator_to_raw_pointer.hpp
@@ -0,0 +1,59 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
+#define BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
+#include <boost/move/detail/pointer_element.hpp>
+
+namespace boost {
+namespace movelib {
+namespace detail {
+
+template <class T>
+inline T* iterator_to_pointer(T* i)
+{ return i; }
+
+template <class Iterator>
+inline typename boost::movelib::iterator_traits<Iterator>::pointer
+ iterator_to_pointer(const Iterator &i)
+{ return i.operator->(); }
+
+template <class Iterator>
+struct iterator_to_element_ptr
+{
+ typedef typename boost::movelib::iterator_traits<Iterator>::pointer pointer;
+ typedef typename boost::movelib::pointer_element<pointer>::type element_type;
+ typedef element_type* type;
+};
+
+} //namespace detail {
+
+template <class Iterator>
+inline typename boost::movelib::detail::iterator_to_element_ptr<Iterator>::type
+ iterator_to_raw_pointer(const Iterator &i)
+{
+ return ::boost::movelib::to_raw_pointer
+ ( ::boost::movelib::detail::iterator_to_pointer(i) );
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#endif //#ifndef BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
diff --git a/include/boost/move/detail/iterator_traits.hpp b/include/boost/move/detail/iterator_traits.hpp
new file mode 100644
index 0000000..5ffcb2c
--- /dev/null
+++ b/include/boost/move/detail/iterator_traits.hpp
@@ -0,0 +1,77 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_ITERATOR_TRAITS_HPP
+#define BOOST_MOVE_DETAIL_ITERATOR_TRAITS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <cstddef>
+#include <boost/move/detail/type_traits.hpp>
+
+#include <boost/move/detail/std_ns_begin.hpp>
+BOOST_MOVE_STD_NS_BEG
+
+struct input_iterator_tag;
+struct forward_iterator_tag;
+struct bidirectional_iterator_tag;
+struct random_access_iterator_tag;
+struct output_iterator_tag;
+
+BOOST_MOVE_STD_NS_END
+#include <boost/move/detail/std_ns_end.hpp>
+
+namespace boost{ namespace movelib{
+
+template<class Iterator>
+struct iterator_traits
+{
+ typedef typename Iterator::difference_type difference_type;
+ typedef typename Iterator::value_type value_type;
+ typedef typename Iterator::pointer pointer;
+ typedef typename Iterator::reference reference;
+ typedef typename Iterator::iterator_category iterator_category;
+ typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
+};
+
+template<class T>
+struct iterator_traits<T*>
+{
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
+};
+
+template<class T>
+struct iterator_traits<const T*>
+{
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef const T* pointer;
+ typedef const T& reference;
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
+};
+
+}} //namespace boost { namespace movelib{
+
+#endif //#ifndef BOOST_MOVE_DETAIL_ITERATOR_TRAITS_HPP
diff --git a/include/boost/move/detail/meta_utils.hpp b/include/boost/move/detail/meta_utils.hpp
new file mode 100644
index 0000000..e45394c
--- /dev/null
+++ b/include/boost/move/detail/meta_utils.hpp
@@ -0,0 +1,585 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
+#define BOOST_MOVE_DETAIL_META_UTILS_HPP
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
+#include <boost/move/detail/meta_utils_core.hpp>
+#include <cstddef> //for std::size_t
+
+//Small meta-typetraits to support move
+
+namespace boost {
+
+//Forward declare boost::rv
+template <class T> class rv;
+
+namespace move_detail {
+
+//////////////////////////////////////
+// is_different
+//////////////////////////////////////
+template<class T, class U>
+struct is_different
+{
+ static const bool value = !is_same<T, U>::value;
+};
+
+//////////////////////////////////////
+// apply
+//////////////////////////////////////
+template<class F, class Param>
+struct apply
+{
+ typedef typename F::template apply<Param>::type type;
+};
+
+//////////////////////////////////////
+// bool_
+//////////////////////////////////////
+
+template< bool C_ >
+struct bool_ : integral_constant<bool, C_>
+{
+ operator bool() const { return C_; }
+ bool operator()() const { return C_; }
+};
+
+typedef bool_<true> true_;
+typedef bool_<false> false_;
+
+//////////////////////////////////////
+// nat
+//////////////////////////////////////
+struct nat{};
+
+//////////////////////////////////////
+// yes_type/no_type
+//////////////////////////////////////
+typedef char yes_type;
+
+struct no_type
+{
+ char _[2];
+};
+
+//////////////////////////////////////
+// natify
+//////////////////////////////////////
+template <class T> struct natify{};
+
+//////////////////////////////////////
+// remove_reference
+//////////////////////////////////////
+template<class T>
+struct remove_reference
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference<T&>
+{
+ typedef T type;
+};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template<class T>
+struct remove_reference<T&&>
+{
+ typedef T type;
+};
+
+#else
+
+template<class T>
+struct remove_reference< rv<T> >
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference< rv<T> &>
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference< const rv<T> &>
+{
+ typedef T type;
+};
+
+#endif
+
+//////////////////////////////////////
+// remove_pointer
+//////////////////////////////////////
+
+template< class T > struct remove_pointer { typedef T type; };
+template< class T > struct remove_pointer<T*> { typedef T type; };
+template< class T > struct remove_pointer<T* const> { typedef T type; };
+template< class T > struct remove_pointer<T* volatile> { typedef T type; };
+template< class T > struct remove_pointer<T* const volatile> { typedef T type; };
+
+//////////////////////////////////////
+// add_pointer
+//////////////////////////////////////
+template< class T >
+struct add_pointer
+{
+ typedef typename remove_reference<T>::type* type;
+};
+
+//////////////////////////////////////
+// add_const
+//////////////////////////////////////
+template<class T>
+struct add_const
+{
+ typedef const T type;
+};
+
+template<class T>
+struct add_const<T&>
+{
+ typedef const T& type;
+};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template<class T>
+struct add_const<T&&>
+{
+ typedef T&& type;
+};
+
+#endif
+
+//////////////////////////////////////
+// add_lvalue_reference
+//////////////////////////////////////
+template<class T>
+struct add_lvalue_reference
+{ typedef T& type; };
+
+template<class T> struct add_lvalue_reference<T&> { typedef T& type; };
+template<> struct add_lvalue_reference<void> { typedef void type; };
+template<> struct add_lvalue_reference<const void> { typedef const void type; };
+template<> struct add_lvalue_reference<volatile void> { typedef volatile void type; };
+template<> struct add_lvalue_reference<const volatile void>{ typedef const volatile void type; };
+
+template<class T>
+struct add_const_lvalue_reference
+{
+ typedef typename remove_reference<T>::type t_unreferenced;
+ typedef typename add_const<t_unreferenced>::type t_unreferenced_const;
+ typedef typename add_lvalue_reference
+ <t_unreferenced_const>::type type;
+};
+
+//////////////////////////////////////
+// is_lvalue_reference
+//////////////////////////////////////
+template<class T>
+struct is_lvalue_reference
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_lvalue_reference<T&>
+{
+ static const bool value = true;
+};
+
+
+//////////////////////////////////////
+// identity
+//////////////////////////////////////
+template <class T>
+struct identity
+{
+ typedef T type;
+ typedef typename add_const_lvalue_reference<T>::type reference;
+ reference operator()(reference t)
+ { return t; }
+};
+
+//////////////////////////////////////
+// is_class_or_union
+//////////////////////////////////////
+template<class T>
+struct is_class_or_union
+{
+ struct twochar { char dummy[2]; };
+ template <class U>
+ static char is_class_or_union_tester(void(U::*)(void));
+ template <class U>
+ static twochar is_class_or_union_tester(...);
+ static const bool value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(char);
+};
+
+//////////////////////////////////////
+// addressof
+//////////////////////////////////////
+template<class T>
+struct addr_impl_ref
+{
+ T & v_;
+ BOOST_MOVE_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {}
+ BOOST_MOVE_FORCEINLINE operator T& () const { return v_; }
+
+ private:
+ addr_impl_ref & operator=(const addr_impl_ref &);
+};
+
+template<class T>
+struct addressof_impl
+{
+ BOOST_MOVE_FORCEINLINE static T * f( T & v, long )
+ {
+ return reinterpret_cast<T*>(
+ &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
+ }
+
+ BOOST_MOVE_FORCEINLINE static T * f( T * v, int )
+ { return v; }
+};
+
+template<class T>
+BOOST_MOVE_FORCEINLINE T * addressof( T & v )
+{
+ return ::boost::move_detail::addressof_impl<T>::f
+ ( ::boost::move_detail::addr_impl_ref<T>( v ), 0 );
+}
+
+//////////////////////////////////////
+// has_pointer_type
+//////////////////////////////////////
+template <class T>
+struct has_pointer_type
+{
+ struct two { char c[2]; };
+ template <class U> static two test(...);
+ template <class U> static char test(typename U::pointer* = 0);
+ static const bool value = sizeof(test<T>(0)) == 1;
+};
+
+//////////////////////////////////////
+// is_convertible
+//////////////////////////////////////
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+
+//use intrinsic since in MSVC
+//overaligned types can't go through ellipsis
+template <class T, class U>
+struct is_convertible
+{
+ static const bool value = __is_convertible_to(T, U);
+};
+
+#else
+
+template <class T, class U>
+class is_convertible
+{
+ typedef typename add_lvalue_reference<T>::type t_reference;
+ typedef char true_t;
+ class false_t { char dummy[2]; };
+ static false_t dispatch(...);
+ static true_t dispatch(U);
+ static t_reference trigger();
+ public:
+ static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
+};
+
+#endif
+
+template <class T, class U, bool IsSame = is_same<T, U>::value>
+struct is_same_or_convertible
+ : is_convertible<T, U>
+{};
+
+template <class T, class U>
+struct is_same_or_convertible<T, U, true>
+{
+ static const bool value = true;
+};
+
+template<
+ bool C
+ , typename F1
+ , typename F2
+ >
+struct eval_if_c
+ : if_c<C,F1,F2>::type
+{};
+
+template<
+ typename C
+ , typename T1
+ , typename T2
+ >
+struct eval_if
+ : if_<C,T1,T2>::type
+{};
+
+
+#if defined(BOOST_GCC) && (BOOST_GCC <= 40000)
+#define BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN
+#endif
+
+template<class T, class U, class R = void>
+struct enable_if_convertible
+ : enable_if< is_convertible<T, U>, R>
+{};
+
+template<class T, class U, class R = void>
+struct disable_if_convertible
+ : disable_if< is_convertible<T, U>, R>
+{};
+
+template<class T, class U, class R = void>
+struct enable_if_same_or_convertible
+ : enable_if< is_same_or_convertible<T, U>, R>
+{};
+
+template<class T, class U, class R = void>
+struct disable_if_same_or_convertible
+ : disable_if< is_same_or_convertible<T, U>, R>
+{};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// and_
+//
+//////////////////////////////////////////////////////////////////////////////
+template<bool, class B = true_, class C = true_, class D = true_>
+struct and_impl
+ : and_impl<B::value, C, D>
+{};
+
+template<>
+struct and_impl<true, true_, true_, true_>
+{
+ static const bool value = true;
+};
+
+template<class B, class C, class D>
+struct and_impl<false, B, C, D>
+{
+ static const bool value = false;
+};
+
+template<class A, class B, class C = true_, class D = true_>
+struct and_
+ : and_impl<A::value, B, C, D>
+{};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// or_
+//
+//////////////////////////////////////////////////////////////////////////////
+template<bool, class B = false_, class C = false_, class D = false_>
+struct or_impl
+ : or_impl<B::value, C, D>
+{};
+
+template<>
+struct or_impl<false, false_, false_, false_>
+{
+ static const bool value = false;
+};
+
+template<class B, class C, class D>
+struct or_impl<true, B, C, D>
+{
+ static const bool value = true;
+};
+
+template<class A, class B, class C = false_, class D = false_>
+struct or_
+ : or_impl<A::value, B, C, D>
+{};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// not_
+//
+//////////////////////////////////////////////////////////////////////////////
+template<class T>
+struct not_
+{
+ static const bool value = !T::value;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// enable_if_and / disable_if_and / enable_if_or / disable_if_or
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template<class R, class A, class B, class C = true_, class D = true_>
+struct enable_if_and
+ : enable_if_c< and_<A, B, C, D>::value, R>
+{};
+
+template<class R, class A, class B, class C = true_, class D = true_>
+struct disable_if_and
+ : disable_if_c< and_<A, B, C, D>::value, R>
+{};
+
+template<class R, class A, class B, class C = false_, class D = false_>
+struct enable_if_or
+ : enable_if_c< or_<A, B, C, D>::value, R>
+{};
+
+template<class R, class A, class B, class C = false_, class D = false_>
+struct disable_if_or
+ : disable_if_c< or_<A, B, C, D>::value, R>
+{};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// has_move_emulation_enabled_impl
+//
+//////////////////////////////////////////////////////////////////////////////
+template<class T>
+struct has_move_emulation_enabled_impl
+ : is_convertible< T, ::boost::rv<T>& >
+{};
+
+template<class T>
+struct has_move_emulation_enabled_impl<T&>
+{ static const bool value = false; };
+
+template<class T>
+struct has_move_emulation_enabled_impl< ::boost::rv<T> >
+{ static const bool value = false; };
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// is_rv_impl
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+struct is_rv_impl
+{ static const bool value = false; };
+
+template <class T>
+struct is_rv_impl< rv<T> >
+{ static const bool value = true; };
+
+template <class T>
+struct is_rv_impl< const rv<T> >
+{ static const bool value = true; };
+
+// Code from Jeffrey Lee Hellrung, many thanks
+
+template< class T >
+struct is_rvalue_reference
+{ static const bool value = false; };
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template< class T >
+struct is_rvalue_reference< T&& >
+{ static const bool value = true; };
+
+#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template< class T >
+struct is_rvalue_reference< boost::rv<T>& >
+{ static const bool value = true; };
+
+template< class T >
+struct is_rvalue_reference< const boost::rv<T>& >
+{ static const bool value = true; };
+
+#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template< class T >
+struct add_rvalue_reference
+{ typedef T&& type; };
+
+#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+namespace detail_add_rvalue_reference
+{
+ template< class T
+ , bool emulation = has_move_emulation_enabled_impl<T>::value
+ , bool rv = is_rv_impl<T>::value >
+ struct add_rvalue_reference_impl { typedef T type; };
+
+ template< class T, bool emulation>
+ struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };
+
+ template< class T, bool rv >
+ struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv<T>& type; };
+} // namespace detail_add_rvalue_reference
+
+template< class T >
+struct add_rvalue_reference
+ : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
+{ };
+
+template< class T >
+struct add_rvalue_reference<T &>
+{ typedef T & type; };
+
+#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template< class T > struct remove_rvalue_reference { typedef T type; };
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template< class T > struct remove_rvalue_reference< T&& > { typedef T type; };
+#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template< class T > struct remove_rvalue_reference< rv<T> > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< const rv<T> > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< volatile rv<T> > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< const volatile rv<T> > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< rv<T>& > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< const rv<T>& > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< volatile rv<T>& > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< const volatile rv<T>& >{ typedef T type; };
+#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+// Ideas from Boost.Move review, Jeffrey Lee Hellrung:
+//
+//- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ?
+// Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue
+// references the same as wrt real rvalue references, i.e., add_reference< rv<T>& > -> T& rather than
+// rv<T>& (since T&& & -> T&).
+//
+//- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
+//
+//- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated
+// rvalue references in C++03. This may be necessary to prevent "accidental moves".
+
+} //namespace move_detail {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
diff --git a/include/boost/move/detail/meta_utils_core.hpp b/include/boost/move/detail/meta_utils_core.hpp
new file mode 100644
index 0000000..40dbb6e
--- /dev/null
+++ b/include/boost/move/detail/meta_utils_core.hpp
@@ -0,0 +1,132 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_META_UTILS_CORE_HPP
+#define BOOST_MOVE_DETAIL_META_UTILS_CORE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//Small meta-typetraits to support move
+
+namespace boost {
+namespace move_detail {
+
+//////////////////////////////////////
+// if_c
+//////////////////////////////////////
+template<bool C, typename T1, typename T2>
+struct if_c
+{
+ typedef T1 type;
+};
+
+template<typename T1, typename T2>
+struct if_c<false,T1,T2>
+{
+ typedef T2 type;
+};
+
+//////////////////////////////////////
+// if_
+//////////////////////////////////////
+template<typename T1, typename T2, typename T3>
+struct if_ : if_c<0 != T1::value, T2, T3>
+{};
+
+//////////////////////////////////////
+// enable_if_c
+//////////////////////////////////////
+template <bool B, class T = void>
+struct enable_if_c
+{
+ typedef T type;
+};
+
+template <class T>
+struct enable_if_c<false, T> {};
+
+//////////////////////////////////////
+// enable_if
+//////////////////////////////////////
+template <class Cond, class T = void>
+struct enable_if : enable_if_c<Cond::value, T> {};
+
+//////////////////////////////////////
+// disable_if_c
+//////////////////////////////////////
+template <bool B, class T = void>
+struct disable_if_c
+ : enable_if_c<!B, T>
+{};
+
+//////////////////////////////////////
+// disable_if
+//////////////////////////////////////
+template <class Cond, class T = void>
+struct disable_if : enable_if_c<!Cond::value, T> {};
+
+//////////////////////////////////////
+// integral_constant
+//////////////////////////////////////
+template<class T, T v>
+struct integral_constant
+{
+ static const T value = v;
+ typedef T value_type;
+ typedef integral_constant<T, v> type;
+
+ operator T() const { return value; }
+ T operator()() const { return value; }
+};
+
+typedef integral_constant<bool, true > true_type;
+typedef integral_constant<bool, false > false_type;
+
+
+//////////////////////////////////////
+// is_same
+//////////////////////////////////////
+template<class T, class U>
+struct is_same
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_same<T, T>
+{
+ static const bool value = true;
+};
+
+//////////////////////////////////////
+// enable_if_same
+//////////////////////////////////////
+template <class T, class U, class R = void>
+struct enable_if_same : enable_if<is_same<T, U>, R> {};
+
+//////////////////////////////////////
+// disable_if_same
+//////////////////////////////////////
+template <class T, class U, class R = void>
+struct disable_if_same : disable_if<is_same<T, U>, R> {};
+
+} //namespace move_detail {
+} //namespace boost {
+
+#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_CORE_HPP
diff --git a/include/boost/move/detail/move_helpers.hpp b/include/boost/move/detail/move_helpers.hpp
new file mode 100644
index 0000000..1713844
--- /dev/null
+++ b/include/boost/move/detail/move_helpers.hpp
@@ -0,0 +1,256 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2010-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_MOVE_HELPERS_HPP
+#define BOOST_MOVE_MOVE_HELPERS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/core.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/type_traits.hpp>
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+#define BOOST_MOVE_CATCH_CONST(U) \
+ typename ::boost::move_detail::if_< ::boost::move_detail::is_class<U>, BOOST_CATCH_CONST_RLVALUE(U), const U &>::type
+#define BOOST_MOVE_CATCH_RVALUE(U)\
+ typename ::boost::move_detail::if_< ::boost::move_detail::is_class<U>, BOOST_RV_REF(U), ::boost::move_detail::nat>::type
+#define BOOST_MOVE_CATCH_FWD(U) BOOST_FWD_REF(U)
+#else
+#define BOOST_MOVE_CATCH_CONST(U) const U &
+#define BOOST_MOVE_CATCH_RVALUE(U) U &&
+#define BOOST_MOVE_CATCH_FWD(U) U &&
+#endif
+
+////////////////////////////////////////
+//
+// BOOST_MOVE_CONVERSION_AWARE_CATCH
+//
+////////////////////////////////////////
+
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class TYPE>
+ struct boost_move_conversion_aware_catch_1
+ : public ::boost::move_detail::enable_if_and
+ < RETURN_VALUE
+ , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::is_class<TYPE>
+ , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>
+ >
+ {};
+
+ template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class TYPE>
+ struct boost_move_conversion_aware_catch_2
+ : public ::boost::move_detail::disable_if_or
+ < RETURN_VALUE
+ , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::and_
+ < ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::is_class<BOOST_MOVE_TEMPL_PARAM>
+ >
+ >
+ {};
+
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
+ { return FWD_FUNCTION(static_cast<const TYPE&>(x)); }\
+ \
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
+ { return FWD_FUNCTION(::boost::move(x)); }\
+ \
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(TYPE &x)\
+ { return FWD_FUNCTION(const_cast<const TYPE &>(x)); }\
+ //
+ #if defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u,\
+ typename boost_move_conversion_aware_catch_1< ::boost::move_detail::nat, BOOST_MOVE_TEMPL_PARAM, TYPE>::type* = 0)\
+ { return FWD_FUNCTION(u); }\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u,\
+ typename boost_move_conversion_aware_catch_2< ::boost::move_detail::nat, BOOST_MOVE_TEMPL_PARAM, TYPE>::type* = 0)\
+ {\
+ TYPE t((u));\
+ return FWD_FUNCTION(::boost::move(t));\
+ }\
+ //
+ #else
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE typename boost_move_conversion_aware_catch_1<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, TYPE>::type\
+ PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
+ { return FWD_FUNCTION(u); }\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE typename boost_move_conversion_aware_catch_2<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, TYPE>::type\
+ PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
+ {\
+ TYPE t((u));\
+ return FWD_FUNCTION(::boost::move(t));\
+ }\
+ //
+ #endif
+#elif (defined(_MSC_VER) && (_MSC_VER == 1600))
+
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
+ { return FWD_FUNCTION(static_cast<const TYPE&>(x)); }\
+ \
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
+ { return FWD_FUNCTION(::boost::move(x)); }\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c\
+ < !::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value\
+ , RETURN_VALUE >::type\
+ PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
+ {\
+ TYPE t((u));\
+ return FWD_FUNCTION(::boost::move(t));\
+ }\
+ //
+
+#else //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
+ { return FWD_FUNCTION(x); }\
+ \
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
+ { return FWD_FUNCTION(::boost::move(x)); }\
+ //
+
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+////////////////////////////////////////
+//
+// BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG
+//
+////////////////////////////////////////
+
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class UNLESS_CONVERTIBLE_TO, class TYPE>
+ struct boost_move_conversion_aware_catch_1arg_1
+ : public ::boost::move_detail::enable_if_and
+ < RETURN_VALUE
+ , ::boost::move_detail::not_< ::boost::move_detail::is_same_or_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> >
+ , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>
+ >
+ {};
+
+ template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class UNLESS_CONVERTIBLE_TO, class TYPE>
+ struct boost_move_conversion_aware_catch_1arg_2
+ : public ::boost::move_detail::disable_if_or
+ < RETURN_VALUE
+ , ::boost::move_detail::is_same_or_convertible< BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>
+ , ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
+ , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
+ >
+ {};
+
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
+ { return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
+ \
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
+ { return FWD_FUNCTION(arg1, ::boost::move(x)); }\
+ \
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, TYPE &x)\
+ { return FWD_FUNCTION(arg1, const_cast<const TYPE &>(x)); }\
+ //
+ #if defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u,\
+ typename boost_move_conversion_aware_catch_1arg_1<void, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type* = 0)\
+ { return FWD_FUNCTION(arg1, u); }\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u,\
+ typename boost_move_conversion_aware_catch_1arg_2<void, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type* = 0)\
+ {\
+ TYPE t((u));\
+ return FWD_FUNCTION(arg1, ::boost::move(t));\
+ }\
+ //
+ #else
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE typename boost_move_conversion_aware_catch_1arg_1<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type\
+ PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
+ { return FWD_FUNCTION(arg1, u); }\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE typename boost_move_conversion_aware_catch_1arg_2<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type\
+ PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
+ {\
+ TYPE t((u));\
+ return FWD_FUNCTION(arg1, ::boost::move(t));\
+ }\
+ //
+ #endif
+
+#elif (defined(_MSC_VER) && (_MSC_VER == 1600))
+
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
+ { return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
+ \
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
+ { return FWD_FUNCTION(arg1, ::boost::move(x)); }\
+ \
+ template<class BOOST_MOVE_TEMPL_PARAM>\
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::disable_if_or\
+ < RETURN_VALUE \
+ , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM> \
+ , ::boost::move_detail::is_same_or_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> \
+ >::type\
+ PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
+ {\
+ TYPE t((u));\
+ return FWD_FUNCTION(arg1, ::boost::move(t));\
+ }\
+ //
+
+#else
+
+ #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
+ { return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
+ \
+ BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
+ { return FWD_FUNCTION(arg1, ::boost::move(x)); }\
+ //
+
+#endif
+
+#endif //#ifndef BOOST_MOVE_MOVE_HELPERS_HPP
diff --git a/include/boost/move/detail/placement_new.hpp b/include/boost/move/detail/placement_new.hpp
new file mode 100644
index 0000000..69d3332
--- /dev/null
+++ b/include/boost/move/detail/placement_new.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_MOVE_DETAIL_PLACEMENT_NEW_HPP
+#define BOOST_MOVE_DETAIL_PLACEMENT_NEW_HPP
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-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/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+struct boost_move_new_t{};
+
+//avoid including <new>
+inline void *operator new(std::size_t, void *p, boost_move_new_t)
+{ return p; }
+
+inline void operator delete(void *, void *, boost_move_new_t)
+{}
+
+#endif //BOOST_MOVE_DETAIL_PLACEMENT_NEW_HPP
diff --git a/include/boost/move/detail/pointer_element.hpp b/include/boost/move/detail/pointer_element.hpp
new file mode 100644
index 0000000..ecdd608
--- /dev/null
+++ b/include/boost/move/detail/pointer_element.hpp
@@ -0,0 +1,168 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_DETAIL_POINTER_ELEMENT_HPP
+#define BOOST_MOVE_DETAIL_POINTER_ELEMENT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
+#include <boost/move/detail/workaround.hpp>
+#endif //BOOST_MOVE_DETAIL_WORKAROUND_HPP
+
+namespace boost {
+namespace movelib {
+namespace detail{
+
+//////////////////////
+//struct first_param
+//////////////////////
+
+template <typename T> struct first_param
+{ typedef void type; };
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <template <typename, typename...> class TemplateClass, typename T, typename... Args>
+ struct first_param< TemplateClass<T, Args...> >
+ {
+ typedef T type;
+ };
+
+#else //C++03 compilers
+
+ template < template //0arg
+ <class
+ > class TemplateClass, class T
+ >
+ struct first_param
+ < TemplateClass<T> >
+ { typedef T type; };
+
+ template < template //1arg
+ <class,class
+ > class TemplateClass, class T
+ , class P0>
+ struct first_param
+ < TemplateClass<T, P0> >
+ { typedef T type; };
+
+ template < template //2arg
+ <class,class,class
+ > class TemplateClass, class T
+ , class P0, class P1>
+ struct first_param
+ < TemplateClass<T, P0, P1> >
+ { typedef T type; };
+
+ template < template //3arg
+ <class,class,class,class
+ > class TemplateClass, class T
+ , class P0, class P1, class P2>
+ struct first_param
+ < TemplateClass<T, P0, P1, P2> >
+ { typedef T type; };
+
+ template < template //4arg
+ <class,class,class,class,class
+ > class TemplateClass, class T
+ , class P0, class P1, class P2, class P3>
+ struct first_param
+ < TemplateClass<T, P0, P1, P2, P3> >
+ { typedef T type; };
+
+ template < template //5arg
+ <class,class,class,class,class,class
+ > class TemplateClass, class T
+ , class P0, class P1, class P2, class P3, class P4>
+ struct first_param
+ < TemplateClass<T, P0, P1, P2, P3, P4> >
+ { typedef T type; };
+
+ template < template //6arg
+ <class,class,class,class,class,class,class
+ > class TemplateClass, class T
+ , class P0, class P1, class P2, class P3, class P4, class P5>
+ struct first_param
+ < TemplateClass<T, P0, P1, P2, P3, P4, P5> >
+ { typedef T type; };
+
+ template < template //7arg
+ <class,class,class,class,class,class,class,class
+ > class TemplateClass, class T
+ , class P0, class P1, class P2, class P3, class P4, class P5, class P6>
+ struct first_param
+ < TemplateClass<T, P0, P1, P2, P3, P4, P5, P6> >
+ { typedef T type; };
+
+ template < template //8arg
+ <class,class,class,class,class,class,class,class,class
+ > class TemplateClass, class T
+ , class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
+ struct first_param
+ < TemplateClass<T, P0, P1, P2, P3, P4, P5, P6, P7> >
+ { typedef T type; };
+
+ template < template //9arg
+ <class,class,class,class,class,class,class,class,class,class
+ > class TemplateClass, class T
+ , class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
+ struct first_param
+ < TemplateClass<T, P0, P1, P2, P3, P4, P5, P6, P7, P8> >
+ { typedef T type; };
+
+#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template <typename T>
+struct has_internal_pointer_element
+{
+ template <typename X>
+ static char test(int, typename X::element_type*);
+
+ template <typename X>
+ static int test(...);
+
+ static const bool value = (1 == sizeof(test<T>(0, 0)));
+};
+
+template<class Ptr, bool = has_internal_pointer_element<Ptr>::value>
+struct pointer_element_impl
+{
+ typedef typename Ptr::element_type type;
+};
+
+template<class Ptr>
+struct pointer_element_impl<Ptr, false>
+{
+ typedef typename boost::movelib::detail::first_param<Ptr>::type type;
+};
+
+} //namespace detail{
+
+template <typename Ptr>
+struct pointer_element
+{
+ typedef typename ::boost::movelib::detail::pointer_element_impl<Ptr>::type type;
+};
+
+template <typename T>
+struct pointer_element<T*>
+{ typedef T type; };
+
+} //namespace movelib {
+} //namespace boost {
+
+#endif // defined(BOOST_MOVE_DETAIL_POINTER_ELEMENT_HPP)
diff --git a/include/boost/move/detail/reverse_iterator.hpp b/include/boost/move/detail/reverse_iterator.hpp
new file mode 100644
index 0000000..73f59ce
--- /dev/null
+++ b/include/boost/move/detail/reverse_iterator.hpp
@@ -0,0 +1,171 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (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_DETAIL_REVERSE_ITERATOR_HPP
+#define BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/detail/meta_utils.hpp>
+
+namespace boost {
+namespace movelib {
+
+template<class It>
+class reverse_iterator
+{
+ public:
+ typedef typename boost::movelib::iterator_traits<It>::pointer pointer;
+ typedef typename boost::movelib::iterator_traits<It>::reference reference;
+ typedef typename boost::movelib::iterator_traits<It>::difference_type difference_type;
+ typedef typename boost::movelib::iterator_traits<It>::iterator_category iterator_category;
+ typedef typename boost::movelib::iterator_traits<It>::value_type value_type;
+
+
+ typedef It iterator_type;
+
+ reverse_iterator()
+ : m_current() //Value initialization to achieve "null iterators" (N3644)
+ {}
+
+ explicit reverse_iterator(It r)
+ : m_current(r)
+ {}
+
+ reverse_iterator(const reverse_iterator& r)
+ : m_current(r.base())
+ {}
+
+ template<class OtherIt>
+ reverse_iterator( const reverse_iterator<OtherIt>& r
+ , typename boost::move_detail::enable_if_convertible<OtherIt, It>::type* =0
+ )
+ : m_current(r.base())
+ {}
+
+ reverse_iterator & operator=( const reverse_iterator& r)
+ { m_current = r.base(); return *this; }
+
+ template<class OtherIt>
+ typename boost::move_detail::enable_if_convertible<OtherIt, It, reverse_iterator &>::type
+ operator=( const reverse_iterator<OtherIt>& r)
+ { m_current = r.base(); return *this; }
+
+ It base() const
+ { return m_current; }
+
+ reference operator*() const
+ {
+ It temp(m_current);
+ --temp;
+ reference r = *temp;
+ return r;
+ }
+
+ pointer operator->() const
+ {
+ It temp(m_current);
+ --temp;
+ return iterator_arrow_result(temp);
+ }
+
+ reference operator[](difference_type off) const
+ {
+ return this->m_current[-off - 1];
+ }
+
+ reverse_iterator& operator++()
+ {
+ --m_current;
+ return *this;
+ }
+
+ reverse_iterator operator++(int)
+ {
+ reverse_iterator temp((*this));
+ --m_current;
+ return temp;
+ }
+
+ reverse_iterator& operator--()
+ {
+ ++m_current;
+ return *this;
+ }
+
+ reverse_iterator operator--(int)
+ {
+ reverse_iterator temp((*this));
+ ++m_current;
+ return temp;
+ }
+
+ friend bool operator==(const reverse_iterator& l, const reverse_iterator& r)
+ { return l.m_current == r.m_current; }
+
+ friend bool operator!=(const reverse_iterator& l, const reverse_iterator& r)
+ { return l.m_current != r.m_current; }
+
+ friend bool operator<(const reverse_iterator& l, const reverse_iterator& r)
+ { return l.m_current > r.m_current; }
+
+ friend bool operator<=(const reverse_iterator& l, const reverse_iterator& r)
+ { return l.m_current >= r.m_current; }
+
+ friend bool operator>(const reverse_iterator& l, const reverse_iterator& r)
+ { return l.m_current < r.m_current; }
+
+ friend bool operator>=(const reverse_iterator& l, const reverse_iterator& r)
+ { return l.m_current <= r.m_current; }
+
+ reverse_iterator& operator+=(difference_type off)
+ { m_current -= off; return *this; }
+
+ reverse_iterator& operator-=(difference_type off)
+ { m_current += off; return *this; }
+
+ friend reverse_iterator operator+(reverse_iterator l, difference_type off)
+ { return (l += off); }
+
+ friend reverse_iterator operator+(difference_type off, reverse_iterator r)
+ { return (r += off); }
+
+ friend reverse_iterator operator-(reverse_iterator l, difference_type off)
+ { return (l-= off); }
+
+ friend difference_type operator-(const reverse_iterator& l, const reverse_iterator& r)
+ { return r.m_current - l.m_current; }
+
+ private:
+ It m_current; // the wrapped iterator
+};
+
+template< class Iterator >
+reverse_iterator<Iterator> make_reverse_iterator( Iterator i )
+{
+ return reverse_iterator<Iterator>(i);
+}
+
+} //namespace movelib {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP
diff --git a/include/boost/move/detail/std_ns_begin.hpp b/include/boost/move/detail/std_ns_begin.hpp
new file mode 100644
index 0000000..a768e61
--- /dev/null
+++ b/include/boost/move/detail/std_ns_begin.hpp
@@ -0,0 +1,30 @@
+#//////////////////////////////////////////////////////////////////////////////
+#//
+#// (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.
+#//
+#//////////////////////////////////////////////////////////////////////////////
+#
+#if defined(_LIBCPP_VERSION)
+ #if defined(__clang__)
+ #define BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wc++11-extensions"
+ #endif
+ #define BOOST_MOVE_STD_NS_BEG _LIBCPP_BEGIN_NAMESPACE_STD
+ #define BOOST_MOVE_STD_NS_END _LIBCPP_END_NAMESPACE_STD
+#elif defined(BOOST_GNU_STDLIB) && defined(_GLIBCXX_BEGIN_NAMESPACE_VERSION) //GCC >= 4.6
+ #define BOOST_MOVE_STD_NS_BEG namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ #define BOOST_MOVE_STD_NS_END _GLIBCXX_END_NAMESPACE_VERSION } // namespace
+#elif defined(BOOST_GNU_STDLIB) && defined(_GLIBCXX_BEGIN_NAMESPACE) //GCC >= 4.2
+ #define BOOST_MOVE_STD_NS_BEG _GLIBCXX_BEGIN_NAMESPACE(std)
+ #define BOOST_MOVE_STD_NS_END _GLIBCXX_END_NAMESPACE
+#else
+ #define BOOST_MOVE_STD_NS_BEG namespace std{
+ #define BOOST_MOVE_STD_NS_END }
+#endif
+
diff --git a/include/boost/move/detail/std_ns_end.hpp b/include/boost/move/detail/std_ns_end.hpp
new file mode 100644
index 0000000..0975059
--- /dev/null
+++ b/include/boost/move/detail/std_ns_end.hpp
@@ -0,0 +1,14 @@
+#//////////////////////////////////////////////////////////////////////////////
+#//
+#// (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.
+#//
+#//////////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
+ #pragma GCC diagnostic pop
+ #undef BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
+#endif //BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
diff --git a/include/boost/move/detail/to_raw_pointer.hpp b/include/boost/move/detail/to_raw_pointer.hpp
new file mode 100644
index 0000000..7e89beb
--- /dev/null
+++ b/include/boost/move/detail/to_raw_pointer.hpp
@@ -0,0 +1,45 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-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.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_DETAIL_TO_RAW_POINTER_HPP
+#define BOOST_MOVE_DETAIL_TO_RAW_POINTER_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+#include <boost/move/detail/pointer_element.hpp>
+
+namespace boost {
+namespace movelib {
+
+template <class T>
+BOOST_MOVE_FORCEINLINE T* to_raw_pointer(T* p)
+{ return p; }
+
+template <class Pointer>
+BOOST_MOVE_FORCEINLINE typename boost::movelib::pointer_element<Pointer>::type*
+to_raw_pointer(const Pointer &p)
+{ return ::boost::movelib::to_raw_pointer(p.operator->()); }
+
+} //namespace movelib
+} //namespace boost
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //BOOST_MOVE_DETAIL_TO_RAW_POINTER_HPP
diff --git a/include/boost/move/detail/type_traits.hpp b/include/boost/move/detail/type_traits.hpp
new file mode 100644
index 0000000..a3326d0
--- /dev/null
+++ b/include/boost/move/detail/type_traits.hpp
@@ -0,0 +1,1086 @@
+//////////////////////////////////////////////////////////////////////////////
+// (C) Copyright John Maddock 2000.
+// (C) Copyright Ion Gaztanaga 2005-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.
+//
+// The alignment and Type traits implementation comes from
+// John Maddock's TypeTraits library.
+//
+// Some other tricks come from Howard Hinnant's papers and StackOverflow replies
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP
+#define BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+
+// move/detail
+#include <boost/move/detail/meta_utils.hpp>
+// other
+#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
+// std
+#include <cstddef>
+
+//Use of Boost.TypeTraits leads to long preprocessed source code due to
+//MPL dependencies. We'll use intrinsics directly and make or own
+//simplified version of TypeTraits.
+//If someday Boost.TypeTraits dependencies are minimized, we should
+//revisit this file redirecting code to Boost.TypeTraits traits.
+
+//These traits don't care about volatile, reference or other checks
+//made by Boost.TypeTraits because no volatile or reference types
+//can be hold in Boost.Containers. This helps to avoid any Boost.TypeTraits
+//dependency.
+
+// Helper macros for builtin compiler support.
+// If your compiler has builtin support for any of the following
+// traits concepts, then redefine the appropriate macros to pick
+// up on the compiler support:
+//
+// (these should largely ignore cv-qualifiers)
+// BOOST_MOVE_IS_POD(T) should evaluate to true if T is a POD type
+// BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect
+// BOOST_MOVE_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy
+// (Note: this trait does not guarantee T is copy constructible, the copy constructor could be deleted but still be trivial)
+// BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) should evaluate to true if T(boost::move(t)) <==> memcpy
+// BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy
+// (Note: this trait does not guarantee T is assignable , the copy assignmen could be deleted but still be trivial)
+// BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) should evaluate to true if t = boost::move(u) <==> memcpy
+// BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect
+// BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) should evaluate to true if "T x;" can not throw
+// BOOST_MOVE_HAS_NOTHROW_COPY(T) should evaluate to true if T(t) can not throw
+// BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) should evaluate to true if t = u can not throw
+// BOOST_MOVE_IS_ENUM(T) should evaluate to true it t is a union type.
+//
+// The following can also be defined: when detected our implementation is greatly simplified.
+//
+// BOOST_ALIGNMENT_OF(T) should evaluate to the alignment requirements of type T.
+
+#if defined(__MSL_CPP__) && (__MSL_CPP__ >= 0x8000)
+ // Metrowerks compiler is acquiring intrinsic type traits support
+ // post version 8. We hook into the published interface to pick up
+ // user defined specializations as well as compiler intrinsics as
+ // and when they become available:
+# include <msl_utility>
+# define BOOST_MOVE_IS_UNION(T) BOOST_STD_EXTENSION_NAMESPACE::is_union<T>::value
+# define BOOST_MOVE_IS_POD(T) BOOST_STD_EXTENSION_NAMESPACE::is_POD<T>::value
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_default_ctor<T>::value
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_copy_ctor<T>::value
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_assignment<T>::value
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_dtor<T>::value
+#endif
+
+#if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\
+ || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500))
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# define BOOST_MOVE_IS_POD(T) (__is_pod(T) && __has_trivial_constructor(T))
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T)|| ::boost::move_detail::is_pod<T>::value)
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) || ::boost::move_detail::is_pod<T>::value)
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) || ::boost::move_detail::is_pod<T>::value)
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) || ::boost::move_detail::is_trivially_default_constructible<T>::value)
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T) || ::boost::move_detail::is_trivially_copy_constructible<T>::value)
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T) || ::boost::move_detail::is_trivially_copy_assignable<T>::value)
+
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# if defined(_MSC_VER) && (_MSC_VER >= 1700)
+# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__has_trivial_move_constructor(T) || ::boost::move_detail::is_pod<T>::value)
+# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) (__has_trivial_move_assign(T) || ::boost::move_detail::is_pod<T>::value)
+# endif
+#endif
+
+#if defined(BOOST_CLANG) && defined(__has_feature)
+
+# if __has_feature(is_union)
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# endif
+# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_pod)
+# define BOOST_MOVE_IS_POD(T) __is_pod(T)
+# endif
+# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_empty)
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# endif
+# if __has_feature(has_trivial_constructor)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
+# endif
+# if __has_feature(has_trivial_copy)
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) __has_trivial_copy(T)
+# endif
+# if __has_feature(has_trivial_assign)
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) )
+# endif
+# if __has_feature(has_trivial_destructor)
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
+# endif
+# if __has_feature(has_nothrow_constructor)
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T)
+# endif
+# if __has_feature(has_nothrow_copy)
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T))
+# endif
+# if __has_feature(is_nothrow_copy_assignable)
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
+# endif
+# if __has_feature(is_enum)
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# endif
+# if __has_feature(has_trivial_move_constructor)
+# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) __has_trivial_move_constructor(T)
+# endif
+# if __has_feature(has_trivial_move_assign)
+# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) __has_trivial_move_assign(T)
+# endif
+# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof(T)
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG)
+
+#ifdef BOOST_INTEL
+# define BOOST_MOVE_INTEL_TT_OPTS || ::boost::move_detail::is_pod<T>::value
+#else
+# define BOOST_MOVE_INTEL_TT_OPTS
+#endif
+
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# define BOOST_MOVE_IS_POD(T) __is_pod(T)
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) ((__has_trivial_constructor(T) BOOST_MOVE_INTEL_TT_OPTS))
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_MOVE_INTEL_TT_OPTS))
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_MOVE_INTEL_TT_OPTS) )
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_MOVE_INTEL_TT_OPTS)
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) BOOST_MOVE_INTEL_TT_OPTS)
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) BOOST_MOVE_INTEL_TT_OPTS))
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_MOVE_INTEL_TT_OPTS))
+
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# if (!defined(unix) && !defined(__unix__)) || defined(__LP64__)
+ // GCC sometimes lies about alignment requirements
+ // of type double on 32-bit unix platforms, use the
+ // old implementation instead in that case:
+# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof__(T)
+# endif
+#endif
+
+#if defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600)
+
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# define BOOST_MOVE_IS_POD(T) __is_pod(T)
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T))
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T))
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T)
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T))
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
+
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof__(T)
+#endif
+
+# if defined(__CODEGEARC__)
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# define BOOST_MOVE_IS_POD(T) __is_pod(T)
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) (__has_trivial_default_constructor(T))
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy_constructor(T))
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T))
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T))
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_default_constructor(T))
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy_constructor(T))
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
+
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# define BOOST_MOVE_ALIGNMENT_OF(T) alignof(T)
+
+#endif
+
+//Fallback definitions
+
+#ifdef BOOST_MOVE_IS_UNION
+ #define BOOST_MOVE_IS_UNION_IMPL(T) BOOST_MOVE_IS_UNION(T)
+#else
+ #define BOOST_MOVE_IS_UNION_IMPL(T) false
+#endif
+
+#ifdef BOOST_MOVE_IS_POD
+ //in some compilers the intrinsic is limited to class types so add scalar and void
+ #define BOOST_MOVE_IS_POD_IMPL(T) (::boost::move_detail::is_scalar<T>::value ||\
+ ::boost::move_detail::is_void<T>::value ||\
+ BOOST_MOVE_IS_POD(T))
+#else
+ #define BOOST_MOVE_IS_POD_IMPL(T) \
+ (::boost::move_detail::is_scalar<T>::value || ::boost::move_detail::is_void<T>::value)
+#endif
+
+#ifdef BOOST_MOVE_IS_EMPTY
+ #define BOOST_MOVE_IS_EMPTY_IMPL(T) BOOST_MOVE_IS_EMPTY(T)
+#else
+ #define BOOST_MOVE_IS_EMPTY_IMPL(T) ::boost::move_detail::is_empty_nonintrinsic<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_COPY
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value ||\
+ (::boost::move_detail::is_copy_constructible<T>::value &&\
+ BOOST_MOVE_HAS_TRIVIAL_COPY(T))
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR
+ #define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR
+ #define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_ASSIGN
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value ||\
+ ( ::boost::move_detail::is_copy_assignable<T>::value &&\
+ BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T))
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN
+ #define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR
+ #define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR
+ #define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_COPY
+ #define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_COPY(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_MOVE
+ #define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_ASSIGN
+ #define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_ASSIGN(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN
+ #define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_IS_ENUM
+ #define BOOST_MOVE_IS_ENUM_IMPL(T) BOOST_MOVE_IS_ENUM(T)
+#else
+ #define BOOST_MOVE_IS_ENUM_IMPL(T) ::boost::move_detail::is_enum_nonintrinsic<T>::value
+#endif
+
+namespace boost {
+namespace move_detail {
+
+//////////////////////////
+// is_reference
+//////////////////////////
+template<class T>
+struct is_reference
+{ static const bool value = false; };
+
+template<class T>
+struct is_reference<T&>
+{ static const bool value = true; };
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template<class T>
+struct is_reference<T&&>
+{ static const bool value = true; };
+#endif
+
+//////////////////////////
+// is_pointer
+//////////////////////////
+template<class T>
+struct is_pointer
+{ static const bool value = false; };
+
+template<class T>
+struct is_pointer<T*>
+{ static const bool value = true; };
+
+//////////////////////////
+// is_const
+//////////////////////////
+template<class T>
+struct is_const
+{ static const bool value = false; };
+
+template<class T>
+struct is_const<const T>
+{ static const bool value = true; };
+
+//////////////////////////
+// unvoid_ref
+//////////////////////////
+template <typename T> struct unvoid_ref : add_lvalue_reference<T>{};
+template <> struct unvoid_ref<void> { typedef unvoid_ref & type; };
+template <> struct unvoid_ref<const void> { typedef unvoid_ref & type; };
+template <> struct unvoid_ref<volatile void> { typedef unvoid_ref & type; };
+template <> struct unvoid_ref<const volatile void> { typedef unvoid_ref & type; };
+
+template <typename T>
+struct add_reference : add_lvalue_reference<T>
+{};
+
+//////////////////////////
+// add_const_reference
+//////////////////////////
+template <class T>
+struct add_const_reference
+{ typedef const T &type; };
+
+template <class T>
+struct add_const_reference<T&>
+{ typedef T& type; };
+
+//////////////////////////
+// add_const_if_c
+//////////////////////////
+template<class T, bool Add>
+struct add_const_if_c
+ : if_c<Add, typename add_const<T>::type, T>
+{};
+
+//////////////////////////
+// remove_const
+//////////////////////////
+template<class T>
+struct remove_const
+{ typedef T type; };
+
+template<class T>
+struct remove_const< const T>
+{ typedef T type; };
+
+//////////////////////////
+// remove_cv
+//////////////////////////
+template<typename T> struct remove_cv { typedef T type; };
+template<typename T> struct remove_cv<const T> { typedef T type; };
+template<typename T> struct remove_cv<const volatile T> { typedef T type; };
+template<typename T> struct remove_cv<volatile T> { typedef T type; };
+
+//////////////////////////
+// make_unsigned
+//////////////////////////
+template <class T>
+struct make_unsigned_impl { typedef T type; };
+template <> struct make_unsigned_impl<signed char> { typedef unsigned char type; };
+template <> struct make_unsigned_impl<signed short> { typedef unsigned short type; };
+template <> struct make_unsigned_impl<signed int> { typedef unsigned int type; };
+template <> struct make_unsigned_impl<signed long> { typedef unsigned long type; };
+#ifdef BOOST_HAS_LONG_LONG
+template <> struct make_unsigned_impl< ::boost::long_long_type > { typedef ::boost::ulong_long_type type; };
+#endif
+
+template <class T>
+struct make_unsigned
+ : make_unsigned_impl<typename remove_cv<T>::type>
+{};
+
+//////////////////////////
+// is_floating_point
+//////////////////////////
+template<class T> struct is_floating_point_cv { static const bool value = false; };
+template<> struct is_floating_point_cv<float> { static const bool value = true; };
+template<> struct is_floating_point_cv<double> { static const bool value = true; };
+template<> struct is_floating_point_cv<long double> { static const bool value = true; };
+
+template<class T>
+struct is_floating_point
+ : is_floating_point_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////
+// is_integral
+//////////////////////////
+template<class T> struct is_integral_cv { static const bool value = false; };
+template<> struct is_integral_cv< bool>{ static const bool value = true; };
+template<> struct is_integral_cv< char>{ static const bool value = true; };
+template<> struct is_integral_cv< unsigned char>{ static const bool value = true; };
+template<> struct is_integral_cv< signed char>{ static const bool value = true; };
+#ifndef BOOST_NO_CXX11_CHAR16_T
+template<> struct is_integral_cv< char16_t>{ static const bool value = true; };
+#endif
+#ifndef BOOST_NO_CXX11_CHAR32_T
+template<> struct is_integral_cv< char32_t>{ static const bool value = true; };
+#endif
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<> struct is_integral_cv< wchar_t>{ static const bool value = true; };
+#endif
+template<> struct is_integral_cv< short>{ static const bool value = true; };
+template<> struct is_integral_cv< unsigned short>{ static const bool value = true; };
+template<> struct is_integral_cv< int>{ static const bool value = true; };
+template<> struct is_integral_cv< unsigned int>{ static const bool value = true; };
+template<> struct is_integral_cv< long>{ static const bool value = true; };
+template<> struct is_integral_cv< unsigned long>{ static const bool value = true; };
+#ifdef BOOST_HAS_LONG_LONG
+template<> struct is_integral_cv< ::boost:: long_long_type>{ static const bool value = true; };
+template<> struct is_integral_cv< ::boost::ulong_long_type>{ static const bool value = true; };
+#endif
+
+template<class T>
+struct is_integral
+ : public is_integral_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// remove_all_extents
+//////////////////////////////////////
+template <class T>
+struct remove_all_extents
+{ typedef T type;};
+
+template <class T>
+struct remove_all_extents<T[]>
+{ typedef typename remove_all_extents<T>::type type; };
+
+template <class T, std::size_t N>
+struct remove_all_extents<T[N]>
+{ typedef typename remove_all_extents<T>::type type;};
+
+//////////////////////////
+// is_scalar
+//////////////////////////
+template<class T>
+struct is_scalar
+{ static const bool value = is_integral<T>::value || is_floating_point<T>::value; };
+
+//////////////////////////
+// is_void
+//////////////////////////
+template<class T>
+struct is_void_cv
+{ static const bool value = false; };
+
+template<>
+struct is_void_cv<void>
+{ static const bool value = true; };
+
+template<class T>
+struct is_void
+ : is_void_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// is_array
+//////////////////////////////////////
+template<class T>
+struct is_array
+{ static const bool value = false; };
+
+template<class T>
+struct is_array<T[]>
+{ static const bool value = true; };
+
+template<class T, std::size_t N>
+struct is_array<T[N]>
+{ static const bool value = true; };
+
+//////////////////////////////////////
+// is_member_pointer
+//////////////////////////////////////
+template <class T> struct is_member_pointer_cv { static const bool value = false; };
+template <class T, class U>struct is_member_pointer_cv<T U::*> { static const bool value = true; };
+
+template <class T>
+struct is_member_pointer
+ : is_member_pointer_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// is_nullptr_t
+//////////////////////////////////////
+template <class T>
+struct is_nullptr_t_cv
+{ static const bool value = false; };
+
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+template <>
+struct is_nullptr_t_cv
+ #if !defined(BOOST_NO_CXX11_DECLTYPE)
+ <decltype(nullptr)>
+ #else
+ <std::nullptr_t>
+ #endif
+{ static const bool value = true; };
+#endif
+
+template <class T>
+struct is_nullptr_t
+ : is_nullptr_t_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// is_function
+//////////////////////////////////////
+//Inspired by libc++, thanks to Howard Hinnant
+//For a function to pointer an lvalue of function type T can be implicitly converted to a prvalue
+//pointer to that function. This does not apply to non-static member functions because lvalues
+//that refer to non-static member functions do not exist.
+template <class T>
+struct is_reference_convertible_to_pointer
+{
+ struct twochar { char dummy[2]; };
+ template <class U> static char test(U*);
+ template <class U> static twochar test(...);
+ static T& source();
+ static const bool value = sizeof(char) == sizeof(test<T>(source()));
+};
+//Filter out:
+// - class types that might have implicit conversions
+// - void (to avoid forming a reference to void later)
+// - references (e.g.: filtering reference to functions)
+// - nullptr_t (convertible to pointer)
+template < class T
+ , bool Filter = is_class_or_union<T>::value ||
+ is_void<T>::value ||
+ is_reference<T>::value ||
+ is_nullptr_t<T>::value >
+struct is_function_impl
+{ static const bool value = is_reference_convertible_to_pointer<T>::value; };
+
+template <class T>
+struct is_function_impl<T, true>
+{ static const bool value = false; };
+
+template <class T>
+struct is_function
+ : is_function_impl<T>
+{};
+
+//////////////////////////////////////
+// is_union
+//////////////////////////////////////
+template<class T>
+struct is_union_noextents_cv
+{ static const bool value = BOOST_MOVE_IS_UNION_IMPL(T); };
+
+template<class T>
+struct is_union
+ : is_union_noextents_cv<typename remove_cv<typename remove_all_extents<T>::type>::type>
+{};
+
+//////////////////////////////////////
+// is_class
+//////////////////////////////////////
+template <class T>
+struct is_class
+{
+ static const bool value = is_class_or_union<T>::value && ! is_union<T>::value;
+};
+
+
+//////////////////////////////////////
+// is_arithmetic
+//////////////////////////////////////
+template <class T>
+struct is_arithmetic
+{
+ static const bool value = is_floating_point<T>::value ||
+ is_integral<T>::value;
+};
+
+//////////////////////////////////////
+// is_member_function_pointer
+//////////////////////////////////////
+template <class T>
+struct is_member_function_pointer_cv
+{
+ static const bool value = false;
+};
+
+template <class T, class C>
+struct is_member_function_pointer_cv<T C::*>
+ : is_function<T>
+{};
+
+template <class T>
+struct is_member_function_pointer
+ : is_member_function_pointer_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// is_enum
+//////////////////////////////////////
+#if !defined(BOOST_MOVE_IS_ENUM)
+//Based on (http://howardhinnant.github.io/TypeHiearchy.pdf)
+template <class T>
+struct is_enum_nonintrinsic
+{
+ static const bool value = !is_arithmetic<T>::value &&
+ !is_reference<T>::value &&
+ !is_class_or_union<T>::value &&
+ !is_array<T>::value &&
+ !is_void<T>::value &&
+ !is_nullptr_t<T>::value &&
+ !is_member_pointer<T>::value &&
+ !is_pointer<T>::value &&
+ !is_function<T>::value;
+};
+#endif
+
+template <class T>
+struct is_enum
+{ static const bool value = BOOST_MOVE_IS_ENUM_IMPL(T); };
+
+//////////////////////////////////////
+// is_pod
+//////////////////////////////////////
+template<class T>
+struct is_pod_noextents_cv //for non-c++11 compilers, a safe fallback
+{ static const bool value = BOOST_MOVE_IS_POD_IMPL(T); };
+
+template<class T>
+struct is_pod
+ : is_pod_noextents_cv<typename remove_cv<typename remove_all_extents<T>::type>::type>
+{};
+
+//////////////////////////////////////
+// is_empty
+//////////////////////////////////////
+#if !defined(BOOST_MOVE_IS_EMPTY)
+
+template <typename T>
+struct empty_helper_t1 : public T
+{
+ empty_helper_t1(); // hh compiler bug workaround
+ int i[256];
+ private:
+
+ empty_helper_t1(const empty_helper_t1&);
+ empty_helper_t1& operator=(const empty_helper_t1&);
+};
+
+struct empty_helper_t2 { int i[256]; };
+
+template <typename T, bool IsClass = is_class<T>::value >
+struct is_empty_nonintrinsic
+{
+ static const bool value = false;
+};
+
+template <typename T>
+struct is_empty_nonintrinsic<T, true>
+{
+ static const bool value = sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2);
+};
+#endif
+
+template <class T>
+struct is_empty
+{ static const bool value = BOOST_MOVE_IS_EMPTY_IMPL(T); };
+
+
+template<class T>
+struct has_boost_move_no_copy_constructor_or_assign_type
+{
+ template <class U>
+ static yes_type test(typename U::boost_move_no_copy_constructor_or_assign*);
+
+ template <class U>
+ static no_type test(...);
+
+ static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
+};
+
+//////////////////////////////////////
+// is_copy_constructible
+//////////////////////////////////////
+#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_CXX11_DECLTYPE) \
+ && !defined(BOOST_INTEL_CXX_VERSION) && \
+ !(defined(BOOST_MSVC) && _MSC_VER == 1800)
+#define BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE
+#endif
+
+template<class T>
+struct is_copy_constructible
+{
+ // Intel compiler has problems with SFINAE for copy constructors and deleted functions:
+ //
+ // error: function *function_name* cannot be referenced -- it is a deleted function
+ // static yes_type test(U&, decltype(U(boost::declval<U&>()))* = 0);
+ // ^
+ // MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See:
+ // https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken
+ #if defined(BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE)
+ template<class U> static typename add_reference<U>::type source();
+ static no_type test(...);
+ #ifdef BOOST_NO_CXX11_DECLTYPE
+ template <class U>
+ static yes_type test(U&, bool_<sizeof(U(source<U>()))>* = 0);
+ #else
+ template <class U>
+ static yes_type test(U&, decltype(U(source<U>()))* = 0);
+ #endif
+ static const bool value = sizeof(test(source<T>())) == sizeof(yes_type);
+ #else
+ static const bool value = !has_boost_move_no_copy_constructor_or_assign_type<T>::value;
+ #endif
+};
+
+
+//////////////////////////////////////
+// is_copy_assignable
+//////////////////////////////////////
+#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_CXX11_DECLTYPE) \
+ && !defined(BOOST_INTEL_CXX_VERSION) && \
+ !(defined(BOOST_MSVC) && _MSC_VER == 1800)
+#define BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE
+#endif
+
+template <class T>
+struct is_copy_assignable
+{
+// Intel compiler has problems with SFINAE for copy constructors and deleted functions:
+//
+// error: function *function_name* cannot be referenced -- it is a deleted function
+// static boost::type_traits::yes_type test(T1&, decltype(T1(boost::declval<T1&>()))* = 0);
+// ^
+//
+// MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See:
+// https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken
+#if defined(BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE)
+ typedef char yes_type;
+ struct no_type { char dummy[2]; };
+
+ template <class U> static typename add_reference<U>::type source();
+ template <class U> static decltype(source<U&>() = source<const U&>(), yes_type() ) test(int);
+ template <class> static no_type test(...);
+
+ static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
+#else
+ static const bool value = !has_boost_move_no_copy_constructor_or_assign_type<T>::value;
+#endif
+};
+
+//////////////////////////////////////
+// is_trivially_destructible
+//////////////////////////////////////
+template<class T>
+struct is_trivially_destructible
+{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_trivially_default_constructible
+//////////////////////////////////////
+template<class T>
+struct is_trivially_default_constructible
+{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_trivially_copy_constructible
+//////////////////////////////////////
+template<class T>
+struct is_trivially_copy_constructible
+{
+ //In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
+ //deleted copy constructors so make sure the type is copy constructible.
+ static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T);
+};
+
+//////////////////////////////////////
+// is_trivially_move_constructible
+//////////////////////////////////////
+template<class T>
+struct is_trivially_move_constructible
+{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_trivially_copy_assignable
+//////////////////////////////////////
+template<class T>
+struct is_trivially_copy_assignable
+{
+ //In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
+ //deleted copy constructors so make sure the type is copy constructible.
+ static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T);
+};
+
+//////////////////////////////////////
+// is_trivially_move_assignable
+//////////////////////////////////////
+template<class T>
+struct is_trivially_move_assignable
+{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_default_constructible
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_default_constructible
+ : is_pod<T>
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_copy_constructible
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_copy_constructible
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_move_constructible
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_move_constructible
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_copy_assignable
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_copy_assignable
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_move_assignable
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_move_assignable
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_swappable
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_swappable
+{
+ static const bool value = is_empty<T>::value || is_pod<T>::value;
+};
+
+//////////////////////////////////////
+// alignment_of
+//////////////////////////////////////
+template <typename T>
+struct alignment_of_hack
+{
+ T t1;
+ char c;
+ T t2;
+ alignment_of_hack();
+};
+
+template <unsigned A, unsigned S>
+struct alignment_logic
+{ static const std::size_t value = A < S ? A : S; };
+
+template< typename T >
+struct alignment_of_impl
+#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400)
+ // With MSVC both the native __alignof operator
+ // and our own logic gets things wrong from time to time :-(
+ // Using a combination of the two seems to make the most of a bad job:
+ : alignment_logic< sizeof(alignment_of_hack<T>) - 2*sizeof(T), __alignof(T)>
+{};
+#elif !defined(BOOST_MOVE_ALIGNMENT_OF)
+ : alignment_logic< sizeof(alignment_of_hack<T>) - 2*sizeof(T), sizeof(T)>
+{};
+#else
+{ static const std::size_t value = BOOST_MOVE_ALIGNMENT_OF(T); };
+#endif
+
+template< typename T >
+struct alignment_of
+ : alignment_of_impl<T>
+{};
+
+class alignment_dummy;
+typedef void (*function_ptr)();
+typedef int (alignment_dummy::*member_ptr);
+typedef int (alignment_dummy::*member_function_ptr)();
+struct alignment_struct
+{ long double dummy[4]; };
+
+/////////////////////////////
+// max_align_t
+/////////////////////////////
+//This is not standard, but should work with all compilers
+union max_align
+{
+ char char_;
+ short short_;
+ int int_;
+ long long_;
+ #ifdef BOOST_HAS_LONG_LONG
+ ::boost::long_long_type long_long_;
+ #endif
+ float float_;
+ double double_;
+ void * void_ptr_;
+ long double long_double_[4];
+ alignment_dummy *unknown_class_ptr_;
+ function_ptr function_ptr_;
+ member_function_ptr member_function_ptr_;
+ alignment_struct alignment_struct_;
+};
+
+typedef union max_align max_align_t;
+
+/////////////////////////////
+// aligned_storage
+/////////////////////////////
+
+#if !defined(BOOST_NO_ALIGNMENT)
+
+template<std::size_t Len, std::size_t Align>
+struct aligned_struct;
+
+#define BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(A)\
+template<std::size_t Len>\
+struct BOOST_ALIGNMENT(A) aligned_struct<Len, A>\
+{\
+ char data[Len];\
+};\
+//
+
+//Up to 4K alignment (typical page size)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x2)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x4)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x8)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x10)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x20)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x40)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x80)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x100)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x200)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x400)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x800)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1000)
+
+#undef BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT
+
+// Workaround for bogus [-Wignored-attributes] warning on GCC 6.x/7.x: don't use a type that "directly" carries the alignment attribute.
+// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82270
+template<std::size_t Len, std::size_t Align>
+union aligned_struct_wrapper
+{
+ aligned_struct<Len, Align> aligner;
+ char data[sizeof(aligned_struct<Len, Align>)];
+};
+
+template<std::size_t Len, std::size_t Align>
+struct aligned_storage_impl
+{
+ typedef aligned_struct_wrapper<Len, Align> type;
+};
+
+#else //BOOST_NO_ALIGNMENT
+
+template<class T, std::size_t Len>
+union aligned_union
+{
+ T aligner;
+ char data[Len];
+};
+
+template<std::size_t Len, std::size_t Align, class T, bool Ok>
+struct aligned_next;
+
+template<std::size_t Len, std::size_t Align, class T>
+struct aligned_next<Len, Align, T, true>
+{
+ BOOST_STATIC_ASSERT((alignment_of<T>::value == Align));
+ typedef aligned_union<T, Len> type;
+};
+
+//End of search defaults to max_align_t
+template<std::size_t Len, std::size_t Align>
+struct aligned_next<Len, Align, max_align_t, false>
+{ typedef aligned_union<max_align_t, Len> type; };
+
+//Now define a search list through types
+#define BOOST_MOVE_ALIGNED_NEXT_STEP(TYPE, NEXT_TYPE)\
+ template<std::size_t Len, std::size_t Align>\
+ struct aligned_next<Len, Align, TYPE, false>\
+ : aligned_next<Len, Align, NEXT_TYPE, Align == alignment_of<NEXT_TYPE>::value>\
+ {};\
+ //
+ BOOST_MOVE_ALIGNED_NEXT_STEP(long double, max_align_t)
+ BOOST_MOVE_ALIGNED_NEXT_STEP(double, long double)
+ #ifdef BOOST_HAS_LONG_LONG
+ BOOST_MOVE_ALIGNED_NEXT_STEP(::boost::long_long_type, double)
+ BOOST_MOVE_ALIGNED_NEXT_STEP(long, ::boost::long_long_type)
+ #else
+ BOOST_MOVE_ALIGNED_NEXT_STEP(long, double)
+ #endif
+ BOOST_MOVE_ALIGNED_NEXT_STEP(int, long)
+ BOOST_MOVE_ALIGNED_NEXT_STEP(short, int)
+ BOOST_MOVE_ALIGNED_NEXT_STEP(char, short)
+#undef BOOST_MOVE_ALIGNED_NEXT_STEP
+
+template<std::size_t Len, std::size_t Align>
+struct aligned_storage_impl
+ : aligned_next<Len, Align, char, Align == alignment_of<char>::value>
+{};
+
+#endif
+
+template<std::size_t Len, std::size_t Align = alignment_of<max_align_t>::value>
+struct aligned_storage
+{
+ //Sanity checks for input parameters
+ BOOST_STATIC_ASSERT(Align > 0);
+
+ //Sanity checks for output type
+ typedef typename aligned_storage_impl<Len ? Len : 1, Align>::type type;
+ static const std::size_t value = alignment_of<type>::value;
+ BOOST_STATIC_ASSERT(value >= Align);
+ BOOST_STATIC_ASSERT((value % Align) == 0);
+
+ //Just in case someone instantiates aligned_storage
+ //instead of aligned_storage::type (typical error).
+ private:
+ aligned_storage();
+};
+
+} //namespace move_detail {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP
diff --git a/include/boost/move/detail/unique_ptr_meta_utils.hpp b/include/boost/move/detail/unique_ptr_meta_utils.hpp
new file mode 100644
index 0000000..e11124d
--- /dev/null
+++ b/include/boost/move/detail/unique_ptr_meta_utils.hpp
@@ -0,0 +1,591 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP
+#define BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <cstddef> //for std::size_t
+
+//Small meta-typetraits to support move
+
+namespace boost {
+
+namespace movelib {
+
+template <class T>
+struct default_delete;
+
+} //namespace movelib {
+
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+//Forward declare boost::rv
+template <class T> class rv;
+#endif
+
+namespace move_upmu {
+
+//////////////////////////////////////
+// nat
+//////////////////////////////////////
+struct nat{};
+
+//////////////////////////////////////
+// natify
+//////////////////////////////////////
+template <class T> struct natify{};
+
+//////////////////////////////////////
+// if_c
+//////////////////////////////////////
+template<bool C, typename T1, typename T2>
+struct if_c
+{
+ typedef T1 type;
+};
+
+template<typename T1, typename T2>
+struct if_c<false,T1,T2>
+{
+ typedef T2 type;
+};
+
+//////////////////////////////////////
+// if_
+//////////////////////////////////////
+template<typename T1, typename T2, typename T3>
+struct if_ : if_c<0 != T1::value, T2, T3>
+{};
+
+//enable_if_
+template <bool B, class T = nat>
+struct enable_if_c
+{
+ typedef T type;
+};
+
+//////////////////////////////////////
+// enable_if_c
+//////////////////////////////////////
+template <class T>
+struct enable_if_c<false, T> {};
+
+//////////////////////////////////////
+// enable_if
+//////////////////////////////////////
+template <class Cond, class T = nat>
+struct enable_if : public enable_if_c<Cond::value, T> {};
+
+//////////////////////////////////////
+// remove_reference
+//////////////////////////////////////
+template<class T>
+struct remove_reference
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference<T&>
+{
+ typedef T type;
+};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template<class T>
+struct remove_reference<T&&>
+{
+ typedef T type;
+};
+
+#else
+
+template<class T>
+struct remove_reference< rv<T> >
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference< rv<T> &>
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference< const rv<T> &>
+{
+ typedef T type;
+};
+
+
+#endif
+
+//////////////////////////////////////
+// remove_const
+//////////////////////////////////////
+template< class T >
+struct remove_const
+{
+ typedef T type;
+};
+
+template< class T >
+struct remove_const<const T>
+{
+ typedef T type;
+};
+
+//////////////////////////////////////
+// remove_volatile
+//////////////////////////////////////
+template< class T >
+struct remove_volatile
+{
+ typedef T type;
+};
+
+template< class T >
+struct remove_volatile<volatile T>
+{
+ typedef T type;
+};
+
+//////////////////////////////////////
+// remove_cv
+//////////////////////////////////////
+template< class T >
+struct remove_cv
+{
+ typedef typename remove_volatile
+ <typename remove_const<T>::type>::type type;
+};
+
+//////////////////////////////////////
+// remove_extent
+//////////////////////////////////////
+template<class T>
+struct remove_extent
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_extent<T[]>
+{
+ typedef T type;
+};
+
+template<class T, std::size_t N>
+struct remove_extent<T[N]>
+{
+ typedef T type;
+};
+
+//////////////////////////////////////
+// extent
+//////////////////////////////////////
+
+template<class T, unsigned N = 0>
+struct extent
+{
+ static const std::size_t value = 0;
+};
+
+template<class T>
+struct extent<T[], 0>
+{
+ static const std::size_t value = 0;
+};
+
+template<class T, unsigned N>
+struct extent<T[], N>
+{
+ static const std::size_t value = extent<T, N-1>::value;
+};
+
+template<class T, std::size_t N>
+struct extent<T[N], 0>
+{
+ static const std::size_t value = N;
+};
+
+template<class T, std::size_t I, unsigned N>
+struct extent<T[I], N>
+{
+ static const std::size_t value = extent<T, N-1>::value;
+};
+
+//////////////////////////////////////
+// add_lvalue_reference
+//////////////////////////////////////
+template<class T>
+struct add_lvalue_reference
+{
+ typedef T& type;
+};
+
+template<class T>
+struct add_lvalue_reference<T&>
+{
+ typedef T& type;
+};
+
+template<>
+struct add_lvalue_reference<void>
+{
+ typedef void type;
+};
+
+template<>
+struct add_lvalue_reference<const void>
+{
+ typedef const void type;
+};
+
+template<>
+struct add_lvalue_reference<volatile void>
+{
+ typedef volatile void type;
+};
+
+template<>
+struct add_lvalue_reference<const volatile void>
+{
+ typedef const volatile void type;
+};
+
+template<class T>
+struct add_const_lvalue_reference
+{
+ typedef typename remove_reference<T>::type t_unreferenced;
+ typedef const t_unreferenced t_unreferenced_const;
+ typedef typename add_lvalue_reference
+ <t_unreferenced_const>::type type;
+};
+
+//////////////////////////////////////
+// is_same
+//////////////////////////////////////
+template<class T, class U>
+struct is_same
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_same<T, T>
+{
+ static const bool value = true;
+};
+
+//////////////////////////////////////
+// is_pointer
+//////////////////////////////////////
+template< class T >
+struct is_pointer
+{
+ static const bool value = false;
+};
+
+template< class T >
+struct is_pointer<T*>
+{
+ static const bool value = true;
+};
+
+//////////////////////////////////////
+// is_reference
+//////////////////////////////////////
+template< class T >
+struct is_reference
+{
+ static const bool value = false;
+};
+
+template< class T >
+struct is_reference<T&>
+{
+ static const bool value = true;
+};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template< class T >
+struct is_reference<T&&>
+{
+ static const bool value = true;
+};
+
+#endif
+
+//////////////////////////////////////
+// is_lvalue_reference
+//////////////////////////////////////
+template<class T>
+struct is_lvalue_reference
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_lvalue_reference<T&>
+{
+ static const bool value = true;
+};
+
+//////////////////////////////////////
+// is_array
+//////////////////////////////////////
+template<class T>
+struct is_array
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_array<T[]>
+{
+ static const bool value = true;
+};
+
+template<class T, std::size_t N>
+struct is_array<T[N]>
+{
+ static const bool value = true;
+};
+
+//////////////////////////////////////
+// has_pointer_type
+//////////////////////////////////////
+template <class T>
+struct has_pointer_type
+{
+ struct two { char c[2]; };
+ template <class U> static two test(...);
+ template <class U> static char test(typename U::pointer* = 0);
+ static const bool value = sizeof(test<T>(0)) == 1;
+};
+
+//////////////////////////////////////
+// pointer_type
+//////////////////////////////////////
+template <class T, class D, bool = has_pointer_type<D>::value>
+struct pointer_type_imp
+{
+ typedef typename D::pointer type;
+};
+
+template <class T, class D>
+struct pointer_type_imp<T, D, false>
+{
+ typedef T* type;
+};
+
+template <class T, class D>
+struct pointer_type
+{
+ typedef typename pointer_type_imp
+ <typename remove_extent<T>::type, typename remove_reference<D>::type>::type type;
+};
+
+//////////////////////////////////////
+// is_convertible
+//////////////////////////////////////
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+
+//use intrinsic since in MSVC
+//overaligned types can't go through ellipsis
+template <class T, class U>
+struct is_convertible
+{
+ static const bool value = __is_convertible_to(T, U);
+};
+
+#else
+
+template <class T, class U>
+class is_convertible
+{
+ typedef typename add_lvalue_reference<T>::type t_reference;
+ typedef char true_t;
+ class false_t { char dummy[2]; };
+ static false_t dispatch(...);
+ static true_t dispatch(U);
+ static t_reference trigger();
+ public:
+ static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
+};
+
+#endif
+
+//////////////////////////////////////
+// is_unary_function
+//////////////////////////////////////
+#if defined(BOOST_MSVC) || defined(__BORLANDC_)
+#define BOOST_MOVE_TT_DECL __cdecl
+#else
+#define BOOST_MOVE_TT_DECL
+#endif
+
+#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(_M_ARM64) && !defined(UNDER_CE)
+#define BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS
+#endif
+
+template <typename T>
+struct is_unary_function_impl
+{ static const bool value = false; };
+
+// avoid duplicate definitions of is_unary_function_impl
+#ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS
+
+template <typename R>
+struct is_unary_function_impl<R (*)()>
+{ static const bool value = true; };
+
+template <typename R>
+struct is_unary_function_impl<R (*)(...)>
+{ static const bool value = true; };
+
+#else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS
+
+template <typename R>
+struct is_unary_function_impl<R (__stdcall*)()>
+{ static const bool value = true; };
+
+#ifndef _MANAGED
+
+template <typename R>
+struct is_unary_function_impl<R (__fastcall*)()>
+{ static const bool value = true; };
+
+#endif
+
+template <typename R>
+struct is_unary_function_impl<R (__cdecl*)()>
+{ static const bool value = true; };
+
+template <typename R>
+struct is_unary_function_impl<R (__cdecl*)(...)>
+{ static const bool value = true; };
+
+#endif
+
+// avoid duplicate definitions of is_unary_function_impl
+#ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS
+
+template <typename R, class T0>
+struct is_unary_function_impl<R (*)(T0)>
+{ static const bool value = true; };
+
+template <typename R, class T0>
+struct is_unary_function_impl<R (*)(T0...)>
+{ static const bool value = true; };
+
+#else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS
+
+template <typename R, class T0>
+struct is_unary_function_impl<R (__stdcall*)(T0)>
+{ static const bool value = true; };
+
+#ifndef _MANAGED
+
+template <typename R, class T0>
+struct is_unary_function_impl<R (__fastcall*)(T0)>
+{ static const bool value = true; };
+
+#endif
+
+template <typename R, class T0>
+struct is_unary_function_impl<R (__cdecl*)(T0)>
+{ static const bool value = true; };
+
+template <typename R, class T0>
+struct is_unary_function_impl<R (__cdecl*)(T0...)>
+{ static const bool value = true; };
+
+#endif
+
+template <typename T>
+struct is_unary_function_impl<T&>
+{ static const bool value = false; };
+
+template<typename T>
+struct is_unary_function
+{ static const bool value = is_unary_function_impl<T>::value; };
+
+//////////////////////////////////////
+// has_virtual_destructor
+//////////////////////////////////////
+#if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\
+ || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500))
+# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+#elif defined(BOOST_CLANG) && defined(__has_feature)
+# if __has_feature(has_virtual_destructor)
+# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+# endif
+#elif defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG)
+# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600)
+# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+#elif defined(__CODEGEARC__)
+# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+#endif
+
+#ifdef BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR
+ template<class T>
+ struct has_virtual_destructor{ static const bool value = BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T); };
+#else
+ //If no intrinsic is available you trust the programmer knows what is doing
+ template<class T>
+ struct has_virtual_destructor{ static const bool value = true; };
+#endif
+
+//////////////////////////////////////
+// missing_virtual_destructor
+//////////////////////////////////////
+
+template< class T, class U
+ , bool enable = is_convertible< U*, T*>::value &&
+ !is_array<T>::value &&
+ !is_same<typename remove_cv<T>::type, void>::value &&
+ !is_same<typename remove_cv<U>::type, typename remove_cv<T>::type>::value
+ >
+struct missing_virtual_destructor_default_delete
+{ static const bool value = !has_virtual_destructor<T>::value; };
+
+template<class T, class U>
+struct missing_virtual_destructor_default_delete<T, U, false>
+{ static const bool value = false; };
+
+template<class Deleter, class U>
+struct missing_virtual_destructor
+{ static const bool value = false; };
+
+template<class T, class U>
+struct missing_virtual_destructor< ::boost::movelib::default_delete<T>, U >
+ : missing_virtual_destructor_default_delete<T, U>
+{};
+
+} //namespace move_upmu {
+} //namespace boost {
+
+#endif //#ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP
diff --git a/include/boost/move/detail/workaround.hpp b/include/boost/move/detail/workaround.hpp
new file mode 100644
index 0000000..1d16f24
--- /dev/null
+++ b/include/boost/move/detail/workaround.hpp
@@ -0,0 +1,69 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
+#define BOOST_MOVE_DETAIL_WORKAROUND_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ #define BOOST_MOVE_PERFECT_FORWARDING
+#endif
+
+#if defined(__has_feature)
+ #define BOOST_MOVE_HAS_FEATURE __has_feature
+#else
+ #define BOOST_MOVE_HAS_FEATURE(x) 0
+#endif
+
+#if BOOST_MOVE_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+ #define BOOST_MOVE_ADDRESS_SANITIZER_ON
+#endif
+
+//Macros for documentation purposes. For code, expands to the argument
+#define BOOST_MOVE_IMPDEF(TYPE) TYPE
+#define BOOST_MOVE_SEEDOC(TYPE) TYPE
+#define BOOST_MOVE_DOC0PTR(TYPE) TYPE
+#define BOOST_MOVE_DOC1ST(TYPE1, TYPE2) TYPE2
+#define BOOST_MOVE_I ,
+#define BOOST_MOVE_DOCIGN(T1) T1
+
+#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) && !defined(__clang__)
+ //Pre-standard rvalue binding rules
+ #define BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+#elif defined(_MSC_VER) && (_MSC_VER == 1600)
+ //Standard rvalue binding rules but with some bugs
+ #define BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
+ #define BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG
+#elif defined(_MSC_VER) && (_MSC_VER == 1700)
+ #define BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG
+#endif
+
+#if defined(BOOST_MOVE_DISABLE_FORCEINLINE)
+ #define BOOST_MOVE_FORCEINLINE inline
+#elif defined(BOOST_MOVE_FORCEINLINE_IS_BOOST_FORCELINE)
+ #define BOOST_MOVE_FORCEINLINE BOOST_FORCEINLINE
+#elif defined(BOOST_MSVC) && defined(_DEBUG)
+ //"__forceinline" and MSVC seems to have some bugs in debug mode
+ #define BOOST_MOVE_FORCEINLINE inline
+#elif defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ < 5)))
+ //Older GCCs have problems with forceinline
+ #define BOOST_MOVE_FORCEINLINE inline
+#else
+ #define BOOST_MOVE_FORCEINLINE BOOST_FORCEINLINE
+#endif
+
+#endif //#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
diff --git a/include/boost/move/iterator.hpp b/include/boost/move/iterator.hpp
new file mode 100644
index 0000000..f36df23
--- /dev/null
+++ b/include/boost/move/iterator.hpp
@@ -0,0 +1,311 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_ITERATOR_HPP
+#define BOOST_MOVE_ITERATOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/utility_core.hpp>
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! Class template move_iterator is an iterator adaptor with the same behavior
+//! as the underlying iterator except that its dereference operator implicitly
+//! converts the value returned by the underlying iterator's dereference operator
+//! to an rvalue reference. Some generic algorithms can be called with move
+//! iterators to replace copying with moving.
+template <class It>
+class move_iterator
+{
+ public:
+ typedef It iterator_type;
+ typedef typename boost::movelib::iterator_traits<iterator_type>::value_type value_type;
+ #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ typedef value_type && reference;
+ #else
+ typedef typename ::boost::move_detail::if_
+ < ::boost::has_move_emulation_enabled<value_type>
+ , ::boost::rv<value_type>&
+ , value_type & >::type reference;
+ #endif
+ typedef It pointer;
+ typedef typename boost::movelib::iterator_traits<iterator_type>::difference_type difference_type;
+ typedef typename boost::movelib::iterator_traits<iterator_type>::iterator_category iterator_category;
+
+ BOOST_MOVE_FORCEINLINE move_iterator()
+ : m_it()
+ {}
+
+ BOOST_MOVE_FORCEINLINE explicit move_iterator(const It &i)
+ : m_it(i)
+ {}
+
+ template <class U>
+ BOOST_MOVE_FORCEINLINE move_iterator(const move_iterator<U>& u)
+ : m_it(u.m_it)
+ {}
+
+ BOOST_MOVE_FORCEINLINE reference operator*() const
+ {
+ #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+ return *m_it;
+ #else
+ return ::boost::move(*m_it);
+ #endif
+ }
+
+ BOOST_MOVE_FORCEINLINE pointer operator->() const
+ { return m_it; }
+
+ BOOST_MOVE_FORCEINLINE move_iterator& operator++()
+ { ++m_it; return *this; }
+
+ BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator++(int)
+ { move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; }
+
+ BOOST_MOVE_FORCEINLINE move_iterator& operator--()
+ { --m_it; return *this; }
+
+ BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator--(int)
+ { move_iterator<iterator_type> tmp(*this); --(*this); return tmp; }
+
+ move_iterator<iterator_type> operator+ (difference_type n) const
+ { return move_iterator<iterator_type>(m_it + n); }
+
+ BOOST_MOVE_FORCEINLINE move_iterator& operator+=(difference_type n)
+ { m_it += n; return *this; }
+
+ BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator- (difference_type n) const
+ { return move_iterator<iterator_type>(m_it - n); }
+
+ BOOST_MOVE_FORCEINLINE move_iterator& operator-=(difference_type n)
+ { m_it -= n; return *this; }
+
+ BOOST_MOVE_FORCEINLINE reference operator[](difference_type n) const
+ {
+ #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+ return m_it[n];
+ #else
+ return ::boost::move(m_it[n]);
+ #endif
+ }
+
+ BOOST_MOVE_FORCEINLINE friend bool operator==(const move_iterator& x, const move_iterator& y)
+ { return x.m_it == y.m_it; }
+
+ BOOST_MOVE_FORCEINLINE friend bool operator!=(const move_iterator& x, const move_iterator& y)
+ { return x.m_it != y.m_it; }
+
+ BOOST_MOVE_FORCEINLINE friend bool operator< (const move_iterator& x, const move_iterator& y)
+ { return x.m_it < y.m_it; }
+
+ BOOST_MOVE_FORCEINLINE friend bool operator<=(const move_iterator& x, const move_iterator& y)
+ { return x.m_it <= y.m_it; }
+
+ BOOST_MOVE_FORCEINLINE friend bool operator> (const move_iterator& x, const move_iterator& y)
+ { return x.m_it > y.m_it; }
+
+ BOOST_MOVE_FORCEINLINE friend bool operator>=(const move_iterator& x, const move_iterator& y)
+ { return x.m_it >= y.m_it; }
+
+ BOOST_MOVE_FORCEINLINE friend difference_type operator-(const move_iterator& x, const move_iterator& y)
+ { return x.m_it - y.m_it; }
+
+ BOOST_MOVE_FORCEINLINE friend move_iterator operator+(difference_type n, const move_iterator& x)
+ { return move_iterator(x.m_it + n); }
+
+ private:
+ It m_it;
+};
+
+//is_move_iterator
+namespace move_detail {
+
+template <class I>
+struct is_move_iterator
+{
+ static const bool value = false;
+};
+
+template <class I>
+struct is_move_iterator< ::boost::move_iterator<I> >
+{
+ static const bool value = true;
+};
+
+} //namespace move_detail {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//!
+//! <b>Returns</b>: move_iterator<It>(i).
+template<class It>
+inline move_iterator<It> make_move_iterator(const It &it)
+{ return move_iterator<It>(it); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// back_move_insert_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+//! A move insert iterator that move constructs elements at the
+//! back of a container
+template <typename C> // C models Container
+class back_move_insert_iterator
+{
+ C* container_m;
+
+ public:
+ typedef C container_type;
+ typedef typename C::value_type value_type;
+ typedef typename C::reference reference;
+ typedef typename C::pointer pointer;
+ typedef typename C::difference_type difference_type;
+ typedef std::output_iterator_tag iterator_category;
+
+ explicit back_move_insert_iterator(C& x) : container_m(&x) { }
+
+ back_move_insert_iterator& operator=(reference x)
+ { container_m->push_back(boost::move(x)); return *this; }
+
+ back_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x)
+ { reference rx = x; return this->operator=(rx); }
+
+ back_move_insert_iterator& operator*() { return *this; }
+ back_move_insert_iterator& operator++() { return *this; }
+ back_move_insert_iterator& operator++(int) { return *this; }
+};
+
+//!
+//! <b>Returns</b>: back_move_insert_iterator<C>(x).
+template <typename C> // C models Container
+inline back_move_insert_iterator<C> back_move_inserter(C& x)
+{
+ return back_move_insert_iterator<C>(x);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// front_move_insert_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! A move insert iterator that move constructs elements int the
+//! front of a container
+template <typename C> // C models Container
+class front_move_insert_iterator
+{
+ C* container_m;
+
+public:
+ typedef C container_type;
+ typedef typename C::value_type value_type;
+ typedef typename C::reference reference;
+ typedef typename C::pointer pointer;
+ typedef typename C::difference_type difference_type;
+ typedef std::output_iterator_tag iterator_category;
+
+ explicit front_move_insert_iterator(C& x) : container_m(&x) { }
+
+ front_move_insert_iterator& operator=(reference x)
+ { container_m->push_front(boost::move(x)); return *this; }
+
+ front_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x)
+ { reference rx = x; return this->operator=(rx); }
+
+ front_move_insert_iterator& operator*() { return *this; }
+ front_move_insert_iterator& operator++() { return *this; }
+ front_move_insert_iterator& operator++(int) { return *this; }
+};
+
+//!
+//! <b>Returns</b>: front_move_insert_iterator<C>(x).
+template <typename C> // C models Container
+inline front_move_insert_iterator<C> front_move_inserter(C& x)
+{
+ return front_move_insert_iterator<C>(x);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// insert_move_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+template <typename C> // C models Container
+class move_insert_iterator
+{
+ C* container_m;
+ typename C::iterator pos_;
+
+ public:
+ typedef C container_type;
+ typedef typename C::value_type value_type;
+ typedef typename C::reference reference;
+ typedef typename C::pointer pointer;
+ typedef typename C::difference_type difference_type;
+ typedef std::output_iterator_tag iterator_category;
+
+ explicit move_insert_iterator(C& x, typename C::iterator pos)
+ : container_m(&x), pos_(pos)
+ {}
+
+ move_insert_iterator& operator=(reference x)
+ {
+ pos_ = container_m->insert(pos_, ::boost::move(x));
+ ++pos_;
+ return *this;
+ }
+
+ move_insert_iterator& operator=(BOOST_RV_REF(value_type) x)
+ { reference rx = x; return this->operator=(rx); }
+
+ move_insert_iterator& operator*() { return *this; }
+ move_insert_iterator& operator++() { return *this; }
+ move_insert_iterator& operator++(int) { return *this; }
+};
+
+//!
+//! <b>Returns</b>: move_insert_iterator<C>(x, it).
+template <typename C> // C models Container
+inline move_insert_iterator<C> move_inserter(C& x, typename C::iterator it)
+{
+ return move_insert_iterator<C>(x, it);
+}
+
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_ITERATOR_HPP
diff --git a/include/boost/move/make_unique.hpp b/include/boost/move/make_unique.hpp
new file mode 100644
index 0000000..ef106db
--- /dev/null
+++ b/include/boost/move/make_unique.hpp
@@ -0,0 +1,238 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006-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_MAKE_UNIQUE_HPP_INCLUDED
+#define BOOST_MOVE_MAKE_UNIQUE_HPP_INCLUDED
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <cstddef> //for std::size_t
+#include <boost/move/detail/unique_ptr_meta_utils.hpp>
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+# include <boost/move/detail/fwd_macros.hpp>
+#endif
+
+//!\file
+//! Defines "make_unique" functions, which are factories to create instances
+//! of unique_ptr depending on the passed arguments.
+//!
+//! This header can be a bit heavyweight in C++03 compilers due to the use of the
+//! preprocessor library, that's why it's a a separate header from <tt>unique_ptr.hpp</tt>
+
+#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+namespace std { //no namespace versioning in clang+libc++
+
+struct nothrow_t;
+
+} //namespace std {
+
+namespace boost{
+namespace move_upmu {
+
+//Compile time switch between
+//single element, unknown bound array
+//and known bound array
+template<class T>
+struct unique_ptr_if
+{
+ typedef ::boost::movelib::unique_ptr<T> t_is_not_array;
+};
+
+template<class T>
+struct unique_ptr_if<T[]>
+{
+ typedef ::boost::movelib::unique_ptr<T[]> t_is_array_of_unknown_bound;
+};
+
+template<class T, std::size_t N>
+struct unique_ptr_if<T[N]>
+{
+ typedef void t_is_array_of_known_bound;
+};
+
+template <int Dummy = 0>
+struct nothrow_holder
+{
+ static std::nothrow_t *pnothrow;
+};
+
+template <int Dummy>
+std::nothrow_t *nothrow_holder<Dummy>::pnothrow =
+ reinterpret_cast<std::nothrow_t *>(0x1234); //Avoid reference to null errors in sanitizers
+
+} //namespace move_upmu {
+} //namespace boost{
+
+#endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+namespace boost{
+namespace movelib {
+
+#if defined(BOOST_MOVE_DOXYGEN_INVOKED) || !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array.
+//!
+//! <b>Returns</b>: <tt>unique_ptr<T>(new T(std::forward<Args>(args)...))</tt>.
+template<class T, class... Args>
+inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)
+ make_unique(BOOST_FWD_REF(Args)... args)
+{ return unique_ptr<T>(new T(::boost::forward<Args>(args)...)); }
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array.
+//!
+//! <b>Returns</b>: <tt>unique_ptr<T>(new T(std::nothrow)(std::forward<Args>(args)...))</tt>.
+template<class T, class... Args>
+inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)
+ make_unique_nothrow(BOOST_FWD_REF(Args)... args)
+{ return unique_ptr<T>(new (*boost::move_upmu::nothrow_holder<>::pnothrow)T(::boost::forward<Args>(args)...)); }
+
+#else
+ #define BOOST_MOVE_MAKE_UNIQUE_CODE(N)\
+ template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array\
+ make_unique( BOOST_MOVE_UREF##N)\
+ { return unique_ptr<T>( new T( BOOST_MOVE_FWD##N ) ); }\
+ \
+ template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array\
+ make_unique_nothrow( BOOST_MOVE_UREF##N)\
+ { return unique_ptr<T>( new (*boost::move_upmu::nothrow_holder<>::pnothrow)T ( BOOST_MOVE_FWD##N ) ); }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_MOVE_MAKE_UNIQUE_CODE)
+ #undef BOOST_MOVE_MAKE_UNIQUE_CODE
+
+#endif
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array.
+//!
+//! <b>Returns</b>: <tt>unique_ptr<T>(new T)</tt> (default initialization)
+template<class T>
+inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)
+ make_unique_definit()
+{
+ return unique_ptr<T>(new T);
+}
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array.
+//!
+//! <b>Returns</b>: <tt>unique_ptr<T>(new T(std::nothrow)</tt> (default initialization)
+template<class T>
+inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)
+ make_unique_nothrow_definit()
+{
+ return unique_ptr<T>(new (*boost::move_upmu::nothrow_holder<>::pnothrow)T);
+}
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of
+//! unknown bound.
+//!
+//! <b>Returns</b>: <tt>unique_ptr<T>(new remove_extent_t<T>[n]())</tt> (value initialization)
+template<class T>
+inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)
+ make_unique(std::size_t n)
+{
+ typedef typename ::boost::move_upmu::remove_extent<T>::type U;
+ return unique_ptr<T>(new U[n]());
+}
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of
+//! unknown bound.
+//!
+//! <b>Returns</b>: <tt>unique_ptr<T>(new (std::nothrow)remove_extent_t<T>[n]())</tt> (value initialization)
+template<class T>
+inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)
+ make_unique_nothrow(std::size_t n)
+{
+ typedef typename ::boost::move_upmu::remove_extent<T>::type U;
+ return unique_ptr<T>(new (*boost::move_upmu::nothrow_holder<>::pnothrow)U[n]());
+}
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of
+//! unknown bound.
+//!
+//! <b>Returns</b>: <tt>unique_ptr<T>(new remove_extent_t<T>[n])</tt> (default initialization)
+template<class T>
+inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)
+ make_unique_definit(std::size_t n)
+{
+ typedef typename ::boost::move_upmu::remove_extent<T>::type U;
+ return unique_ptr<T>(new U[n]);
+}
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of
+//! unknown bound.
+//!
+//! <b>Returns</b>: <tt>unique_ptr<T>(new (std::nothrow)remove_extent_t<T>[n])</tt> (default initialization)
+template<class T>
+inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)
+ make_unique_nothrow_definit(std::size_t n)
+{
+ typedef typename ::boost::move_upmu::remove_extent<T>::type U;
+ return unique_ptr<T>(new (*boost::move_upmu::nothrow_holder<>::pnothrow) U[n]);
+}
+
+#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is
+//! an array of known bound.
+template<class T, class... Args>
+inline BOOST_MOVE_DOC1ST(unspecified,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound)
+ make_unique(BOOST_FWD_REF(Args) ...) = delete;
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is
+//! an array of known bound.
+template<class T, class... Args>
+inline BOOST_MOVE_DOC1ST(unspecified,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound)
+ make_unique_definit(BOOST_FWD_REF(Args) ...) = delete;
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is
+//! an array of known bound.
+template<class T, class... Args>
+inline BOOST_MOVE_DOC1ST(unspecified,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound)
+ make_unique_nothrow(BOOST_FWD_REF(Args) ...) = delete;
+
+//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is
+//! an array of known bound.
+template<class T, class... Args>
+inline BOOST_MOVE_DOC1ST(unspecified,
+ typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound)
+ make_unique_nothrow_definit(BOOST_FWD_REF(Args) ...) = delete;
+
+#endif
+
+} //namespace movelib {
+
+} //namespace boost{
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_MAKE_UNIQUE_HPP_INCLUDED
diff --git a/include/boost/move/move.hpp b/include/boost/move/move.hpp
new file mode 100644
index 0000000..62dddbc
--- /dev/null
+++ b/include/boost/move/move.hpp
@@ -0,0 +1,35 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright David Abrahams, Vicente Botet 2009.
+// (C) Copyright 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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+//! A general library header that includes
+//! the rest of top-level headers.
+
+#ifndef BOOST_MOVE_MOVE_HPP
+#define BOOST_MOVE_MOVE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/traits.hpp>
+#include <boost/move/algorithm.hpp>
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_MOVE_HPP
diff --git a/include/boost/move/traits.hpp b/include/boost/move/traits.hpp
new file mode 100644
index 0000000..b48b8f6
--- /dev/null
+++ b/include/boost/move/traits.hpp
@@ -0,0 +1,77 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright 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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_TRAITS_HPP
+#define BOOST_MOVE_TRAITS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#include <boost/move/core.hpp>
+#endif
+#include <boost/move/detail/meta_utils.hpp>
+#include <boost/move/detail/type_traits.hpp>
+
+namespace boost {
+
+//! If this trait yields to true
+//! (<i>has_trivial_destructor_after_move <T>::value == true</i>)
+//! means that if T is used as argument of a move construction/assignment,
+//! there is no need to call T's destructor.
+//! This optimization tipically is used to improve containers' performance.
+//!
+//! By default this trait is true if the type has trivial destructor,
+//! every class should specialize this trait if it wants to improve performance
+//! when inserted in containers.
+template <class T>
+struct has_trivial_destructor_after_move
+ : ::boost::move_detail::is_trivially_destructible<T>
+{};
+
+//! By default this traits returns
+//! <pre>boost::is_nothrow_move_constructible<T>::value && boost::is_nothrow_move_assignable<T>::value </pre>.
+//! Classes with non-throwing move constructor
+//! and assignment can specialize this trait to obtain some performance improvements.
+template <class T>
+struct has_nothrow_move
+{
+ static const bool value = boost::move_detail::is_nothrow_move_constructible<T>::value &&
+ boost::move_detail::is_nothrow_move_assignable<T>::value;
+};
+
+namespace move_detail {
+
+template <class T>
+struct is_nothrow_move_constructible_or_uncopyable
+{
+ //The standard requires is_nothrow_move_constructible for move_if_noexcept
+ //but a user (usually in C++03) might specialize has_nothrow_move which includes it
+ static const bool value = is_nothrow_move_constructible<T>::value ||
+ has_nothrow_move<T>::value ||
+ !is_copy_constructible<T>::value;
+};
+
+} //move_detail {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_TRAITS_HPP
diff --git a/include/boost/move/unique_ptr.hpp b/include/boost/move/unique_ptr.hpp
new file mode 100644
index 0000000..2d794e8
--- /dev/null
+++ b/include/boost/move/unique_ptr.hpp
@@ -0,0 +1,871 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_HPP_INCLUDED
+#define BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
+#include <boost/move/detail/unique_ptr_meta_utils.hpp>
+#include <boost/move/default_delete.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/assert.hpp>
+
+#include <cstddef> //For std::nullptr_t and std::size_t
+
+//!\file
+//! Describes the smart pointer unique_ptr, a drop-in replacement for std::unique_ptr,
+//! usable also from C++03 compilers.
+//!
+//! Main differences from std::unique_ptr to avoid heavy dependencies,
+//! specially in C++03 compilers:
+//! - <tt>operator < </tt> uses pointer <tt>operator < </tt>instead of <tt>std::less<common_type></tt>.
+//! This avoids dependencies on <tt>std::common_type</tt> and <tt>std::less</tt>
+//! (<tt><type_traits>/<functional></tt> headers). In C++03 this avoid pulling Boost.Typeof and other
+//! cascading dependencies. As in all Boost platforms <tt>operator <</tt> on raw pointers and
+//! other smart pointers provides strict weak ordering in practice this should not be a problem for users.
+//! - assignable from literal 0 for compilers without nullptr
+//! - <tt>unique_ptr<T[]></tt> is constructible and assignable from <tt>unique_ptr<U[]></tt> if
+//! cv-less T and cv-less U are the same type and T is more CV qualified than U.
+
+namespace boost{
+// @cond
+namespace move_upd {
+
+////////////////////////////////////////////
+// deleter types
+////////////////////////////////////////////
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template <class T>
+class is_noncopyable
+{
+ typedef char true_t;
+ class false_t { char dummy[2]; };
+ template<class U> static false_t dispatch(...);
+ template<class U> static true_t dispatch(typename U::boost_move_no_copy_constructor_or_assign*);
+ public:
+ static const bool value = sizeof(dispatch<T>(0)) == sizeof(true_t);
+};
+#endif //defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+template <class D>
+struct deleter_types
+{
+ typedef typename bmupmu::add_lvalue_reference<D>::type del_ref;
+ typedef typename bmupmu::add_const_lvalue_reference<D>::type del_cref;
+ #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef typename bmupmu::if_c
+ < bmupmu::is_lvalue_reference<D>::value, D, del_cref >::type deleter_arg_type1;
+ typedef typename bmupmu::remove_reference<D>::type && deleter_arg_type2;
+ #else
+ typedef typename bmupmu::if_c
+ < is_noncopyable<D>::value, bmupmu::nat, del_cref>::type non_ref_deleter_arg1;
+ typedef typename bmupmu::if_c< bmupmu::is_lvalue_reference<D>::value
+ , D, non_ref_deleter_arg1 >::type deleter_arg_type1;
+ typedef ::boost::rv<D> & deleter_arg_type2;
+ #endif
+};
+
+////////////////////////////////////////////
+// unique_ptr_data
+////////////////////////////////////////////
+template <class P, class D, bool = bmupmu::is_unary_function<D>::value || bmupmu::is_reference<D>::value >
+struct unique_ptr_data
+{
+ typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
+ typedef typename deleter_types<D>::del_ref del_ref;
+ typedef typename deleter_types<D>::del_cref del_cref;
+
+ BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
+ : m_p(), d()
+ {}
+
+ BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
+ : m_p(p), d()
+ {}
+
+ BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
+ : m_p(p), d(d1)
+ {}
+
+ template <class U>
+ BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d1) BOOST_NOEXCEPT
+ : m_p(p), d(::boost::forward<U>(d1))
+ {}
+
+ BOOST_MOVE_FORCEINLINE del_ref deleter() { return d; }
+ BOOST_MOVE_FORCEINLINE del_cref deleter() const{ return d; }
+
+ P m_p;
+ D d;
+
+ private:
+ unique_ptr_data& operator=(const unique_ptr_data&);
+ unique_ptr_data(const unique_ptr_data&);
+};
+
+template <class P, class D>
+struct unique_ptr_data<P, D, false>
+ : private D
+{
+ typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
+ typedef typename deleter_types<D>::del_ref del_ref;
+ typedef typename deleter_types<D>::del_cref del_cref;
+
+ BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
+ : D(), m_p()
+ {}
+
+ BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
+ : D(), m_p(p)
+ {}
+
+ BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
+ : D(d1), m_p(p)
+ {}
+
+ template <class U>
+ BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
+ : D(::boost::forward<U>(d)), m_p(p)
+ {}
+
+ BOOST_MOVE_FORCEINLINE del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); }
+ BOOST_MOVE_FORCEINLINE del_cref deleter() const BOOST_NOEXCEPT { return static_cast<del_cref>(*this); }
+
+ P m_p;
+
+ private:
+ unique_ptr_data& operator=(const unique_ptr_data&);
+ unique_ptr_data(const unique_ptr_data&);
+};
+
+////////////////////////////////////////////
+// is_unique_ptr_convertible
+////////////////////////////////////////////
+
+//Although non-standard, we avoid using pointer_traits
+//to avoid heavy dependencies
+template <typename T>
+struct get_element_type
+{
+ struct DefaultWrap { typedef bmupmu::natify<T> element_type; };
+ template <typename X> static char test(int, typename X::element_type*);
+ template <typename X> static int test(...);
+ static const bool value = (1 == sizeof(test<T>(0, 0)));
+ typedef typename bmupmu::if_c<value, T, DefaultWrap>::type::element_type type;
+};
+
+template<class T>
+struct get_element_type<T*>
+{
+ typedef T type;
+};
+
+template<class T>
+struct get_cvelement
+ : bmupmu::remove_cv<typename get_element_type<T>::type>
+{};
+
+template <class P1, class P2>
+struct is_same_cvelement_and_convertible
+{
+ typedef typename bmupmu::remove_reference<P1>::type arg1;
+ typedef typename bmupmu::remove_reference<P2>::type arg2;
+ static const bool same_cvless =
+ bmupmu::is_same<typename get_cvelement<arg1>::type,typename get_cvelement<arg2>::type>::value;
+ static const bool value = same_cvless && bmupmu::is_convertible<arg1, arg2>::value;
+};
+
+template<bool IsArray, class FromPointer, class ThisPointer>
+struct is_unique_ptr_convertible
+ : is_same_cvelement_and_convertible<FromPointer, ThisPointer>
+{};
+
+template<class FromPointer, class ThisPointer>
+struct is_unique_ptr_convertible<false, FromPointer, ThisPointer>
+ : bmupmu::is_convertible<FromPointer, ThisPointer>
+{};
+
+////////////////////////////////////////
+//// enable_up_moveconv_assign
+////////////////////////////////////////
+
+template<class T, class FromPointer, class ThisPointer, class Type = bmupmu::nat>
+struct enable_up_ptr
+ : bmupmu::enable_if_c< is_unique_ptr_convertible
+ < bmupmu::is_array<T>::value, FromPointer, ThisPointer>::value, Type>
+{};
+
+////////////////////////////////////////
+//// enable_up_moveconv_assign
+////////////////////////////////////////
+
+template<class T, class D, class U, class E>
+struct unique_moveconvert_assignable
+{
+ static const bool t_is_array = bmupmu::is_array<T>::value;
+ static const bool value =
+ t_is_array == bmupmu::is_array<U>::value &&
+ bmupmu::extent<T>::value == bmupmu::extent<U>::value &&
+ is_unique_ptr_convertible
+ < t_is_array
+ , typename bmupmu::pointer_type<U, E>::type, typename bmupmu::pointer_type<T, D>::type
+ >::value;
+};
+
+template<class T, class D, class U, class E, std::size_t N>
+struct unique_moveconvert_assignable<T[], D, U[N], E>
+ : unique_moveconvert_assignable<T[], D, U[], E>
+{};
+
+template<class T, class D, class U, class E, class Type = bmupmu::nat>
+struct enable_up_moveconv_assign
+ : bmupmu::enable_if_c<unique_moveconvert_assignable<T, D, U, E>::value, Type>
+{};
+
+////////////////////////////////////////
+//// enable_up_moveconv_constr
+////////////////////////////////////////
+
+template<class D, class E, bool IsReference = bmupmu::is_reference<D>::value>
+struct unique_deleter_is_initializable
+ : bmupmu::is_same<D, E>
+{};
+
+template <class T, class U>
+class is_rvalue_convertible
+{
+ #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef typename bmupmu::remove_reference<T>::type&& t_from;
+ #else
+ typedef typename bmupmu::if_c
+ < ::boost::has_move_emulation_enabled<T>::value && !bmupmu::is_reference<T>::value
+ , ::boost::rv<T>&
+ , typename bmupmu::add_lvalue_reference<T>::type
+ >::type t_from;
+ #endif
+
+ typedef char true_t;
+ class false_t { char dummy[2]; };
+ static false_t dispatch(...);
+ static true_t dispatch(U);
+ static t_from trigger();
+ public:
+ static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
+};
+
+template<class D, class E>
+struct unique_deleter_is_initializable<D, E, false>
+{
+ #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ //Clang has some problems with is_rvalue_convertible with non-copyable types
+ //so use intrinsic if available
+ #if defined(BOOST_CLANG)
+ #if __has_feature(is_convertible_to)
+ static const bool value = __is_convertible_to(E, D);
+ #else
+ static const bool value = is_rvalue_convertible<E, D>::value;
+ #endif
+ #else
+ static const bool value = is_rvalue_convertible<E, D>::value;
+ #endif
+
+ #else //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ //No hope for compilers with move emulation for now. In several compilers is_convertible
+ // leads to errors, so just move the Deleter and see if the conversion works
+ static const bool value = true; /*is_rvalue_convertible<E, D>::value*/
+ #endif
+};
+
+template<class T, class D, class U, class E, class Type = bmupmu::nat>
+struct enable_up_moveconv_constr
+ : bmupmu::enable_if_c
+ < unique_moveconvert_assignable<T, D, U, E>::value && unique_deleter_is_initializable<D, E>::value
+ , Type>
+{};
+
+} //namespace move_upd {
+// @endcond
+
+namespace movelib {
+
+//! A unique pointer is an object that owns another object and
+//! manages that other object through a pointer.
+//!
+//! More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose
+//! of p when u is itself destroyed (e.g., when leaving block scope). In this context, u is said to own p.
+//!
+//! The mechanism by which u disposes of p is known as p's associated deleter, a function object whose correct
+//! invocation results in p's appropriate disposition (typically its deletion).
+//!
+//! Let the notation u.p denote the pointer stored by u, and let u.d denote the associated deleter. Upon request,
+//! u can reset (replace) u.p and u.d with another pointer and deleter, but must properly dispose of its owned
+//! object via the associated deleter before such replacement is considered completed.
+//!
+//! Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of
+//! such a transfer, the following postconditions hold:
+//! - u2.p is equal to the pre-transfer u.p,
+//! - u.p is equal to nullptr, and
+//! - if the pre-transfer u.d maintained state, such state has been transferred to u2.d.
+//!
+//! As in the case of a reset, u2 must properly dispose of its pre-transfer owned object via the pre-transfer
+//! associated deleter before the ownership transfer is considered complete.
+//!
+//! Each object of a type U instantiated from the unique_ptr template specified in this subclause has the strict
+//! ownership semantics, specified above, of a unique pointer. In partial satisfaction of these semantics, each
+//! such U is MoveConstructible and MoveAssignable, but is not CopyConstructible nor CopyAssignable.
+//! The template parameter T of unique_ptr may be an incomplete type.
+//!
+//! The uses of unique_ptr include providing exception safety for dynamically allocated memory, passing
+//! ownership of dynamically allocated memory to a function, and returning dynamically allocated memory from
+//! a function.
+//!
+//! If T is an array type (e.g. unique_ptr<MyType[]>) the interface is slightly altered:
+//! - Pointers to types derived from T are rejected by the constructors, and by reset.
+//! - The observers <tt>operator*</tt> and <tt>operator-></tt> are not provided.
+//! - The indexing observer <tt>operator[]</tt> is provided.
+//!
+//! \tparam T Provides the type of the stored pointer.
+//! \tparam D The deleter type:
+//! - The default type for the template parameter D is default_delete. A client-supplied template argument
+//! D shall be a function object type, lvalue-reference to function, or lvalue-reference to function object type
+//! for which, given a value d of type D and a value ptr of type unique_ptr<T, D>::pointer, the expression
+//! d(ptr) is valid and has the effect of disposing of the pointer as appropriate for that deleter.
+//! - If the deleter's type D is not a reference type, D shall satisfy the requirements of Destructible.
+//! - If the type <tt>remove_reference<D>::type::pointer</tt> exists, it shall satisfy the requirements of NullablePointer.
+template <class T, class D = default_delete<T> >
+class unique_ptr
+{
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ public:
+ unique_ptr(const unique_ptr&) = delete;
+ unique_ptr& operator=(const unique_ptr&) = delete;
+ private:
+ #else
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr)
+
+ typedef bmupmu::pointer_type<T, D > pointer_type_obtainer;
+ typedef bmupd::unique_ptr_data
+ <typename pointer_type_obtainer::type, D> data_type;
+ typedef typename bmupd::deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
+ typedef typename bmupd::deleter_types<D>::deleter_arg_type2 deleter_arg_type2;
+ data_type m_data;
+ #endif
+
+ public:
+ //! If the type <tt>remove_reference<D>::type::pointer</tt> exists, then it shall be a
+ //! synonym for <tt>remove_reference<D>::type::pointer</tt>. Otherwise it shall be a
+ //! synonym for T*.
+ typedef typename BOOST_MOVE_SEEDOC(pointer_type_obtainer::type) pointer;
+ //! If T is an array type, then element_type is equal to T. Otherwise, if T is a type
+ //! in the form U[], element_type is equal to U.
+ typedef typename BOOST_MOVE_SEEDOC(bmupmu::remove_extent<T>::type) element_type;
+ typedef D deleter_type;
+
+ //! <b>Requires</b>: D shall satisfy the requirements of DefaultConstructible, and
+ //! that construction shall not throw an exception.
+ //!
+ //! <b>Effects</b>: Constructs a unique_ptr object that owns nothing, value-initializing the
+ //! stored pointer and the stored deleter.
+ //!
+ //! <b>Postconditions</b>: <tt>get() == nullptr</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter.
+ //!
+ //! <b>Remarks</b>: If this constructor is instantiated with a pointer type or reference type
+ //! for the template argument D, the program is ill-formed.
+ BOOST_MOVE_FORCEINLINE BOOST_CONSTEXPR unique_ptr() BOOST_NOEXCEPT
+ : m_data()
+ {
+ //If this constructor is instantiated with a pointer type or reference type
+ //for the template argument D, the program is ill-formed.
+ BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
+ BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
+ }
+
+ //! <b>Effects</b>: Same as <tt>unique_ptr()</tt> (default constructor).
+ //!
+ BOOST_MOVE_FORCEINLINE BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
+ : m_data()
+ {
+ //If this constructor is instantiated with a pointer type or reference type
+ //for the template argument D, the program is ill-formed.
+ BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
+ BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
+ }
+
+ //! <b>Requires</b>: D shall satisfy the requirements of DefaultConstructible, and
+ //! that construction shall not throw an exception.
+ //!
+ //! <b>Effects</b>: Constructs a unique_ptr which owns p, initializing the stored pointer
+ //! with p and value initializing the stored deleter.
+ //!
+ //! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter.
+ //!
+ //! <b>Remarks</b>: If this constructor is instantiated with a pointer type or reference type
+ //! for the template argument D, the program is ill-formed.
+ //! This constructor shall not participate in overload resolution unless:
+ //! - If T is not an array type and Pointer is implicitly convertible to pointer.
+ //! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
+ template<class Pointer>
+ BOOST_MOVE_FORCEINLINE explicit unique_ptr(Pointer p
+ BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
+ ) BOOST_NOEXCEPT
+ : m_data(p)
+ {
+ //If T is not an array type, element_type_t<Pointer> derives from T
+ //it uses the default deleter and T has no virtual destructor, then you have a problem
+ BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
+ <D, typename bmupd::get_element_type<Pointer>::type>::value ));
+ //If this constructor is instantiated with a pointer type or reference type
+ //for the template argument D, the program is ill-formed.
+ BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
+ BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
+ }
+
+ //!The signature of this constructor depends upon whether D is a reference type.
+ //! - If D is non-reference type A, then the signature is <tt>unique_ptr(pointer p, const A& d)</tt>.
+ //! - If D is an lvalue-reference type A&, then the signature is <tt>unique_ptr(pointer p, A& d)</tt>.
+ //! - If D is an lvalue-reference type const A&, then the signature is <tt>unique_ptr(pointer p, const A& d)</tt>.
+ //!
+ //!
+ //! <b>Requires</b>: Either
+ //! - D is not an lvalue-reference type and d is an lvalue or const rvalue.
+ //! D shall satisfy the requirements of CopyConstructible, and the copy constructor of D
+ //! shall not throw an exception. This unique_ptr will hold a copy of d.
+ //! - D is an lvalue-reference type and d is an lvalue. the type which D references need not be CopyConstructible nor
+ //! MoveConstructible. This unique_ptr will hold a D which refers to the lvalue d.
+ //!
+ //! <b>Effects</b>: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and
+ //! initializing the deleter as described above.
+ //!
+ //! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. If D is a
+ //! reference type then <tt>get_deleter()</tt> returns a reference to the lvalue d.
+ //!
+ //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
+ //! - If T is not an array type and Pointer is implicitly convertible to pointer.
+ //! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
+ template<class Pointer>
+ BOOST_MOVE_FORCEINLINE unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1
+ BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
+ ) BOOST_NOEXCEPT
+ : m_data(p, d1)
+ {
+ //If T is not an array type, element_type_t<Pointer> derives from T
+ //it uses the default deleter and T has no virtual destructor, then you have a problem
+ BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
+ <D, typename bmupd::get_element_type<Pointer>::type>::value ));
+ }
+
+ //! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type1 d1)</tt>
+ //! and additionally <tt>get() == nullptr</tt>
+ BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT
+ : m_data(pointer(), d1)
+ {}
+
+ //! The signature of this constructor depends upon whether D is a reference type.
+ //! - If D is non-reference type A, then the signature is <tt>unique_ptr(pointer p, A&& d)</tt>.
+ //! - If D is an lvalue-reference type A&, then the signature is <tt>unique_ptr(pointer p, A&& d)</tt>.
+ //! - If D is an lvalue-reference type const A&, then the signature is <tt>unique_ptr(pointer p, const A&& d)</tt>.
+ //!
+ //! <b>Requires</b>: Either
+ //! - D is not an lvalue-reference type and d is a non-const rvalue. D
+ //! shall satisfy the requirements of MoveConstructible, and the move constructor
+ //! of D shall not throw an exception. This unique_ptr will hold a value move constructed from d.
+ //! - D is an lvalue-reference type and d is an rvalue, the program is ill-formed.
+ //!
+ //! <b>Effects</b>: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and
+ //! initializing the deleter as described above.
+ //!
+ //! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. If D is a
+ //! reference type then <tt>get_deleter()</tt> returns a reference to the lvalue d.
+ //!
+ //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
+ //! - If T is not an array type and Pointer is implicitly convertible to pointer.
+ //! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
+ template<class Pointer>
+ BOOST_MOVE_FORCEINLINE unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2
+ BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
+ ) BOOST_NOEXCEPT
+ : m_data(p, ::boost::move(d2))
+ {
+ //If T is not an array type, element_type_t<Pointer> derives from T
+ //it uses the default deleter and T has no virtual destructor, then you have a problem
+ BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
+ <D, typename bmupd::get_element_type<Pointer>::type>::value ));
+ }
+
+ //! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type2 d2)</tt>
+ //! and additionally <tt>get() == nullptr</tt>
+ BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT
+ : m_data(pointer(), ::boost::move(d2))
+ {}
+
+ //! <b>Requires</b>: If D is not a reference type, D shall satisfy the requirements of MoveConstructible.
+ //! Construction of the deleter from an rvalue of type D shall not throw an exception.
+ //!
+ //! <b>Effects</b>: Constructs a unique_ptr by transferring ownership from u to *this. If D is a reference type,
+ //! this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's
+ //! deleter.
+ //!
+ //! <b>Postconditions</b>: <tt>get()</tt> yields the value u.get() yielded before the construction. <tt>get_deleter()</tt>
+ //! returns a reference to the stored deleter that was constructed from u.get_deleter(). If D is a
+ //! reference type then <tt>get_deleter()</tt> and <tt>u.get_deleter()</tt> both reference the same lvalue deleter.
+ BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
+ : m_data(u.release(), ::boost::move_if_not_lvalue_reference<D>(u.get_deleter()))
+ {}
+
+ //! <b>Requires</b>: If E is not a reference type, construction of the deleter from an rvalue of type E shall be
+ //! well formed and shall not throw an exception. Otherwise, E is a reference type and construction of the
+ //! deleter from an lvalue of type E shall be well formed and shall not throw an exception.
+ //!
+ //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
+ //! - <tt>unique_ptr<U, E>::pointer</tt> is implicitly convertible to pointer,
+ //! - U is not an array type, and
+ //! - either D is a reference type and E is the same type as D, or D is not a reference type and E is
+ //! implicitly convertible to D.
+ //!
+ //! <b>Effects</b>: Constructs a unique_ptr by transferring ownership from u to *this. If E is a reference type,
+ //! this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.
+ //!
+ //! <b>Postconditions</b>: <tt>get()</tt> yields the value <tt>u.get()</tt> yielded before the construction. <tt>get_deleter()</tt>
+ //! returns a reference to the stored deleter that was constructed from <tt>u.get_deleter()</tt>.
+ template <class U, class E>
+ BOOST_MOVE_FORCEINLINE unique_ptr( BOOST_RV_REF_BEG_IF_CXX11 unique_ptr<U, E> BOOST_RV_REF_END_IF_CXX11 u
+ BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr<T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E>::type* =0)
+ ) BOOST_NOEXCEPT
+ : m_data(u.release(), ::boost::move_if_not_lvalue_reference<E>(u.get_deleter()))
+ {
+ //If T is not an array type, U derives from T
+ //it uses the default deleter and T has no virtual destructor, then you have a problem
+ BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
+ <D, typename unique_ptr<U, E>::pointer>::value ));
+ }
+
+ //! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior,
+ //! and shall not throw exceptions.
+ //!
+ //! <b>Effects</b>: If <tt>get() == nullpt1r</tt> there are no effects. Otherwise <tt>get_deleter()(get())</tt>.
+ //!
+ //! <b>Note</b>: The use of default_delete requires T to be a complete type
+ ~unique_ptr()
+ { if(m_data.m_p) m_data.deleter()(m_data.m_p); }
+
+ //! <b>Requires</b>: If D is not a reference type, D shall satisfy the requirements of MoveAssignable
+ //! and assignment of the deleter from an rvalue of type D shall not throw an exception. Otherwise, D
+ //! is a reference type; <tt>remove_reference<D>::type</tt> shall satisfy the CopyAssignable requirements and
+ //! assignment of the deleter from an lvalue of type D shall not throw an exception.
+ //!
+ //! <b>Effects</b>: Transfers ownership from u to *this as if by calling <tt>reset(u.release())</tt> followed
+ //! by <tt>get_deleter() = std::forward<D>(u.get_deleter())</tt>.
+ //!
+ //! <b>Returns</b>: *this.
+ unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
+ {
+ this->reset(u.release());
+ m_data.deleter() = ::boost::move_if_not_lvalue_reference<D>(u.get_deleter());
+ return *this;
+ }
+
+ //! <b>Requires</b>: If E is not a reference type, assignment of the deleter from an rvalue of type E shall be
+ //! well-formed and shall not throw an exception. Otherwise, E is a reference type and assignment of the
+ //! deleter from an lvalue of type E shall be well-formed and shall not throw an exception.
+ //!
+ //! <b>Remarks</b>: This operator shall not participate in overload resolution unless:
+ //! - <tt>unique_ptr<U, E>::pointer</tt> is implicitly convertible to pointer and
+ //! - U is not an array type.
+ //!
+ //! <b>Effects</b>: Transfers ownership from u to *this as if by calling <tt>reset(u.release())</tt> followed by
+ //! <tt>get_deleter() = std::forward<E>(u.get_deleter())</tt>.
+ //!
+ //! <b>Returns</b>: *this.
+ template <class U, class E>
+ BOOST_MOVE_DOC1ST(unique_ptr&, typename bmupd::enable_up_moveconv_assign
+ <T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E BOOST_MOVE_I unique_ptr &>::type)
+ operator=(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u) BOOST_NOEXCEPT
+ {
+ this->reset(u.release());
+ m_data.deleter() = ::boost::move_if_not_lvalue_reference<E>(u.get_deleter());
+ return *this;
+ }
+
+ //! <b>Effects</b>: <tt>reset()</tt>.
+ //!
+ //! <b>Postcondition</b>: <tt>get() == nullptr</tt>
+ //!
+ //! <b>Returns</b>: *this.
+ unique_ptr& operator=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
+ { this->reset(); return *this; }
+
+ //! <b>Requires</b>: <tt>get() != nullptr</tt>.
+ //!
+ //! <b>Returns</b>: <tt>*get()</tt>.
+ //!
+ //! <b>Remarks</b: If T is an array type, the program is ill-formed.
+ BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
+ operator*() const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value));
+ return *m_data.m_p;
+ }
+
+ //! <b>Requires</b>: i < the number of elements in the array to which the stored pointer points.
+ //!
+ //! <b>Returns</b>: <tt>get()[i]</tt>.
+ //!
+ //! <b>Remarks</b: If T is not an array type, the program is ill-formed.
+ BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
+ operator[](std::size_t i) const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( bmupmu::extent<T>::value == 0 || i < bmupmu::extent<T>::value );
+ BOOST_ASSERT(m_data.m_p);
+ return m_data.m_p[i];
+ }
+
+ //! <b>Requires</b>: <tt>get() != nullptr</tt>.
+ //!
+ //! <b>Returns</b>: <tt>get()</tt>.
+ //!
+ //! <b>Note</b>: use typically requires that T be a complete type.
+ //!
+ //! <b>Remarks</b: If T is an array type, the program is ill-formed.
+ BOOST_MOVE_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value));
+ BOOST_ASSERT(m_data.m_p);
+ return m_data.m_p;
+ }
+
+ //! <b>Returns</b>: The stored pointer.
+ //!
+ BOOST_MOVE_FORCEINLINE pointer get() const BOOST_NOEXCEPT
+ { return m_data.m_p; }
+
+ //! <b>Returns</b>: A reference to the stored deleter.
+ //!
+ BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(D&, typename bmupmu::add_lvalue_reference<D>::type)
+ get_deleter() BOOST_NOEXCEPT
+ { return m_data.deleter(); }
+
+ //! <b>Returns</b>: A reference to the stored deleter.
+ //!
+ BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(const D&, typename bmupmu::add_const_lvalue_reference<D>::type)
+ get_deleter() const BOOST_NOEXCEPT
+ { return m_data.deleter(); }
+
+ #ifdef BOOST_MOVE_DOXYGEN_INVOKED
+ //! <b>Returns</b>: Returns: get() != nullptr.
+ //!
+ BOOST_MOVE_FORCEINLINE explicit operator bool
+ #else
+ BOOST_MOVE_FORCEINLINE operator bmupd::explicit_bool_arg
+ #endif
+ ()const BOOST_NOEXCEPT
+ {
+ return m_data.m_p
+ ? &bmupd::bool_conversion::for_bool
+ : bmupd::explicit_bool_arg(0);
+ }
+
+ //! <b>Postcondition</b>: <tt>get() == nullptr</tt>.
+ //!
+ //! <b>Returns</b>: The value <tt>get()</tt> had at the start of the call to release.
+ BOOST_MOVE_FORCEINLINE pointer release() BOOST_NOEXCEPT
+ {
+ const pointer tmp = m_data.m_p;
+ m_data.m_p = pointer();
+ return tmp;
+ }
+
+ //! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior,
+ //! and shall not throw exceptions.
+ //!
+ //! <b>Effects</b>: assigns p to the stored pointer, and then if the old value of the stored pointer, old_p, was not
+ //! equal to nullptr, calls <tt>get_deleter()(old_p)</tt>. Note: The order of these operations is significant
+ //! because the call to <tt>get_deleter()</tt> may destroy *this.
+ //!
+ //! <b>Postconditions</b>: <tt>get() == p</tt>. Note: The postcondition does not hold if the call to <tt>get_deleter()</tt>
+ //! destroys *this since <tt>this->get()</tt> is no longer a valid expression.
+ //!
+ //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
+ //! - If T is not an array type and Pointer is implicitly convertible to pointer.
+ //! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
+ template<class Pointer>
+ BOOST_MOVE_DOC1ST(void, typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer BOOST_MOVE_I void>::type)
+ reset(Pointer p) BOOST_NOEXCEPT
+ {
+ //If T is not an array type, element_type_t<Pointer> derives from T
+ //it uses the default deleter and T has no virtual destructor, then you have a problem
+ BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
+ <D, typename bmupd::get_element_type<Pointer>::type>::value ));
+ pointer tmp = m_data.m_p;
+ m_data.m_p = p;
+ if(tmp) m_data.deleter()(tmp);
+ }
+
+ //! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior,
+ //! and shall not throw exceptions.
+ //!
+ //! <b>Effects</b>: assigns nullptr to the stored pointer, and then if the old value of the stored pointer, old_p, was not
+ //! equal to nullptr, calls <tt>get_deleter()(old_p)</tt>. Note: The order of these operations is significant
+ //! because the call to <tt>get_deleter()</tt> may destroy *this.
+ //!
+ //! <b>Postconditions</b>: <tt>get() == p</tt>. Note: The postcondition does not hold if the call to <tt>get_deleter()</tt>
+ //! destroys *this since <tt>this->get()</tt> is no longer a valid expression.
+ void reset() BOOST_NOEXCEPT
+ { this->reset(pointer()); }
+
+ //! <b>Effects</b>: Same as <tt>reset()</tt>
+ //!
+ void reset(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
+ { this->reset(); }
+
+ //! <b>Requires</b>: <tt>get_deleter()</tt> shall be swappable and shall not throw an exception under swap.
+ //!
+ //! <b>Effects</b>: Invokes swap on the stored pointers and on the stored deleters of *this and u.
+ void swap(unique_ptr& u) BOOST_NOEXCEPT
+ {
+ ::boost::adl_move_swap(m_data.m_p, u.m_data.m_p);
+ ::boost::adl_move_swap(m_data.deleter(), u.m_data.deleter());
+ }
+};
+
+//! <b>Effects</b>: Calls <tt>x.swap(y)</tt>.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE void swap(unique_ptr<T, D> &x, unique_ptr<T, D> &y) BOOST_NOEXCEPT
+{ x.swap(y); }
+
+//! <b>Returns</b>: <tt>x.get() == y.get()</tt>.
+//!
+template <class T1, class D1, class T2, class D2>
+BOOST_MOVE_FORCEINLINE bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+{ return x.get() == y.get(); }
+
+//! <b>Returns</b>: <tt>x.get() != y.get()</tt>.
+//!
+template <class T1, class D1, class T2, class D2>
+BOOST_MOVE_FORCEINLINE bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+{ return x.get() != y.get(); }
+
+//! <b>Returns</b>: x.get() < y.get().
+//!
+//! <b>Remarks</b>: This comparison shall induce a
+//! strict weak ordering betwen pointers.
+template <class T1, class D1, class T2, class D2>
+BOOST_MOVE_FORCEINLINE bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+{ return x.get() < y.get(); }
+
+//! <b>Returns</b>: !(y < x).
+//!
+template <class T1, class D1, class T2, class D2>
+BOOST_MOVE_FORCEINLINE bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+{ return !(y < x); }
+
+//! <b>Returns</b>: y < x.
+//!
+template <class T1, class D1, class T2, class D2>
+BOOST_MOVE_FORCEINLINE bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+{ return y < x; }
+
+//! <b>Returns</b>:!(x < y).
+//!
+template <class T1, class D1, class T2, class D2>
+BOOST_MOVE_FORCEINLINE bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
+{ return !(x < y); }
+
+//! <b>Returns</b>:!x.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator==(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
+{ return !x; }
+
+//! <b>Returns</b>:!x.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator==(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
+{ return !x; }
+
+//! <b>Returns</b>: (bool)x.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator!=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
+{ return !!x; }
+
+//! <b>Returns</b>: (bool)x.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator!=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
+{ return !!x; }
+
+//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
+//!
+//! <b>Returns</b>: Returns <tt>x.get() < pointer()</tt>.
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator<(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
+{ return x.get() < typename unique_ptr<T, D>::pointer(); }
+
+//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
+//!
+//! <b>Returns</b>: Returns <tt>pointer() < x.get()</tt>.
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator<(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
+{ return typename unique_ptr<T, D>::pointer() < x.get(); }
+
+//! <b>Returns</b>: <tt>nullptr < x</tt>.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator>(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
+{ return x.get() > typename unique_ptr<T, D>::pointer(); }
+
+//! <b>Returns</b>: <tt>x < nullptr</tt>.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator>(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
+{ return typename unique_ptr<T, D>::pointer() > x.get(); }
+
+//! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator<=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
+{ return !(bmupd::nullptr_type() < x); }
+
+//! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator<=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
+{ return !(x < bmupd::nullptr_type()); }
+
+//! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator>=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
+{ return !(x < bmupd::nullptr_type()); }
+
+//! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
+//!
+template <class T, class D>
+BOOST_MOVE_FORCEINLINE bool operator>=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
+{ return !(bmupd::nullptr_type() < x); }
+
+} //namespace movelib {
+} //namespace boost{
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED
diff --git a/include/boost/move/utility.hpp b/include/boost/move/utility.hpp
new file mode 100644
index 0000000..28de793
--- /dev/null
+++ b/include/boost/move/utility.hpp
@@ -0,0 +1,150 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+//! This header includes core utilities from <tt><boost/move/utility_core.hpp></tt> and defines
+//! some more advanced utilities such as:
+
+#ifndef BOOST_MOVE_MOVE_UTILITY_HPP
+#define BOOST_MOVE_MOVE_UTILITY_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
+#include <boost/move/utility_core.hpp>
+#include <boost/move/traits.hpp>
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ namespace boost {
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_if_noexcept()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && !has_move_emulation_enabled<T>::value
+ , typename ::boost::move_detail::add_const<T>::type &
+ >::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
+ && ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, rv<T>&>::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ {
+ return *static_cast<rv<T>* >(::boost::move_detail::addressof(x));
+ }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
+ && ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
+ , rv<T>&
+ >::type
+ move_if_noexcept(rv<T>& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
+ && !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
+ , typename ::boost::move_detail::add_const<T>::type &
+ >::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
+ && !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
+ , typename ::boost::move_detail::add_const<T>::type &
+ >::type
+ move_if_noexcept(rv<T>& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ } //namespace boost
+
+#else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+ #include <utility>
+
+ namespace boost{
+
+ using ::std::move_if_noexcept;
+
+ } //namespace boost
+
+ #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
+
+ namespace boost {
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_if_noexcept()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ //! This function provides a way to convert a reference into a rvalue reference
+ //! in compilers with rvalue references. For other compilers converts T & into
+ //! <i>::boost::rv<T> &</i> so that move emulation is activated. Reference
+ //! would be converted to rvalue reference only if input type is nothrow move
+ //! constructible or if it has no copy constructor. In all other cases const
+ //! reference would be returned
+ template <class T>
+ rvalue_reference_or_const_lvalue_reference move_if_noexcept(input_reference) noexcept;
+
+ #else //BOOST_MOVE_DOXYGEN_INVOKED
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, T&&>::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ { return ::boost::move(x); }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
+ < !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, const T&>::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ { return x; }
+
+ #endif //BOOST_MOVE_DOXYGEN_INVOKED
+
+ } //namespace boost {
+
+ #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_MOVE_UTILITY_HPP
diff --git a/include/boost/move/utility_core.hpp b/include/boost/move/utility_core.hpp
new file mode 100644
index 0000000..55042a9
--- /dev/null
+++ b/include/boost/move/utility_core.hpp
@@ -0,0 +1,318 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+//! This header defines core utilities to ease the development
+//! of move-aware functions. This header minimizes dependencies
+//! from other libraries.
+
+#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP
+#define BOOST_MOVE_MOVE_UTILITY_CORE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp> //forceinline
+#include <boost/move/core.hpp>
+#include <boost/move/detail/meta_utils.hpp>
+#include <boost/static_assert.hpp>
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ namespace boost {
+
+ template<class T>
+ struct enable_move_utility_emulation
+ {
+ static const bool value = true;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
+ < T &
+ , enable_move_utility_emulation<T>
+ , has_move_emulation_disabled<T>
+ >::type
+ move(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
+ < rv<T>&
+ , enable_move_utility_emulation<T>
+ , has_move_emulation_enabled<T>
+ >::type
+ move(T& x) BOOST_NOEXCEPT
+ {
+ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x) );
+ }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
+ < rv<T>&
+ , enable_move_utility_emulation<T>
+ , has_move_emulation_enabled<T>
+ >::type
+ move(rv<T>& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // forward()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
+ < T &
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_rv<T>
+ >::type
+ forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
+ {
+ return const_cast<T&>(x);
+ }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
+ < const T &
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_not_rv<T>
+ >::type
+ forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_if_not_lvalue_reference()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
+ < T &
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_rv<T>
+ >::type
+ move_if_not_lvalue_reference(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
+ {
+ return const_cast<T&>(x);
+ }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
+ < typename ::boost::move_detail::add_lvalue_reference<T>::type
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_not_rv<T>
+ , ::boost::move_detail::or_
+ < ::boost::move_detail::is_lvalue_reference<T>
+ , has_move_emulation_disabled<T>
+ >
+ >::type
+ move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
+ < rv<T>&
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_not_rv<T>
+ , ::boost::move_detail::and_
+ < ::boost::move_detail::not_< ::boost::move_detail::is_lvalue_reference<T> >
+ , has_move_emulation_enabled<T>
+ >
+ >::type
+ move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
+ {
+ return move(x);
+ }
+
+ } //namespace boost
+
+#else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+ #include <utility>
+
+ namespace boost{
+
+ using ::std::move;
+ using ::std::forward;
+
+ } //namespace boost
+
+ #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
+
+ namespace boost {
+
+ //! This trait's internal boolean `value` is false in compilers with rvalue references
+ //! and true in compilers without rvalue references.
+ //!
+ //! A user can specialize this trait for a type T to false to SFINAE out `move` and `forward`
+ //! so that the user can define a different move emulation for that type in namespace boost
+ //! (e.g. another Boost library for its types) and avoid any overload ambiguity.
+ template<class T>
+ struct enable_move_utility_emulation
+ {
+ static const bool value = false;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ //! This function provides a way to convert a reference into a rvalue reference
+ //! in compilers with rvalue references. For other compilers if `T` is Boost.Move
+ //! enabled type then it converts `T&` into <tt>::boost::rv<T> &</tt> so that
+ //! move emulation is activated, else it returns `T &`.
+ template <class T>
+ rvalue_reference move(input_reference) noexcept;
+
+ #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+
+ //Old move approach, lvalues could bind to rvalue references
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
+ { return t; }
+
+ #else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
+ { return static_cast<typename ::boost::move_detail::remove_reference<T>::type &&>(t); }
+
+ #endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // forward
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ //! This function provides limited form of forwarding that is usually enough for
+ //! in-place construction and avoids the exponential overloading for
+ //! achieve the limited forwarding in C++03.
+ //!
+ //! For compilers with rvalue references this function provides perfect forwarding.
+ //!
+ //! Otherwise:
+ //! * If input_reference binds to const ::boost::rv<T> & then it output_reference is
+ //! ::boost::rv<T> &
+ //!
+ //! * Else, output_reference is equal to input_reference.
+ template <class T> output_reference forward(input_reference) noexcept;
+ #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+
+ //Old move approach, lvalues could bind to rvalue references
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
+ { return t; }
+
+ #else //Old move
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
+ { return static_cast<T&&>(t); }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
+ {
+ //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
+ BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
+ return static_cast<T&&>(t);
+ }
+
+ #endif //BOOST_MOVE_DOXYGEN_INVOKED
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_if_not_lvalue_reference
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Calls `boost::move` if `input_reference` is not a lvalue reference.
+ //! Otherwise returns the reference
+ template <class T> output_reference move_if_not_lvalue_reference(input_reference) noexcept;
+ #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+
+ //Old move approach, lvalues could bind to rvalue references
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
+ { return t; }
+
+ #else //Old move
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
+ { return static_cast<T&&>(t); }
+
+ template <class T>
+ BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
+ {
+ //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
+ BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
+ return static_cast<T&&>(t);
+ }
+
+ #endif //BOOST_MOVE_DOXYGEN_INVOKED
+
+ } //namespace boost {
+
+ #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+namespace boost{
+namespace move_detail{
+
+template <typename T>
+typename boost::move_detail::add_rvalue_reference<T>::type declval();
+
+} //namespace move_detail{
+} //namespace boost{
+
+#endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP