1
0
mirror of https://git.suyu.dev/suyu/suyu synced 2025-09-11 16:56:32 -05:00

Initial commit

This commit is contained in:
Crimson-Hawk
2024-03-05 16:42:40 +08:00
commit f1e4595ebf
39576 changed files with 7006612 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
CRTLinkage: dynamic
LibraryLinkage: dynamic

View File

@@ -0,0 +1,8 @@
Package: boost-move
Version: 1.79.0
Depends: boost-assert, boost-config, boost-core, boost-static-assert, boost-vcpkg-helpers, boost-winapi
Architecture: x64-windows
Multi-Arch: same
Abi: c41e7bcb3cbb57100f8b9da78c55dca8017a976ac084f3a13c28135622927a0b
Description: Boost move module
Type: Port

View File

@@ -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

View File

@@ -0,0 +1,363 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
namespace boost {
namespace movelib {
///@cond
namespace detail_adaptive {
template<class RandIt, class Compare, class XBuf>
inline void adaptive_merge_combine_blocks( RandIt first
, typename iter_size<RandIt>::type len1
, typename iter_size<RandIt>::type len2
, typename iter_size<RandIt>::type collected
, typename iter_size<RandIt>::type n_keys
, typename iter_size<RandIt>::type l_block
, bool use_internal_buf
, bool xbuf_used
, Compare comp
, XBuf & xbuf
)
{
typedef typename iter_size<RandIt>::type size_type;
size_type const len = size_type(len1+len2);
size_type const l_combine = size_type(len-collected);
size_type const l_combine1 = size_type(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 iter_size<RandIt>::type len1
, typename iter_size<RandIt>::type len2
, typename iter_size<RandIt>::type collected
, typename iter_size<RandIt>::type l_intbuf
, typename iter_size<RandIt>::type //l_block
, bool //use_internal_buf
, bool xbuf_used
, Compare comp
, XBuf & xbuf
)
{
typedef typename iter_size<RandIt>::type size_type;
size_type n_keys = size_type(collected-l_intbuf);
size_type len = size_type(len1+len2);
if (!xbuf_used || n_keys) {
xbuf.clear();
const size_type middle = xbuf_used && n_keys ? n_keys: collected;
unstable_sort(first, first + middle, comp, xbuf);
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A k/b srt: ", len);
stable_merge(first, first + middle, first + len, comp, xbuf);
}
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 = size_type(len1/l_block + len2/l_block);
const size_type second_half_blocks = size_type(len2/l_block);
const size_type first_half_aux = size_type(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 = size_type((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;
if (xbuf.capacity() > l_block){
l_block = xbuf.capacity();
}
//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 iter_size<RandIt>::type len1
, typename iter_size<RandIt>::type len2
, Compare comp
, XBuf & xbuf
)
{
typedef typename iter_size<RandIt>::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 = size_type(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 = size_type(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
, typename iter_size<RandIt>::type uninitialized_len = 0)
{
typedef typename iter_size<RandIt>::type size_type;
typedef typename iterator_traits<RandIt>::value_type value_type;
if (first == middle || middle == last){
return;
}
//Reduce ranges to merge if possible
do {
if (comp(*middle, *first)){
break;
}
++first;
if (first == middle)
return;
} while(1);
RandIt first_high(middle);
--first_high;
do {
--last;
if (comp(*last, *first_high)){
++last;
break;
}
if (last == middle)
return;
} while(1);
::boost::movelib::adaptive_xbuf<value_type, value_type*, size_type> xbuf(uninitialized, size_type(uninitialized_len));
::boost::movelib::detail_adaptive::adaptive_merge_impl(first, size_type(middle - first), size_type(last - middle), comp, xbuf);
}
} //namespace movelib {
} //namespace boost {
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#include <boost/move/detail/config_end.hpp>
#endif //#define BOOST_MOVE_ADAPTIVE_MERGE_HPP

View File

@@ -0,0 +1,654 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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>
#include <boost/core/ignore_unused.hpp>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
namespace boost {
namespace movelib {
///@cond
namespace detail_adaptive {
template<class RandIt>
void move_data_backward( RandIt cur_pos
, typename iter_size<RandIt>::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 iter_size<RandIt>::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 iter_size<RandIt>::type
adaptive_sort_build_blocks
( RandIt const first
, typename iter_size<RandIt>::type const len
, typename iter_size<RandIt>::type const l_base
, typename iter_size<RandIt>::type const l_build_buf
, XBuf & xbuf
, Compare comp)
{
typedef typename iter_size<RandIt>::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 = size_type(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, size_type(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, size_type(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<size_type>(elements_in_blocks, size_type(2u*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 iter_size<RandIt>::type const len
, typename iter_size<RandIt>::type const l_prev_merged
, typename iter_size<RandIt>::type const l_block
, bool const use_buf
, bool const xbuf_used
, XBuf & xbuf
, Compare comp
, bool merge_left)
{
boost::ignore_unused(xbuf);
typedef typename iter_size<RandIt>::type size_type;
size_type const l_reg_combined = size_type(2u*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;
boost::ignore_unused(l_total_combined);
BOOST_ASSERT(l_total_combined <= len);
size_type const max_i = size_type(n_reg_combined + (l_irreg_combined != 0));
if(merge_left || !use_buf) {
for( size_type combined_i = 0; combined_i != max_i; ) {
//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, size_type, 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(boost::movelib::is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::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);
++combined_i;
if(combined_i != max_i)
combined_first += l_reg_combined;
}
}
else{
combined_first += size_type(l_reg_combined*(max_i-1u));
for( size_type combined_i = max_i; combined_i; ) {
--combined_i;
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, size_type, 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(boost::movelib::is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::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);
if(combined_i)
combined_first -= l_reg_combined;
}
}
}
//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 iter_size<RandIt>::type &n_keys
, RandIt const buffer
, typename iter_size<RandIt>::type const l_buf_plus_data
, typename iter_size<RandIt>::type l_merged
, typename iter_size<RandIt>::type &l_intbuf
, XBuf & xbuf
, Compare comp)
{
typedef typename iter_size<RandIt>::type size_type;
RandIt const first = buffer + l_intbuf;
size_type const l_data = size_type(l_buf_plus_data - l_intbuf);
size_type const l_unique = size_type(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 = size_type(2u*l_merged)
, ++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, size_type(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 = size_type(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 = size_type(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 = size_type(2u*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 = size_type(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 iter_size<RandIt>::type const l_intbuf
, typename iter_size<RandIt>::type const n_keys
, typename iter_size<RandIt>::type const len
, XBuf & xbuf
, Compare comp)
{
//BOOST_ASSERT(n_keys || xbuf.size() == l_intbuf);
xbuf.clear();
typedef typename iter_size<RandIt>::type size_type;
size_type const n_key_plus_buf = size_type(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 typename iter_size<RandIt>::type 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 = size_type(2u*l_intbuf);
}
//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 = size_type(l_intbuf-1u);
while(n_min_ideal_keys >= (len-l_intbuf-n_min_ideal_keys)/l_intbuf){
--n_min_ideal_keys;
}
++n_min_ideal_keys;
BOOST_ASSERT(n_min_ideal_keys <= l_intbuf);
if(xbuf.template supports_aligned_trailing<size_type>
(l_intbuf, size_type((size_type(len-l_intbuf)-1u)/l_intbuf+1u))){
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 : size_type(l_intbuf*2u);
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 = size_type(l_intbuf*2);
n_keys = l_intbuf;
}
else if(collected >= (n_min_ideal_keys+l_intbuf)){
l_build_buf = l_intbuf;
n_keys = size_type(collected - l_intbuf);
}
//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-1u)){
n_keys &= size_type(n_keys-1u); // 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 iter_size<RandIt>::type const len
, Compare comp
, XBuf & xbuf
)
{
typedef typename iter_size<RandIt>::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 = size_type(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
, size_type(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, size_type(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
, typename iter_size<RandIt>::type uninitialized_len)
{
typedef typename iter_size<RandIt>::type size_type;
typedef typename iterator_traits<RandIt>::value_type value_type;
::boost::movelib::adaptive_xbuf<value_type, RandRawIt, size_type> 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>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#endif //#define BOOST_MOVE_ADAPTIVE_SORT_HPP

View File

@@ -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

View File

@@ -0,0 +1,121 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
namespace boost { namespace movelib{
template <class RandomAccessIterator, class Compare>
class heap_sort_helper
{
typedef typename boost::movelib::iter_size<RandomAccessIterator>::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 = size_type(2u*(hole_index + 1u));
while (second_child < len) {
if (comp(*(first + second_child), *(first + size_type(second_child - 1u))))
second_child--;
*(first + hole_index) = boost::move(*(first + second_child));
hole_index = second_child;
second_child = size_type(2u * (second_child + 1u));
}
if (second_child == len) {
*(first + hole_index) = boost::move(*(first + size_type(second_child - 1u)));
hole_index = size_type(second_child - 1);
}
{ //push_heap-like ending
size_type parent = size_type((hole_index - 1u) / 2u);
while (hole_index > top_index && comp(*(first + parent), value)) {
*(first + hole_index) = boost::move(*(first + parent));
hole_index = parent;
parent = size_type((hole_index - 1u) / 2u);
}
*(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 = size_type(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{
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#include <boost/move/detail/config_end.hpp>
#endif //#ifndef BOOST_MOVE_DETAIL_HEAP_SORT_HPP

View File

@@ -0,0 +1,137 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
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{
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#endif //#ifndef BOOST_MOVE_DETAIL_INSERT_SORT_HPP

View File

@@ -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

View File

@@ -0,0 +1,946 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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/core/ignore_unused.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>
#include <cstddef>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
namespace boost {
namespace movelib {
template<class T, class RandRawIt = T*, class SizeType = typename iter_size<RandRawIt>::type>
class adaptive_xbuf
{
adaptive_xbuf(const adaptive_xbuf &);
adaptive_xbuf & operator=(const adaptive_xbuf &);
#if !defined(UINTPTR_MAX)
typedef std::size_t uintptr_t;
#endif
public:
typedef RandRawIt iterator;
typedef SizeType size_type;
BOOST_MOVE_FORCEINLINE adaptive_xbuf()
: m_ptr(), m_size(0), m_capacity(0)
{}
BOOST_MOVE_FORCEINLINE adaptive_xbuf(RandRawIt raw_memory, size_type cap)
: m_ptr(raw_memory), m_size(0), m_capacity(cap)
{}
template<class RandIt>
void move_assign(RandIt first, size_type n)
{
typedef typename iterator_traits<RandIt>::difference_type rand_diff_t;
if(n <= m_size){
boost::move(first, first+rand_diff_t(n), m_ptr);
size_type sz = m_size;
while(sz-- != n){
m_ptr[sz].~T();
}
m_size = n;
}
else{
RandRawIt result = boost::move(first, first+rand_diff_t(m_size), m_ptr);
boost::uninitialized_move(first+rand_diff_t(m_size), first+rand_diff_t(n), result);
m_size = n;
}
}
template<class RandIt>
void push_back(RandIt first, size_type 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);
}
}
BOOST_MOVE_FORCEINLINE void set_size(size_type sz)
{
m_size = sz;
}
void shrink_to_fit(size_type const sz)
{
if(m_size > sz){
for(size_type szt_i = sz; szt_i != m_size; ++szt_i){
m_ptr[szt_i].~T();
}
m_size = sz;
}
}
void initialize_until(size_type const sz, T &t)
{
BOOST_ASSERT(m_size < m_capacity);
if(m_size < sz){
BOOST_TRY
{
::new((void*)&m_ptr[m_size]) T(::boost::move(t));
++m_size;
for(; m_size != sz; ++m_size){
::new((void*)&m_ptr[m_size]) T(::boost::move(m_ptr[m_size-1]));
}
t = ::boost::move(m_ptr[m_size-1]);
}
BOOST_CATCH(...)
{
while(m_size)
{
--m_size;
m_ptr[m_size].~T();
}
}
BOOST_CATCH_END
}
}
private:
template<class RIt>
BOOST_MOVE_FORCEINLINE static bool is_raw_ptr(RIt)
{
return false;
}
BOOST_MOVE_FORCEINLINE static bool is_raw_ptr(T*)
{
return true;
}
public:
template<class U>
bool supports_aligned_trailing(size_type sz, size_type trail_count) const
{
if(this->is_raw_ptr(this->data()) && m_capacity){
uintptr_t u_addr_sz = uintptr_t(&*(this->data()+sz));
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>
BOOST_MOVE_FORCEINLINE U *aligned_trailing() const
{
return this->aligned_trailing<U>(this->size());
}
template<class U>
BOOST_MOVE_FORCEINLINE U *aligned_trailing(size_type 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;
}
BOOST_MOVE_FORCEINLINE ~adaptive_xbuf()
{
this->clear();
}
BOOST_MOVE_FORCEINLINE size_type capacity() const
{ return m_capacity; }
BOOST_MOVE_FORCEINLINE iterator data() const
{ return m_ptr; }
BOOST_MOVE_FORCEINLINE iterator begin() const
{ return m_ptr; }
BOOST_MOVE_FORCEINLINE iterator end() const
{ return m_ptr+m_size; }
BOOST_MOVE_FORCEINLINE size_type size() const
{ return m_size; }
BOOST_MOVE_FORCEINLINE bool empty() const
{ return !m_size; }
BOOST_MOVE_FORCEINLINE void clear()
{
this->shrink_to_fit(0u);
}
private:
RandRawIt m_ptr;
size_type m_size;
size_type m_capacity;
};
template<class Iterator, class SizeType, class Op>
class range_xbuf
{
range_xbuf(const range_xbuf &);
range_xbuf & operator=(const range_xbuf &);
public:
typedef SizeType 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, size_type n)
{
BOOST_ASSERT(size_type(n) <= size_type(m_cap-m_first));
typedef typename iter_difference<RandIt>::type d_type;
m_last = Op()(forward_t(), first, first+d_type(n), m_first);
}
~range_xbuf()
{}
size_type capacity() const
{ return m_cap-m_first; }
Iterator data() const
{ return m_first; }
Iterator end() const
{ return m_last; }
size_type 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(size_type sz)
{
m_last = m_first;
m_last += sz;
}
private:
Iterator const m_first;
Iterator m_last;
Iterator const m_cap;
};
// @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 = Unsigned(z << 1);
x = Unsigned(x >> 1);
y = Unsigned(y >> 1);
}
while(x && y){
if(!(x&1))
x = Unsigned(x >> 1);
else if(!(y&1))
y = Unsigned (y >> 1);
else if(x >=y)
x = Unsigned((x-y) >> 1u);
else
y = Unsigned((y-x) >> 1);
}
return Unsigned(z*(x+y));
}
}
template<typename RandIt>
RandIt rotate_gcd(RandIt first, RandIt middle, RandIt last)
{
typedef typename iter_size<RandIt>::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 iter_size<RandIt>::type size_type;
size_type len = size_type(last - first);
RandIt middle;
while (len) {
size_type step = size_type(len >> 1);
middle = first;
middle += step;
if (comp(*middle, key)) {
first = ++middle;
len = size_type(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 iter_size<RandIt>::type size_type;
size_type len = size_type(last - first);
RandIt middle;
while (len) {
size_type step = size_type(len >> 1);
middle = first;
middle += step;
if (!comp(key, *middle)) {
first = ++middle;
len = size_type(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());
}
///////////////////////////////////////////////////////////////////////////////
//
// 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 iter_size<RandIt>::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: 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 = 16u;
template <class RandIt, class Compare>
void merge_bufferless_ONlogN_recursive
( RandIt first, RandIt middle, RandIt last
, typename iter_size<RandIt>::type len1
, typename iter_size<RandIt>::type len2
, Compare comp)
{
typedef typename iter_size<RandIt>::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;
size_type len11 = 0;
size_type 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 size_type len_internal = size_type(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 = size_type(len1-len11);
len2 = size_type(len2-len22);
}
else {
merge_bufferless_ONlogN_recursive
(new_middle, second_cut, last, size_type(len1 - len11), size_type(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)
{
typedef typename iter_size<RandIt>::type size_type;
merge_bufferless_ONlogN_recursive
(first, middle, last, size_type(middle - first), size_type(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);
boost::ignore_unused(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);
boost::ignore_unused(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
// [first, 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);
boost::ignore_unused(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);
}
/// This is a helper function for the merge routines.
template<typename BidirectionalIterator1, typename BidirectionalIterator2>
BidirectionalIterator1
rotate_adaptive(BidirectionalIterator1 first,
BidirectionalIterator1 middle,
BidirectionalIterator1 last,
typename iter_size<BidirectionalIterator1>::type len1,
typename iter_size<BidirectionalIterator1>::type len2,
BidirectionalIterator2 buffer,
typename iter_size<BidirectionalIterator1>::type buffer_size)
{
if (len1 > len2 && len2 <= buffer_size)
{
if(len2) //Protect against self-move ranges
{
BidirectionalIterator2 buffer_end = boost::move(middle, last, buffer);
boost::move_backward(first, middle, last);
return boost::move(buffer, buffer_end, first);
}
else
return first;
}
else if (len1 <= buffer_size)
{
if(len1) //Protect against self-move ranges
{
BidirectionalIterator2 buffer_end = boost::move(first, middle, buffer);
BidirectionalIterator1 ret = boost::move(middle, last, first);
boost::move(buffer, buffer_end, ret);
return ret;
}
else
return last;
}
else
return rotate_gcd(first, middle, last);
}
template<typename BidirectionalIterator,
typename Pointer, typename Compare>
void merge_adaptive_ONlogN_recursive
(BidirectionalIterator first,
BidirectionalIterator middle,
BidirectionalIterator last,
typename iter_size<BidirectionalIterator>::type len1,
typename iter_size<BidirectionalIterator>::type len2,
Pointer buffer,
typename iter_size<BidirectionalIterator>::type buffer_size,
Compare comp)
{
typedef typename iter_size<BidirectionalIterator>::type size_type;
//trivial cases
if (!len2 || !len1) {
// no-op
}
else if (len1 <= buffer_size || len2 <= buffer_size) {
range_xbuf<Pointer, size_type, move_op> rxbuf(buffer, buffer + buffer_size);
buffered_merge(first, middle, last, comp, rxbuf);
}
else if (size_type(len1 + len2) == 2u) {
if (comp(*middle, *first))
adl_move_swap(*first, *middle);
}
else if (size_type(len1 + len2) < MergeBufferlessONLogNRotationThreshold) {
merge_bufferless_ON2(first, middle, last, comp);
}
else {
BidirectionalIterator first_cut = first;
BidirectionalIterator second_cut = middle;
size_type len11 = 0;
size_type len22 = 0;
if (len1 > len2) //(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);
}
BidirectionalIterator new_middle
= rotate_adaptive(first_cut, middle, second_cut,
size_type(len1 - len11), len22, buffer,
buffer_size);
merge_adaptive_ONlogN_recursive(first, first_cut, new_middle, len11,
len22, buffer, buffer_size, comp);
merge_adaptive_ONlogN_recursive(new_middle, second_cut, last,
size_type(len1 - len11), size_type(len2 - len22), buffer, buffer_size, comp);
}
}
template<typename BidirectionalIterator, typename Compare, typename RandRawIt>
void merge_adaptive_ONlogN(BidirectionalIterator first,
BidirectionalIterator middle,
BidirectionalIterator last,
Compare comp,
RandRawIt uninitialized,
typename iter_size<BidirectionalIterator>::type uninitialized_len)
{
typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
typedef typename iter_size<BidirectionalIterator>::type size_type;
if (first == middle || middle == last)
return;
if(uninitialized_len)
{
const size_type len1 = size_type(middle - first);
const size_type len2 = size_type(last - middle);
::boost::movelib::adaptive_xbuf<value_type, RandRawIt> xbuf(uninitialized, uninitialized_len);
xbuf.initialize_until(uninitialized_len, *first);
merge_adaptive_ONlogN_recursive(first, middle, last, len1, len2, xbuf.begin(), uninitialized_len, comp);
}
else
{
merge_bufferless(first, middle, last, comp);
}
}
} //namespace movelib {
} //namespace boost {
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#endif //#define BOOST_MOVE_MERGE_HPP

View File

@@ -0,0 +1,216 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
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 iter_size<RandIt>::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 iter_size<RandIt>::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 = size_type(count/2u);
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 iter_size<RandIt>::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(size_type(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 iter_size<RandIt>::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 = size_type(count/2u);
size_type const rest = size_type(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));
}
}
///@cond
template<class RandIt, class RandItRaw, class Compare>
void merge_sort_with_constructed_buffer( RandIt first, RandIt last, Compare comp, RandItRaw buffer)
{
typedef typename iter_size<RandIt>::type size_type;
size_type const count = size_type(last - first);
if(count <= MergeSortInsertionSortThreshold){
insertion_sort(first, last, comp);
}
else{
size_type const half = size_type(count/2);
size_type const rest = size_type(count - half);
RandIt const half_it = first + half;
RandIt const rest_it = first + rest;
merge_sort_copy(half_it, last, buffer, comp);
merge_sort_copy(first, half_it, rest_it, comp);
merge_with_right_placed
(buffer, buffer + rest
, first, rest_it, last, antistable<Compare>(comp));
}
}
template<typename RandIt, typename Pointer,
typename Distance, typename Compare>
void stable_sort_ONlogN_recursive(RandIt first, RandIt last, Pointer buffer, Distance buffer_size, Compare comp)
{
typedef typename iter_size<RandIt>::type size_type;
if (size_type(last - first) <= size_type(MergeSortInsertionSortThreshold)) {
insertion_sort(first, last, comp);
}
else {
const size_type len = size_type(last - first) / 2u;
const RandIt middle = first + len;
if (len > ((buffer_size+1)/2)){
stable_sort_ONlogN_recursive(first, middle, buffer, buffer_size, comp);
stable_sort_ONlogN_recursive(middle, last, buffer, buffer_size, comp);
}
else{
merge_sort_with_constructed_buffer(first, middle, comp, buffer);
merge_sort_with_constructed_buffer(middle, last, comp, buffer);
}
merge_adaptive_ONlogN_recursive(first, middle, last,
size_type(middle - first),
size_type(last - middle),
buffer, buffer_size,
comp);
}
}
template<typename BidirectionalIterator, typename Compare, typename RandRawIt>
void stable_sort_adaptive_ONlogN2(BidirectionalIterator first,
BidirectionalIterator last,
Compare comp,
RandRawIt uninitialized,
std::size_t uninitialized_len)
{
typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
::boost::movelib::adaptive_xbuf<value_type, RandRawIt> xbuf(uninitialized, uninitialized_len);
xbuf.initialize_until(uninitialized_len, *first);
stable_sort_ONlogN_recursive(first, last, uninitialized, uninitialized_len, comp);
}
///@endcond
}} //namespace boost { namespace movelib{
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#include <boost/move/detail/config_end.hpp>
#endif //#ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP

View File

@@ -0,0 +1,344 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
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:: iter_size<Iter>::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:: iter_size<Iter>::type bad_allowed
, bool leftmost = true)
{
typedef typename boost::movelib:: iter_size<Iter>::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:: iter_size<Iter>::type size_type;
pdqsort_detail::pdqsort_loop<Iter, Compare>(begin, end, comp, pdqsort_detail::log2(size_type(end - begin)));
}
} //namespace movelib {
} //namespace boost {
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#include <boost/move/detail/config_end.hpp>
#endif //BOOST_MOVE_ALGO_PDQSORT_HPP

View File

@@ -0,0 +1,213 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
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 element in 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;
}
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
} //namespace movelib {
} //namespace boost {
#endif //#define BOOST_MOVE_SET_DIFFERENCE_HPP

View File

@@ -0,0 +1,160 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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/move/detail/addressof.hpp>
#include <boost/core/no_exceptions_support.hpp>
#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
#include <algorithm>
#endif
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

View File

@@ -0,0 +1,101 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
{
BOOST_MOVE_FORCEINLINE explicit antistable(Comp &comp)
: m_comp(comp)
{}
BOOST_MOVE_FORCEINLINE antistable(const antistable & other)
: m_comp(other.m_comp)
{}
template<class U, class V>
BOOST_MOVE_FORCEINLINE bool operator()(const U &u, const V & v)
{ return !m_comp(v, u); }
BOOST_MOVE_FORCEINLINE const Comp &get() const
{ return m_comp; }
private:
antistable & operator=(const antistable &);
Comp &m_comp;
};
template<class Comp>
Comp unantistable(Comp comp)
{ return comp; }
template<class Comp>
Comp unantistable(antistable<Comp> comp)
{ return comp.get(); }
template <class Comp>
class negate
{
public:
BOOST_MOVE_FORCEINLINE negate()
{}
BOOST_MOVE_FORCEINLINE explicit negate(Comp comp)
: m_comp(comp)
{}
template <class T1, class T2>
BOOST_MOVE_FORCEINLINE bool operator()(const T1& l, const T2& r)
{
return !m_comp(l, r);
}
private:
Comp m_comp;
};
template <class Comp>
class inverse
{
public:
BOOST_MOVE_FORCEINLINE inverse()
{}
BOOST_MOVE_FORCEINLINE explicit inverse(Comp comp)
: m_comp(comp)
{}
template <class T1, class T2>
BOOST_MOVE_FORCEINLINE 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

View File

@@ -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

View File

@@ -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/core/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

View File

@@ -0,0 +1,515 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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)
#define BOOST_MOVE_TO_LV_CAST(LV_TYPE, ARG) static_cast<LV_TYPE>(ARG)
//Move emulation rv breaks standard aliasing rules so add workarounds for some compilers
#if defined(BOOST_GCC) && (BOOST_GCC >= 40400) && (BOOST_GCC < 40500)
#define BOOST_RV_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
#else
#define BOOST_RV_ATTRIBUTE_MAY_ALIAS
#endif
namespace boost {
//////////////////////////////////////////////////////////////////////////////
//
// struct rv
//
//////////////////////////////////////////////////////////////////////////////
template <class T>
class BOOST_RV_ATTRIBUTE_MAY_ALIAS 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&);
};
//////////////////////////////////////////////////////////////////////////////
//
// 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;
}
template <class T>
BOOST_MOVE_FORCEINLINE T& unrv(::boost::rv<T> &rv) BOOST_NOEXCEPT
{ return BOOST_MOVE_TO_LV_CAST(T&, rv); }
} //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))
//
#define BOOST_MOVE_TO_LV(ARG) \
::boost::move_detail::unrv(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))
//
//!This macro is used to achieve portable optimal move constructors.
//!
//!In C++03 mode, when accessing a member of type through a rvalue (implemented as a `rv<T> &` type, where rv<T> derives
//!from T) triggers a potential UB as the program never creates objects of type rv<T>. This macro casts back `rv<T>` to
//!`T&` so that access to member types are done through the original type.
//!
//!In C++11 compilers the cast from a rvalue reference of a derived type to a rvalue reference of
//!a base type is implicit, so it's a no-op.
#define BOOST_MOVE_TO_LV(ARG) 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

View File

@@ -0,0 +1,244 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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;
}
template< class T, class U
, bool enable = def_del_compatible_cond< U, T>::value &&
!move_upmu::is_array<T>::value &&
!move_upmu::is_same<typename move_upmu::remove_cv<T>::type, void>::value &&
!move_upmu::is_same<typename move_upmu::remove_cv<U>::type, typename move_upmu::remove_cv<T>::type>::value
>
struct missing_virtual_destructor_default_delete
{ static const bool value = !move_upmu::has_virtual_destructor<T>::value; };
template<class T, class U>
struct missing_virtual_destructor_default_delete<T, U, false>
{ static const bool value = false; };
//////////////////////////////////////
// missing_virtual_destructor
//////////////////////////////////////
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_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(( !bmupd::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(( !bmupd::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(( !bmupd::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

View File

@@ -0,0 +1,61 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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_ADDRESSOF_HPP
#define BOOST_MOVE_DETAIL_ADDRESSOF_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 {
#if defined(BOOST_MSVC_FULL_VER) && BOOST_MSVC_FULL_VER >= 190024215
#define BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
#elif defined(BOOST_GCC) && BOOST_GCC >= 70000
#define BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
#elif defined(__has_builtin)
#if __has_builtin(__builtin_addressof)
#define BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
#endif
#endif
#ifdef BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
template<class T>
BOOST_MOVE_FORCEINLINE T *addressof( T & v ) BOOST_NOEXCEPT
{
return __builtin_addressof(v);
}
#else //BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
template <typename T>
BOOST_MOVE_FORCEINLINE T* addressof(T& obj)
{
return static_cast<T*>(
static_cast<void*>(
const_cast<char*>(
&reinterpret_cast<const volatile char&>(obj)
)));
}
#endif //BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
} //namespace move_detail {
} //namespace boost {
#endif //#ifndef BOOST_MOVE_DETAIL_ADDRESSOF_HPP

View File

@@ -0,0 +1,22 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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 : 4619) // there is no warning number 'XXXX'
# 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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,36 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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_FORCE_CAST_HPP
#define BOOST_MOVE_DETAIL_FORCE_CAST_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>
BOOST_MOVE_FORCEINLINE T force_ptr(const volatile void *p)
{
return static_cast<T>(const_cast<void*>(p));
}
} //namespace move_detail {
} //namespace boost {
#endif //#ifndef BOOST_MOVE_DETAIL_FORCE_CAST_HPP

View File

@@ -0,0 +1,893 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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_UREFANONN
#define BOOST_MOVE_UREFANON0
#define BOOST_MOVE_UREFANON1 BOOST_FWD_REF(P0)
#define BOOST_MOVE_UREFANON2 BOOST_MOVE_UREFANON1, BOOST_FWD_REF(P1)
#define BOOST_MOVE_UREFANON3 BOOST_MOVE_UREFANON2, BOOST_FWD_REF(P2)
#define BOOST_MOVE_UREFANON4 BOOST_MOVE_UREFANON3, BOOST_FWD_REF(P3)
#define BOOST_MOVE_UREFANON5 BOOST_MOVE_UREFANON4, BOOST_FWD_REF(P4)
#define BOOST_MOVE_UREFANON6 BOOST_MOVE_UREFANON5, BOOST_FWD_REF(P5)
#define BOOST_MOVE_UREFANON7 BOOST_MOVE_UREFANON6, BOOST_FWD_REF(P6)
#define BOOST_MOVE_UREFANON8 BOOST_MOVE_UREFANON7, BOOST_FWD_REF(P7)
#define BOOST_MOVE_UREFANON9 BOOST_MOVE_UREFANON8, BOOST_FWD_REF(P8)
//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

View File

@@ -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>
BOOST_MOVE_FORCEINLINE T* iterator_to_pointer(T* i)
{ return i; }
template <class Iterator>
BOOST_MOVE_FORCEINLINE 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>
BOOST_MOVE_FORCEINLINE 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

View File

@@ -0,0 +1,177 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
#if (BOOST_CXX_VERSION > 201703L) && defined(__cpp_lib_concepts)
#include <iterator>
#define BOOST_MOVE_CONTIGUOUS_ITERATOR_TAG
namespace boost {
namespace movelib {
using std::iterator_traits;
template<class T>
struct iter_difference
{
typedef typename std::iterator_traits<T>::difference_type type;
};
template<class T>
struct iter_value
{
typedef typename std::iterator_traits<T>::value_type type;
};
template<class T>
struct iter_category
{
typedef typename std::iterator_traits<T>::iterator_category type;
};
}} //namespace boost::movelib
#else
#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;
#if ( (defined(BOOST_GNU_STDLIB) && (__cplusplus > 201703L))\
|| (defined(_LIBCPP_VERSION) && (_LIBCPP_STD_VER > 17))\
|| (defined(_YVALS) && defined(_CPPLIB_VER) && defined(__cpp_lib_concepts))\
|| (__cplusplus >= 202002L)\
)
# define BOOST_MOVE_CONTIGUOUS_ITERATOR_TAG
struct contiguous_iterator_tag;
#endif
BOOST_MOVE_STD_NS_END
#include <boost/move/detail/std_ns_end.hpp>
namespace boost{ namespace movelib{
template<class T>
struct iter_difference
{
typedef typename T::difference_type type;
};
template<class T>
struct iter_difference<T*>
{
typedef std::ptrdiff_t type;
};
template<class T>
struct iter_value
{
typedef typename T::value_type type;
};
template<class T>
struct iter_value<T*>
{
typedef T type;
};
template<class T>
struct iter_value<const T*>
{
typedef T type;
};
template<class T>
struct iter_category
{
typedef typename T::iterator_category type;
};
template<class T>
struct iter_category<T*>
{
typedef std::random_access_iterator_tag type;
};
template<class Iterator>
struct iterator_traits
{
typedef typename iter_difference<Iterator>::type difference_type;
typedef typename iter_value<Iterator>::type value_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename iter_category<Iterator>::type iterator_category;
};
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;
};
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;
};
}} //namespace boost::movelib
#endif //
#include <boost/move/detail/type_traits.hpp>
namespace boost {
namespace movelib {
template<class T>
struct iter_size
: boost::move_detail::
make_unsigned<typename iter_difference<T>::type >
{};
}} //namespace boost move_detail {
#endif //#ifndef BOOST_MOVE_DETAIL_ITERATOR_TRAITS_HPP

View File

@@ -0,0 +1,559 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
#include <boost/move/detail/addressof.hpp>
//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{};
struct nat2{};
struct nat3{};
//////////////////////////////////////
// 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
//////////////////////////////////////
//////////////////////////////////////
// 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

View File

@@ -0,0 +1,137 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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 {
template<typename T>
struct voider { typedef void type; };
//////////////////////////////////////
// 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
//////////////////////////////////////
struct enable_if_nat{};
template <bool B, class T = enable_if_nat>
struct enable_if_c
{
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
//////////////////////////////////////
// enable_if
//////////////////////////////////////
template <class Cond, class T = enable_if_nat>
struct enable_if : enable_if_c<Cond::value, T> {};
//////////////////////////////////////
// disable_if_c
//////////////////////////////////////
template <bool B, class T = enable_if_nat>
struct disable_if_c
: enable_if_c<!B, T>
{};
//////////////////////////////////////
// disable_if
//////////////////////////////////////
template <class Cond, class T = enable_if_nat>
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 = enable_if_nat>
struct enable_if_same : enable_if<is_same<T, U>, R> {};
//////////////////////////////////////
// disable_if_same
//////////////////////////////////////
template <class T, class U, class R = enable_if_nat>
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

View File

@@ -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

View File

@@ -0,0 +1,227 @@
// This code is based on Timer and Chrono code. Thanks to authors:
//
// Boost.Timer:
// Copyright Beman Dawes 1994-2007, 2011
//
// Boost.Chrono:
// Copyright Beman Dawes 2008
// Copyright 2009-2010 Vicente J. Botet Escriba
//
// Simplified and modified to be able to support exceptionless (-fno-exceptions).
// Boost.Timer depends on Boost.Chorno wich uses boost::throw_exception.
// And Boost.Chrono DLLs don't build in Win32 as there is no
// boost::throw_exception(std::exception const&) implementation
// in Boost.Chrono:
//
// Copyright 2020 Ion Gaztanaga
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//----------------------------------------------------------------------------//
// Windows //
//----------------------------------------------------------------------------//
#ifndef BOOST_MOVE_DETAIL_NSEC_CLOCK_HPP
#define BOOST_MOVE_DETAIL_NSEC_CLOCK_HPP
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <cstdlib>
# if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
# define BOOST_MOVE_DETAIL_WINDOWS_API
# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define BOOST_MOVE_DETAIL_MAC_API
# else
# define BOOST_MOVE_DETAIL_POSIX_API
# endif
#if defined(BOOST_MOVE_DETAIL_WINDOWS_API)
#include <boost/winapi/time.hpp>
#include <boost/winapi/timers.hpp>
#include <boost/winapi/get_last_error.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/assert.hpp>
#include <boost/core/ignore_unused.hpp>
namespace boost { namespace move_detail {
template<int Dummy>
struct QPFHolder
{
static inline double get_nsec_per_tic()
{
boost::winapi::LARGE_INTEGER_ freq;
boost::winapi::BOOL_ r = boost::winapi::QueryPerformanceFrequency( &freq );
boost::ignore_unused(r);
BOOST_ASSERT(r != 0 && "Boost::Move - get_nanosecs_per_tic Internal Error");
return double(1000000000.0L / freq.QuadPart);
}
static const double nanosecs_per_tic;
};
template<int Dummy>
const double QPFHolder<Dummy>::nanosecs_per_tic = get_nsec_per_tic();
inline boost::uint64_t nsec_clock() BOOST_NOEXCEPT
{
double nanosecs_per_tic = QPFHolder<0>::nanosecs_per_tic;
boost::winapi::LARGE_INTEGER_ pcount;
unsigned times=0;
while ( !boost::winapi::QueryPerformanceCounter( &pcount ) )
{
if ( ++times > 3 )
{
BOOST_ASSERT("Boost::Move - QueryPerformanceCounter Internal Error");
return 0u;
}
}
return static_cast<boost::uint64_t>(nanosecs_per_tic * double(pcount.QuadPart));
}
}} //namespace boost { namespace move_detail {
#elif defined(BOOST_MOVE_DETAIL_MAC_API)
#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
inline boost::uint64_t nsec_clock() BOOST_NOEXCEPT
{
boost::uint64_t count = ::mach_absolute_time();
mach_timebase_info_data_t info;
mach_timebase_info(&info);
return static_cast<boost::uint64_t>
( static_cast<double>(count)*(static_cast<double>(info.numer) / info.denom) );
}
#elif defined(BOOST_MOVE_DETAIL_POSIX_API)
#include <time.h>
# if defined(CLOCK_MONOTONIC_PRECISE) //BSD
# define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
# elif defined(CLOCK_MONOTONIC_RAW) //Linux
# define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
# elif defined(CLOCK_HIGHRES) //Solaris
# define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_HIGHRES
# elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris)
# define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_MONOTONIC
# else
# error "No high resolution steady clock in your system, please provide a patch"
# endif
inline boost::uint64_t nsec_clock() BOOST_NOEXCEPT
{
struct timespec count;
::clock_gettime(BOOST_MOVE_DETAIL_CLOCK_MONOTONIC, &count);
boost::uint64_t r = static_cast<boost::uint64_t>(count.tv_sec);
r *= 1000000000U;
r += static_cast<boost::uint64_t>(count.tv_nsec);
return r;
}
#endif // POSIX
namespace boost { namespace move_detail {
typedef boost::uint64_t nanosecond_type;
struct cpu_times
{
nanosecond_type wall;
nanosecond_type user;
nanosecond_type system;
void clear() { wall = user = system = 0; }
cpu_times()
{ this->clear(); }
};
inline void get_cpu_times(boost::move_detail::cpu_times& current)
{
current.wall = nsec_clock();
}
class cpu_timer
{
public:
// constructor
cpu_timer() BOOST_NOEXCEPT { start(); }
// observers
bool is_stopped() const BOOST_NOEXCEPT { return m_is_stopped; }
cpu_times elapsed() const BOOST_NOEXCEPT; // does not stop()
// actions
void start() BOOST_NOEXCEPT;
void stop() BOOST_NOEXCEPT;
void resume() BOOST_NOEXCEPT;
private:
cpu_times m_times;
bool m_is_stopped;
};
// cpu_timer ---------------------------------------------------------------------//
inline void cpu_timer::start() BOOST_NOEXCEPT
{
m_is_stopped = false;
get_cpu_times(m_times);
}
inline void cpu_timer::stop() BOOST_NOEXCEPT
{
if (is_stopped())
return;
m_is_stopped = true;
cpu_times current;
get_cpu_times(current);
m_times.wall = (current.wall - m_times.wall);
m_times.user = (current.user - m_times.user);
m_times.system = (current.system - m_times.system);
}
inline cpu_times cpu_timer::elapsed() const BOOST_NOEXCEPT
{
if (is_stopped())
return m_times;
cpu_times current;
get_cpu_times(current);
current.wall -= m_times.wall;
current.user -= m_times.user;
current.system -= m_times.system;
return current;
}
inline void cpu_timer::resume() BOOST_NOEXCEPT
{
if (is_stopped())
{
cpu_times current (m_times);
start();
m_times.wall -= current.wall;
m_times.user -= current.user;
m_times.system -= current.system;
}
}
} // namespace move_detail
} // namespace boost
#endif //BOOST_MOVE_DETAIL_NSEC_CLOCK_HPP

View File

@@ -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

View File

@@ -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)

View File

@@ -0,0 +1,178 @@
/////////////////////////////////////////////////////////////////////////////
//
// (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 I>
BOOST_MOVE_FORCEINLINE typename iterator_traits<I>::pointer iterator_arrow_result(const I &i)
{ return i.operator->(); }
template<class T>
BOOST_MOVE_FORCEINLINE T * iterator_arrow_result(T *p)
{ return p; }
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;
BOOST_MOVE_FORCEINLINE reverse_iterator()
: m_current() //Value initialization to achieve "null iterators" (N3644)
{}
BOOST_MOVE_FORCEINLINE explicit reverse_iterator(It r)
: m_current(r)
{}
BOOST_MOVE_FORCEINLINE reverse_iterator(const reverse_iterator& r)
: m_current(r.base())
{}
template<class OtherIt>
BOOST_MOVE_FORCEINLINE
reverse_iterator( const reverse_iterator<OtherIt>& r
, typename boost::move_detail::enable_if_convertible<OtherIt, It>::type* =0
)
: m_current(r.base())
{}
BOOST_MOVE_FORCEINLINE reverse_iterator & operator=( const reverse_iterator& r)
{ m_current = r.base(); return *this; }
template<class OtherIt>
BOOST_MOVE_FORCEINLINE typename boost::move_detail::enable_if_convertible<OtherIt, It, reverse_iterator &>::type
operator=( const reverse_iterator<OtherIt>& r)
{ m_current = r.base(); return *this; }
BOOST_MOVE_FORCEINLINE It base() const
{ return m_current; }
BOOST_MOVE_FORCEINLINE reference operator*() const
{
It temp(m_current);
--temp;
reference r = *temp;
return r;
}
BOOST_MOVE_FORCEINLINE pointer operator->() const
{
It temp(m_current);
--temp;
return (iterator_arrow_result)(temp);
}
BOOST_MOVE_FORCEINLINE reference operator[](difference_type off) const
{
return this->m_current[difference_type(-off - 1)];
}
BOOST_MOVE_FORCEINLINE reverse_iterator& operator++()
{
--m_current;
return *this;
}
BOOST_MOVE_FORCEINLINE reverse_iterator operator++(int)
{
reverse_iterator temp((*this));
--m_current;
return temp;
}
BOOST_MOVE_FORCEINLINE reverse_iterator& operator--()
{
++m_current;
return *this;
}
BOOST_MOVE_FORCEINLINE reverse_iterator operator--(int)
{
reverse_iterator temp((*this));
++m_current;
return temp;
}
BOOST_MOVE_FORCEINLINE friend bool operator==(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current == r.m_current; }
BOOST_MOVE_FORCEINLINE friend bool operator!=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current != r.m_current; }
BOOST_MOVE_FORCEINLINE friend bool operator<(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current > r.m_current; }
BOOST_MOVE_FORCEINLINE friend bool operator<=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current >= r.m_current; }
BOOST_MOVE_FORCEINLINE friend bool operator>(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current < r.m_current; }
BOOST_MOVE_FORCEINLINE friend bool operator>=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current <= r.m_current; }
BOOST_MOVE_FORCEINLINE reverse_iterator& operator+=(difference_type off)
{ m_current -= off; return *this; }
BOOST_MOVE_FORCEINLINE reverse_iterator& operator-=(difference_type off)
{ m_current += off; return *this; }
BOOST_MOVE_FORCEINLINE friend reverse_iterator operator+(reverse_iterator l, difference_type off)
{ return (l += off); }
BOOST_MOVE_FORCEINLINE friend reverse_iterator operator+(difference_type off, reverse_iterator r)
{ return (r += off); }
BOOST_MOVE_FORCEINLINE friend reverse_iterator operator-(reverse_iterator l, difference_type off)
{ return (l-= off); }
BOOST_MOVE_FORCEINLINE 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 >
BOOST_MOVE_FORCEINLINE 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

View File

@@ -0,0 +1,34 @@
#//////////////////////////////////////////////////////////////////////////////
#//
#// (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
#if defined(_MSC_VER) && (_MSC_VER >= 1915)
#pragma warning (push)
#pragma warning (disable : 4643) // Forward declaring 'X' in namespace std is not permitted by the C++ Standard
#endif
#define BOOST_MOVE_STD_NS_BEG namespace std{
#define BOOST_MOVE_STD_NS_END }
#endif

View File

@@ -0,0 +1,16 @@
#//////////////////////////////////////////////////////////////////////////////
#//
#// (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
#elif defined(_MSC_VER) && (_MSC_VER >= 1915)
#pragma warning (pop)
#endif //BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,565 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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(BOOST_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
} //namespace move_upmu {
} //namespace boost {
#endif //#ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP

View File

@@ -0,0 +1,71 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
//#define BOOST_MOVE_DISABLE_FORCEINLINE
#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) && (_MSC_VER < 1900 || defined(_DEBUG))
//"__forceinline" and MSVC seems to have some bugs in old versions and in debug mode
#define BOOST_MOVE_FORCEINLINE inline
#elif defined(BOOST_GCC) && (__GNUC__ <= 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

View File

@@ -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>
BOOST_MOVE_FORCEINLINE 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

View File

@@ -0,0 +1,248 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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)
#if defined(_MSC_VER) && (_MSC_VER >= 1915)
#pragma warning (push)
#pragma warning (disable : 4643) // Forward declaring 'X' in namespace std is not permitted by the C++ Standard
#endif
namespace std { //no namespace versioning in clang+libc++
struct nothrow_t;
} //namespace std {
#if defined(_MSC_VER) && (_MSC_VER >= 1915)
#pragma warning (pop)
#endif
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

View File

@@ -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

View File

@@ -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 &lt;T&gt;::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

View File

@@ -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(( !bmupd::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(( !bmupd::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(( !bmupd::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(( !bmupd::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(( !bmupd::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

View File

@@ -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

View File

@@ -0,0 +1,321 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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
} //namespace boost {
#endif //BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
//////////////////////////////////////////////////////////////////////////////
//
// move_if_not_lvalue_reference
//
//////////////////////////////////////////////////////////////////////////////
namespace boost {
#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 //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

View File

@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,4 @@
The package boost is compatible with built-in CMake targets:
find_package(Boost REQUIRED [COMPONENTS <libs>...])
target_link_libraries(main PRIVATE Boost::boost Boost::<lib1> Boost::<lib2> ...)

View File

@@ -0,0 +1,115 @@
{
"$schema": "https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.1/schemas/spdx-schema.json",
"spdxVersion": "SPDX-2.2",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"documentNamespace": "https://spdx.org/spdxdocs/boost-move-x64-windows-1.79.0-2dfd9217-652b-48ee-8e3d-45d80bfb81c5",
"name": "boost-move:x64-windows@1.79.0 c41e7bcb3cbb57100f8b9da78c55dca8017a976ac084f3a13c28135622927a0b",
"creationInfo": {
"creators": [
"Tool: vcpkg-9268e366206712e38102b28dbd1617697a99ff2e"
],
"created": "2022-07-23T08:22:06Z"
},
"relationships": [
{
"spdxElementId": "SPDXRef-port",
"relationshipType": "GENERATES",
"relatedSpdxElement": "SPDXRef-binary"
},
{
"spdxElementId": "SPDXRef-port",
"relationshipType": "CONTAINS",
"relatedSpdxElement": "SPDXRef-file-0"
},
{
"spdxElementId": "SPDXRef-port",
"relationshipType": "CONTAINS",
"relatedSpdxElement": "SPDXRef-file-1"
},
{
"spdxElementId": "SPDXRef-binary",
"relationshipType": "GENERATED_FROM",
"relatedSpdxElement": "SPDXRef-port"
},
{
"spdxElementId": "SPDXRef-file-0",
"relationshipType": "CONTAINED_BY",
"relatedSpdxElement": "SPDXRef-port"
},
{
"spdxElementId": "SPDXRef-file-1",
"relationshipType": "CONTAINED_BY",
"relatedSpdxElement": "SPDXRef-port"
},
{
"spdxElementId": "SPDXRef-file-1",
"relationshipType": "DEPENDENCY_MANIFEST_OF",
"relatedSpdxElement": "SPDXRef-port"
}
],
"packages": [
{
"name": "boost-move",
"SPDXID": "SPDXRef-port",
"versionInfo": "1.79.0",
"downloadLocation": "NOASSERTION",
"homepage": "https://github.com/boostorg/move",
"licenseConcluded": "BSL-1.0",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"description": "Boost move module",
"comment": "This is the port (recipe) consumed by vcpkg."
},
{
"name": "boost-move:x64-windows",
"SPDXID": "SPDXRef-binary",
"versionInfo": "c41e7bcb3cbb57100f8b9da78c55dca8017a976ac084f3a13c28135622927a0b",
"downloadLocation": "NONE",
"licenseConcluded": "BSL-1.0",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"comment": "This is a binary package built by vcpkg."
},
{
"SPDXID": "SPDXRef-resource-1",
"name": "boostorg/move",
"downloadLocation": "git+https://github.com/boostorg/move@boost-1.79.0",
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"checksums": [
{
"algorithm": "SHA512",
"checksumValue": "1c62ca4673ca70dd1334ac6380f74db2f3827631d1419f658461bd4ab22a81406a2b1229adf48f92cf827a627e1997409c9911d8bc9ed6a5d5ac320127818fb0"
}
]
}
],
"files": [
{
"fileName": "./portfile.cmake",
"SPDXID": "SPDXRef-file-0",
"checksums": [
{
"algorithm": "SHA256",
"checksumValue": "375fbf4ef0f6bdd453d422048c17c4d9fcb4e04d89964e7a35a53c58fbeb0466"
}
],
"licenseConcluded": "NOASSERTION",
"copyrightText": "NOASSERTION"
},
{
"fileName": "./vcpkg.json",
"SPDXID": "SPDXRef-file-1",
"checksums": [
{
"algorithm": "SHA256",
"checksumValue": "9c64621fc895735b365b93a0022291e1e3046fc058dbc7049eeafd6163f8f5a6"
}
],
"licenseConcluded": "NOASSERTION",
"copyrightText": "NOASSERTION"
}
]
}

View File

@@ -0,0 +1,17 @@
boost-assert a50eed453b8be6c8932fb3d5f8feaf194a2ebeaed7982db4e36e3ba17f3ec107
boost-config 797535e8975ed7cf5bbe11d9f7fe26caa5da8fe819888564758d82a21109fade
boost-core 498aea0b6b68bcfe1ec683e76c2f0d32477dfe9ba958f518980ff806b6faba90
boost-static-assert 795e87a155fce50821163bc84e802f28dce54e4af6a3a86045f9ecec76ad4c95
boost-vcpkg-helpers c81c7b003df356a1a120a7c0c2f5a2ac95f3c33b006a2a5b4c02dcf0c9f3deaa
boost-winapi e3a25230fe97591ec7dbff1bfe0e2db388523e993305526811adef219f215c5a
cmake 3.23.2
features core
portfile.cmake 375fbf4ef0f6bdd453d422048c17c4d9fcb4e04d89964e7a35a53c58fbeb0466
ports.cmake 366c60b768113102408b32ac1d7c7b48ef7d30a477af2a220ecc222d9ffa3166
post_build_checks 2
powershell 7.2.5
triplet x64-windows
triplet_abi 4556164a2cd3dd6f4742101eabb46def7e71b6e5856faa88e5d005aac12a803c-c0600b35e024ce0485ed253ef5419f3686f7257cfb58cb6a24febcb600fc4b4c-27ebd443f77a6c449168adfa6ce8def60cf46e88
vcpkg.json 9c64621fc895735b365b93a0022291e1e3046fc058dbc7049eeafd6163f8f5a6
vcpkg_from_git 0aab20e34e84d52ba4763f009e539bfa8f418c41c918c8cf700156f1a8551a10
vcpkg_from_github b743742296a114ea1b18ae99672e02f142c4eb2bef7f57d36c038bedbfb0502f