整理
This commit is contained in:
274
include/boost/move/adl_move_swap.hpp
Normal file
274
include/boost/move/adl_move_swap.hpp
Normal file
@@ -0,0 +1,274 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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) && (_LIBCPP_VERSION >= 13000)
|
||||
#include <__utility/swap.h> //libc++ refactored <utility> headers in smaller headers
|
||||
#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>
|
||||
inline 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>
|
||||
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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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
|
||||
365
include/boost/move/algo/adaptive_merge.hpp
Normal file
365
include/boost/move/algo/adaptive_merge.hpp
Normal file
@@ -0,0 +1,365 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
#include <cassert>
|
||||
|
||||
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#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);
|
||||
}
|
||||
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);
|
||||
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);
|
||||
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
|
||||
655
include/boost/move/algo/adaptive_sort.hpp
Normal file
655
include/boost/move/algo/adaptive_sort.hpp
Normal file
@@ -0,0 +1,655 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 <cassert>
|
||||
|
||||
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#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;
|
||||
assert(l_build_buf <= len);
|
||||
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;
|
||||
|
||||
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());
|
||||
|
||||
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::movelib::ignore(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::movelib::ignore(l_total_combined);
|
||||
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);
|
||||
assert(!l_intbuf || (l_block == l_intbuf));
|
||||
assert(n == 0 || (!use_internal_buf || prev_use_internal_buf) );
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
//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;
|
||||
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{
|
||||
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;
|
||||
}
|
||||
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_MOVE_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{
|
||||
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
|
||||
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
|
||||
1523
include/boost/move/algo/detail/adaptive_sort_merge.hpp
Normal file
1523
include/boost/move/algo/detail/adaptive_sort_merge.hpp
Normal file
File diff suppressed because it is too large
Load Diff
122
include/boost/move/algo/detail/basic_op.hpp
Normal file
122
include/boost/move/algo/detail/basic_op.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
#include <boost/move/algo/move.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>
|
||||
inline void operator()(SourceIt source, DestinationIt dest)
|
||||
{ *dest = ::boost::move(*source); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
inline DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
|
||||
{ return ::boost::move(first, last, dest_begin); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline void operator()(SourceIt source, DestinationIt dest)
|
||||
{ boost::adl_move_swap(*dest, *source); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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
|
||||
122
include/boost/move/algo/detail/heap_sort.hpp
Normal file
122
include/boost/move/algo/detail/heap_sort.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
#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{
|
||||
|
||||
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);
|
||||
assert(boost::movelib::is_sorted(first, last, comp));
|
||||
}
|
||||
};
|
||||
|
||||
template <class RandomAccessIterator, class Compare>
|
||||
inline 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
|
||||
137
include/boost/move/algo/detail/insertion_sort.hpp
Normal file
137
include/boost/move/algo/detail/insertion_sort.hpp
Normal 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
|
||||
55
include/boost/move/algo/detail/is_sorted.hpp
Normal file
55
include/boost/move/algo/detail/is_sorted.hpp
Normal 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
|
||||
896
include/boost/move/algo/detail/merge.hpp
Normal file
896
include/boost/move/algo/detail/merge.hpp
Normal file
@@ -0,0 +1,896 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_MOVE_MERGE_HPP
|
||||
#define BOOST_MOVE_MERGE_HPP
|
||||
|
||||
#include <boost/move/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/algo/detail/search.hpp>
|
||||
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
|
||||
#include <cassert>
|
||||
#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;
|
||||
|
||||
inline adaptive_xbuf()
|
||||
: m_ptr(), m_size(0), m_capacity(0)
|
||||
{}
|
||||
|
||||
inline 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
inline 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)
|
||||
{
|
||||
assert(m_size < m_capacity);
|
||||
if(m_size < sz){
|
||||
BOOST_MOVE_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_MOVE_CATCH(...)
|
||||
{
|
||||
while(m_size)
|
||||
{
|
||||
--m_size;
|
||||
m_ptr[m_size].~T();
|
||||
}
|
||||
}
|
||||
BOOST_MOVE_CATCH_END
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<class RIt>
|
||||
inline static bool is_raw_ptr(RIt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline 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>
|
||||
inline U *aligned_trailing() const
|
||||
{
|
||||
return this->aligned_trailing<U>(this->size());
|
||||
}
|
||||
|
||||
template<class U>
|
||||
inline 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;
|
||||
}
|
||||
|
||||
inline ~adaptive_xbuf()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
inline size_type capacity() const
|
||||
{ return m_capacity; }
|
||||
|
||||
inline iterator data() const
|
||||
{ return m_ptr; }
|
||||
|
||||
inline iterator begin() const
|
||||
{ return m_ptr; }
|
||||
|
||||
inline iterator end() const
|
||||
{ return m_ptr+m_size; }
|
||||
|
||||
inline size_type size() const
|
||||
{ return m_size; }
|
||||
|
||||
inline bool empty() const
|
||||
{ return !m_size; }
|
||||
|
||||
inline 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)
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
assert((last - first) == (r_first - dest_first));
|
||||
while ( first != last ) {
|
||||
if (r_first == r_last) {
|
||||
InputOutIterator end = op(forward_t(), first, last, dest_first);
|
||||
assert(end == r_last);
|
||||
boost::movelib::ignore(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)
|
||||
{
|
||||
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);
|
||||
assert(last == res);
|
||||
boost::movelib::ignore(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)
|
||||
{
|
||||
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);
|
||||
assert(end == r_last);
|
||||
boost::movelib::ignore(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
|
||||
216
include/boost/move/algo/detail/merge_sort.hpp
Normal file
216
include/boost/move/algo/detail/merge_sort.hpp
Normal 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
|
||||
345
include/boost/move/algo/detail/pdqsort.hpp
Normal file
345
include/boost/move/algo/detail/pdqsort.hpp
Normal file
@@ -0,0 +1,345 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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;
|
||||
if(begin != pivot_pos) //Avoid potential self-move
|
||||
*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
|
||||
79
include/boost/move/algo/detail/search.hpp
Normal file
79
include/boost/move/algo/detail/search.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2022-2022.
|
||||
// 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_SEARCH_HPP
|
||||
#define BOOST_MOVE_DETAIL_SEARCH_HPP
|
||||
|
||||
#include <boost/move/detail/iterator_traits.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 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;
|
||||
}
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif //#define BOOST_MOVE_DETAIL_SEARCH_HPP
|
||||
213
include/boost/move/algo/detail/set_difference.hpp
Normal file
213
include/boost/move/algo/detail/set_difference.hpp
Normal 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
|
||||
159
include/boost/move/algo/move.hpp
Normal file
159
include/boost/move/algo/move.hpp
Normal file
@@ -0,0 +1,159 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
#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_MOVE_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_MOVE_CATCH(...){
|
||||
for (; back != r; ++back){
|
||||
boost::movelib::iterator_to_raw_pointer(back)->~input_value_type();
|
||||
}
|
||||
BOOST_MOVE_RETHROW;
|
||||
}
|
||||
BOOST_MOVE_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
|
||||
101
include/boost/move/algo/predicate.hpp
Normal file
101
include/boost/move/algo/predicate.hpp
Normal 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 <cassert>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
template<class Comp>
|
||||
struct antistable
|
||||
{
|
||||
inline explicit antistable(Comp &comp)
|
||||
: m_comp(comp)
|
||||
{}
|
||||
|
||||
inline antistable(const antistable & other)
|
||||
: m_comp(other.m_comp)
|
||||
{}
|
||||
|
||||
template<class U, class V>
|
||||
inline bool operator()(const U &u, const V & v)
|
||||
{ return !m_comp(v, u); }
|
||||
|
||||
inline 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:
|
||||
inline negate()
|
||||
{}
|
||||
|
||||
inline explicit negate(Comp comp)
|
||||
: m_comp(comp)
|
||||
{}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator()(const T1& l, const T2& r)
|
||||
{
|
||||
return !m_comp(l, r);
|
||||
}
|
||||
|
||||
private:
|
||||
Comp m_comp;
|
||||
};
|
||||
|
||||
|
||||
template <class Comp>
|
||||
class inverse
|
||||
{
|
||||
public:
|
||||
inline inverse()
|
||||
{}
|
||||
|
||||
inline explicit inverse(Comp comp)
|
||||
: m_comp(comp)
|
||||
{}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline 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
|
||||
55
include/boost/move/algo/unique.hpp
Normal file
55
include/boost/move/algo/unique.hpp
Normal 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
|
||||
166
include/boost/move/algorithm.hpp
Normal file
166
include/boost/move/algorithm.hpp
Normal file
@@ -0,0 +1,166 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 <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
|
||||
515
include/boost/move/core.hpp
Normal file
515
include/boost/move/core.hpp
Normal 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_core.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
|
||||
243
include/boost/move/default_delete.hpp
Normal file
243
include/boost/move/default_delete.hpp
Normal file
@@ -0,0 +1,243 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 <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_MOVE_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_MOVE_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_MOVE_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_MOVE_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_MOVE_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
|
||||
61
include/boost/move/detail/addressof.hpp
Normal file
61
include/boost/move/detail/addressof.hpp
Normal 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
|
||||
21
include/boost/move/detail/config_begin.hpp
Normal file
21
include/boost/move/detail/config_begin.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable : 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 : 4714) // "function": marked as __forceinline not inlined
|
||||
# pragma warning (disable : 4127) // conditional expression is constant
|
||||
#endif
|
||||
12
include/boost/move/detail/config_end.hpp
Normal file
12
include/boost/move/detail/config_end.hpp
Normal 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
|
||||
66
include/boost/move/detail/destruct_n.hpp
Normal file
66
include/boost/move/detail/destruct_n.hpp
Normal 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
|
||||
36
include/boost/move/detail/force_ptr.hpp
Normal file
36
include/boost/move/detail/force_ptr.hpp
Normal 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
|
||||
893
include/boost/move/detail/fwd_macros.hpp
Normal file
893
include/boost/move/detail/fwd_macros.hpp
Normal 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
|
||||
59
include/boost/move/detail/iterator_to_raw_pointer.hpp
Normal file
59
include/boost/move/detail/iterator_to_raw_pointer.hpp
Normal 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>
|
||||
inline typename boost::movelib::iterator_traits<Iterator>::pointer
|
||||
iterator_to_pointer(const Iterator &i)
|
||||
{ return i.operator->(); }
|
||||
|
||||
template <class Iterator>
|
||||
struct iterator_to_element_ptr
|
||||
{
|
||||
typedef typename boost::movelib::iterator_traits<Iterator>::pointer pointer;
|
||||
typedef typename boost::movelib::pointer_element<pointer>::type element_type;
|
||||
typedef element_type* type;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
template <class Iterator>
|
||||
inline typename boost::movelib::detail::iterator_to_element_ptr<Iterator>::type
|
||||
iterator_to_raw_pointer(const Iterator &i)
|
||||
{
|
||||
return ::boost::movelib::to_raw_pointer
|
||||
( ::boost::movelib::detail::iterator_to_pointer(i) );
|
||||
}
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
|
||||
177
include/boost/move/detail/iterator_traits.hpp
Normal file
177
include/boost/move/detail/iterator_traits.hpp
Normal 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
|
||||
53
include/boost/move/detail/launder.hpp
Normal file
53
include/boost/move/detail/launder.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_LAUNDER_HPP
|
||||
#define BOOST_MOVE_DETAIL_LAUNDER_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_MOVE_HAS_BUILTIN_LAUNDER)
|
||||
|
||||
template<class T>
|
||||
BOOST_MOVE_FORCEINLINE T* launder(T* p)
|
||||
{
|
||||
return __builtin_launder( p );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<class T>
|
||||
BOOST_MOVE_FORCEINLINE T* launder(T* p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
BOOST_MOVE_FORCEINLINE T launder_cast(const volatile void* p)
|
||||
{
|
||||
return (launder)(static_cast<T>(const_cast<void*>(p)));
|
||||
}
|
||||
|
||||
} //namespace move_detail {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_LAUNDER_HPP
|
||||
544
include/boost/move/detail/meta_utils.hpp
Normal file
544
include/boost/move/detail/meta_utils.hpp
Normal file
@@ -0,0 +1,544 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/workaround.hpp> //forceinline
|
||||
#include <boost/move/detail/meta_utils_core.hpp>
|
||||
#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_>
|
||||
{
|
||||
inline operator bool() const { return C_; }
|
||||
inline bool operator()() const { return C_; }
|
||||
};
|
||||
|
||||
typedef bool_<true> true_;
|
||||
typedef bool_<false> false_;
|
||||
|
||||
//////////////////////////////////////
|
||||
// nat
|
||||
//////////////////////////////////////
|
||||
struct nat{};
|
||||
struct nat2{};
|
||||
struct nat3{};
|
||||
|
||||
template <unsigned N>
|
||||
struct natN
|
||||
{};
|
||||
|
||||
//////////////////////////////////////
|
||||
// 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;
|
||||
};
|
||||
|
||||
//////////////////////////////////////
|
||||
// identity
|
||||
//////////////////////////////////////
|
||||
template <class T>
|
||||
struct identity
|
||||
{
|
||||
typedef T type;
|
||||
typedef typename add_const_lvalue_reference<T>::type reference;
|
||||
BOOST_MOVE_FORCEINLINE reference operator()(reference t) const
|
||||
{ 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 {
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
|
||||
152
include/boost/move/detail/meta_utils_core.hpp
Normal file
152
include/boost/move/detail/meta_utils_core.hpp
Normal file
@@ -0,0 +1,152 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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> {};
|
||||
|
||||
//////////////////////////////////////
|
||||
// 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;
|
||||
};
|
||||
|
||||
} //namespace move_detail {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_CORE_HPP
|
||||
256
include/boost/move/detail/move_helpers.hpp
Normal file
256
include/boost/move/detail/move_helpers.hpp
Normal 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)\
|
||||
inline RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
|
||||
{ return FWD_FUNCTION(static_cast<const TYPE&>(x)); }\
|
||||
\
|
||||
inline RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
|
||||
{ return FWD_FUNCTION(::boost::move(x)); }\
|
||||
\
|
||||
inline 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>\
|
||||
inline 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>\
|
||||
inline 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>\
|
||||
inline 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>\
|
||||
inline 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)\
|
||||
inline RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
|
||||
{ return FWD_FUNCTION(static_cast<const TYPE&>(x)); }\
|
||||
\
|
||||
inline RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
|
||||
{ return FWD_FUNCTION(::boost::move(x)); }\
|
||||
\
|
||||
template<class BOOST_MOVE_TEMPL_PARAM>\
|
||||
inline 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)\
|
||||
inline RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
|
||||
{ return FWD_FUNCTION(x); }\
|
||||
\
|
||||
inline 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)\
|
||||
inline RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
|
||||
{ return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
|
||||
\
|
||||
inline RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
|
||||
{ return FWD_FUNCTION(arg1, ::boost::move(x)); }\
|
||||
\
|
||||
inline 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>\
|
||||
inline 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>\
|
||||
inline 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>\
|
||||
inline 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>\
|
||||
inline 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)\
|
||||
inline RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
|
||||
{ return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
|
||||
\
|
||||
inline 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>\
|
||||
inline 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)\
|
||||
inline RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
|
||||
{ return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
|
||||
\
|
||||
inline 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
|
||||
268
include/boost/move/detail/nsec_clock.hpp
Normal file
268
include/boost/move/detail/nsec_clock.hpp
Normal file
@@ -0,0 +1,268 @@
|
||||
// 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 <boost/move/detail/workaround.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 <cassert>
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
#include <windows.h>
|
||||
#else
|
||||
|
||||
#if defined (WIN32_PLATFORM_PSPC)
|
||||
#define BOOST_MOVE_WINAPI_IMPORT BOOST_SYMBOL_IMPORT
|
||||
#define BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM
|
||||
#elif defined (_WIN32_WCE)
|
||||
#define BOOST_MOVE_WINAPI_IMPORT
|
||||
#define BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM
|
||||
#else
|
||||
#define BOOST_MOVE_WINAPI_IMPORT BOOST_SYMBOL_IMPORT
|
||||
#define BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM BOOST_SYMBOL_IMPORT
|
||||
#endif
|
||||
|
||||
#if defined(WINAPI)
|
||||
#define BOOST_MOVE_WINAPI_CC WINAPI
|
||||
#else
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
#define BOOST_MOVE_WINAPI_CC __stdcall
|
||||
#else
|
||||
// On architectures other than 32-bit x86 __stdcall is ignored. Clang also issues a warning.
|
||||
#define BOOST_MOVE_WINAPI_CC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
union _LARGE_INTEGER;
|
||||
typedef long long QuadPart;
|
||||
|
||||
BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM int BOOST_MOVE_WINAPI_CC
|
||||
QueryPerformanceCounter(::_LARGE_INTEGER* lpPerformanceCount);
|
||||
|
||||
BOOST_MOVE_WINAPI_IMPORT_EXCEPT_WM int BOOST_MOVE_WINAPI_CC
|
||||
QueryPerformanceFrequency(::_LARGE_INTEGER* lpFrequency);
|
||||
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace move_detail {
|
||||
|
||||
BOOST_FORCEINLINE int QueryPerformanceCounter(long long* lpPerformanceCount)
|
||||
{
|
||||
return ::QueryPerformanceCounter(reinterpret_cast< ::_LARGE_INTEGER* >(lpPerformanceCount));
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE int QueryPerformanceFrequency(long long* lpFrequency)
|
||||
{
|
||||
return ::QueryPerformanceFrequency(reinterpret_cast< ::_LARGE_INTEGER* >(lpFrequency));
|
||||
}
|
||||
|
||||
|
||||
template<int Dummy>
|
||||
struct QPFHolder
|
||||
{
|
||||
static inline double get_nsec_per_tic()
|
||||
{
|
||||
long long freq;
|
||||
//According to MS documentation:
|
||||
//"On systems that run Windows XP or later, the function will always succeed and will thus never return zero"
|
||||
(void)boost::move_detail::QueryPerformanceFrequency(&freq);
|
||||
return double(1000000000.0L / double(freq));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
long long pcount;
|
||||
//According to MS documentation:
|
||||
//"On systems that run Windows XP or later, the function will always succeed and will thus never return zero"
|
||||
(void)boost::move_detail::QueryPerformanceCounter( &pcount );
|
||||
return static_cast<boost::uint64_t>(nanosecs_per_tic * double(pcount));
|
||||
}
|
||||
|
||||
}} //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
|
||||
32
include/boost/move/detail/placement_new.hpp
Normal file
32
include/boost/move/detail/placement_new.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#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
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
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
|
||||
168
include/boost/move/detail/pointer_element.hpp
Normal file
168
include/boost/move/detail/pointer_element.hpp
Normal 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)
|
||||
178
include/boost/move/detail/reverse_iterator.hpp
Normal file
178
include/boost/move/detail/reverse_iterator.hpp
Normal 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>
|
||||
inline 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;
|
||||
|
||||
inline reverse_iterator()
|
||||
: m_current() //Value initialization to achieve "null iterators" (N3644)
|
||||
{}
|
||||
|
||||
inline explicit reverse_iterator(It r)
|
||||
: m_current(r)
|
||||
{}
|
||||
|
||||
inline reverse_iterator(const reverse_iterator& r)
|
||||
: m_current(r.base())
|
||||
{}
|
||||
|
||||
template<class OtherIt>
|
||||
inline
|
||||
reverse_iterator( const reverse_iterator<OtherIt>& r
|
||||
, typename boost::move_detail::enable_if_convertible<OtherIt, It>::type* =0
|
||||
)
|
||||
: m_current(r.base())
|
||||
{}
|
||||
|
||||
inline reverse_iterator & operator=( const reverse_iterator& r)
|
||||
{ m_current = r.base(); return *this; }
|
||||
|
||||
template<class OtherIt>
|
||||
inline typename boost::move_detail::enable_if_convertible<OtherIt, It, reverse_iterator &>::type
|
||||
operator=( const reverse_iterator<OtherIt>& r)
|
||||
{ m_current = r.base(); return *this; }
|
||||
|
||||
inline It base() const
|
||||
{ return m_current; }
|
||||
|
||||
inline reference operator*() const
|
||||
{
|
||||
It temp(m_current);
|
||||
--temp;
|
||||
reference r = *temp;
|
||||
return r;
|
||||
}
|
||||
|
||||
inline pointer operator->() const
|
||||
{
|
||||
It temp(m_current);
|
||||
--temp;
|
||||
return (iterator_arrow_result)(temp);
|
||||
}
|
||||
|
||||
inline reference operator[](difference_type off) const
|
||||
{
|
||||
return this->m_current[difference_type(-off - 1)];
|
||||
}
|
||||
|
||||
inline reverse_iterator& operator++()
|
||||
{
|
||||
--m_current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline reverse_iterator operator++(int)
|
||||
{
|
||||
reverse_iterator temp((*this));
|
||||
--m_current;
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline reverse_iterator& operator--()
|
||||
{
|
||||
++m_current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline reverse_iterator operator--(int)
|
||||
{
|
||||
reverse_iterator temp((*this));
|
||||
++m_current;
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline friend bool operator==(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current == r.m_current; }
|
||||
|
||||
inline friend bool operator!=(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current != r.m_current; }
|
||||
|
||||
inline friend bool operator<(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current > r.m_current; }
|
||||
|
||||
inline friend bool operator<=(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current >= r.m_current; }
|
||||
|
||||
inline friend bool operator>(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current < r.m_current; }
|
||||
|
||||
inline friend bool operator>=(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current <= r.m_current; }
|
||||
|
||||
inline reverse_iterator& operator+=(difference_type off)
|
||||
{ m_current -= off; return *this; }
|
||||
|
||||
inline reverse_iterator& operator-=(difference_type off)
|
||||
{ m_current += off; return *this; }
|
||||
|
||||
inline friend reverse_iterator operator+(reverse_iterator l, difference_type off)
|
||||
{ return (l += off); }
|
||||
|
||||
inline friend reverse_iterator operator+(difference_type off, reverse_iterator r)
|
||||
{ return (r += off); }
|
||||
|
||||
inline friend reverse_iterator operator-(reverse_iterator l, difference_type off)
|
||||
{ return (l-= off); }
|
||||
|
||||
inline 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 >
|
||||
inline 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
|
||||
40
include/boost/move/detail/std_ns_begin.hpp
Normal file
40
include/boost/move/detail/std_ns_begin.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#//////////////////////////////////////////////////////////////////////////////
|
||||
#//
|
||||
#// (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.
|
||||
#//
|
||||
#//////////////////////////////////////////////////////////////////////////////
|
||||
#
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#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
|
||||
#elif defined(BOOST_DINKUMWARE_STDLIB)
|
||||
#define BOOST_MOVE_STD_NS_BEG _STD_BEGIN
|
||||
#define BOOST_MOVE_STD_NS_END _STD_END
|
||||
#else
|
||||
#define BOOST_MOVE_STD_NS_BEG namespace std {
|
||||
#define BOOST_MOVE_STD_NS_END }
|
||||
#endif
|
||||
|
||||
#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
|
||||
19
include/boost/move/detail/std_ns_end.hpp
Normal file
19
include/boost/move/detail/std_ns_end.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#//////////////////////////////////////////////////////////////////////////////
|
||||
#//
|
||||
#// (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
|
||||
|
||||
#undef BOOST_MOVE_STD_NS_BEG
|
||||
#undef BOOST_MOVE_STD_NS_END
|
||||
45
include/boost/move/detail/to_raw_pointer.hpp
Normal file
45
include/boost/move/detail/to_raw_pointer.hpp
Normal 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>
|
||||
inline 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
|
||||
1357
include/boost/move/detail/type_traits.hpp
Normal file
1357
include/boost/move/detail/type_traits.hpp
Normal file
File diff suppressed because it is too large
Load Diff
565
include/boost/move/detail/unique_ptr_meta_utils.hpp
Normal file
565
include/boost/move/detail/unique_ptr_meta_utils.hpp
Normal 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
|
||||
156
include/boost/move/detail/workaround.hpp
Normal file
156
include/boost/move/detail/workaround.hpp
Normal file
@@ -0,0 +1,156 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_CLANG) || (defined(BOOST_GCC) && ((__GNUC__ <= 5) || defined(__MINGW32__)))
|
||||
//Older GCCs have problems with forceinline
|
||||
//Clang can have code bloat issues with forceinline, see
|
||||
//https://lists.boost.org/boost-users/2023/04/91445.php and
|
||||
//https://github.com/llvm/llvm-project/issues/62202
|
||||
#define BOOST_MOVE_FORCEINLINE inline
|
||||
#else
|
||||
#define BOOST_MOVE_FORCEINLINE BOOST_FORCEINLINE
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
template <typename T1>
|
||||
BOOST_FORCEINLINE BOOST_CXX14_CONSTEXPR void ignore(T1 const&)
|
||||
{}
|
||||
|
||||
}} //namespace boost::movelib {
|
||||
|
||||
#if !(defined BOOST_NO_EXCEPTIONS)
|
||||
# define BOOST_MOVE_TRY { try
|
||||
# define BOOST_MOVE_CATCH(x) catch(x)
|
||||
# define BOOST_MOVE_RETHROW throw;
|
||||
# define BOOST_MOVE_CATCH_END }
|
||||
#else
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900
|
||||
# define BOOST_MOVE_TRY { if (true)
|
||||
# define BOOST_MOVE_CATCH(x) else if (false)
|
||||
# else
|
||||
// warning C4127: conditional expression is constant
|
||||
# define BOOST_MOVE_TRY { \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable: 4127)) \
|
||||
if (true) \
|
||||
__pragma(warning(pop))
|
||||
# define BOOST_MOVE_CATCH(x) else \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable: 4127)) \
|
||||
if (false) \
|
||||
__pragma(warning(pop))
|
||||
# endif
|
||||
# define BOOST_MOVE_RETHROW
|
||||
# define BOOST_MOVE_CATCH_END }
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_STATIC_ASSERT
|
||||
# ifndef BOOST_NO_CXX11_VARIADIC_MACROS
|
||||
# define BOOST_MOVE_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
|
||||
# else
|
||||
# define BOOST_MOVE_STATIC_ASSERT( B ) static_assert(B, #B)
|
||||
# endif
|
||||
#else
|
||||
namespace boost {
|
||||
namespace move_detail {
|
||||
|
||||
template<bool B>
|
||||
struct STATIC_ASSERTION_FAILURE;
|
||||
|
||||
template<>
|
||||
struct STATIC_ASSERTION_FAILURE<true>{};
|
||||
|
||||
template<unsigned> struct static_assert_test {};
|
||||
|
||||
}}
|
||||
|
||||
#define BOOST_MOVE_STATIC_ASSERT(B) \
|
||||
typedef ::boost::move_detail::static_assert_test<\
|
||||
(unsigned)sizeof(::boost::move_detail::STATIC_ASSERTION_FAILURE<bool(B)>)>\
|
||||
BOOST_JOIN(boost_move_static_assert_typedef_, __LINE__) BOOST_ATTRIBUTE_UNUSED
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(__has_cpp_attribute) || defined(__CUDACC__)
|
||||
#define BOOST_MOVE_HAS_MSVC_ATTRIBUTE(ATTR) 0
|
||||
#else
|
||||
#define BOOST_MOVE_HAS_MSVC_ATTRIBUTE(ATTR) __has_cpp_attribute(msvc::ATTR)
|
||||
#endif
|
||||
|
||||
// See https://devblogs.microsoft.com/cppblog/improving-the-state-of-debug-performance-in-c/
|
||||
// for details on how MSVC has improved debug experience, specifically for move/forward-like utilities
|
||||
#if BOOST_MOVE_HAS_MSVC_ATTRIBUTE(intrinsic)
|
||||
#define BOOST_MOVE_INTRINSIC_CAST [[msvc::intrinsic]]
|
||||
#else
|
||||
#define BOOST_MOVE_INTRINSIC_CAST BOOST_MOVE_FORCEINLINE
|
||||
#endif
|
||||
|
||||
#if defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_launder)
|
||||
#define BOOST_MOVE_HAS_BUILTIN_LAUNDER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
|
||||
311
include/boost/move/iterator.hpp
Normal file
311
include/boost/move/iterator.hpp
Normal 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;
|
||||
|
||||
inline move_iterator()
|
||||
: m_it()
|
||||
{}
|
||||
|
||||
inline explicit move_iterator(const It &i)
|
||||
: m_it(i)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
inline move_iterator(const move_iterator<U>& u)
|
||||
: m_it(u.m_it)
|
||||
{}
|
||||
|
||||
inline 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
|
||||
}
|
||||
|
||||
inline pointer operator->() const
|
||||
{ return m_it; }
|
||||
|
||||
inline move_iterator& operator++()
|
||||
{ ++m_it; return *this; }
|
||||
|
||||
inline move_iterator<iterator_type> operator++(int)
|
||||
{ move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; }
|
||||
|
||||
inline move_iterator& operator--()
|
||||
{ --m_it; return *this; }
|
||||
|
||||
inline 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); }
|
||||
|
||||
inline move_iterator& operator+=(difference_type n)
|
||||
{ m_it += n; return *this; }
|
||||
|
||||
inline move_iterator<iterator_type> operator- (difference_type n) const
|
||||
{ return move_iterator<iterator_type>(m_it - n); }
|
||||
|
||||
inline move_iterator& operator-=(difference_type n)
|
||||
{ m_it -= n; return *this; }
|
||||
|
||||
inline 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
|
||||
}
|
||||
|
||||
inline friend bool operator==(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it == y.m_it; }
|
||||
|
||||
inline friend bool operator!=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it != y.m_it; }
|
||||
|
||||
inline friend bool operator< (const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it < y.m_it; }
|
||||
|
||||
inline friend bool operator<=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it <= y.m_it; }
|
||||
|
||||
inline friend bool operator> (const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it > y.m_it; }
|
||||
|
||||
inline friend bool operator>=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it >= y.m_it; }
|
||||
|
||||
inline friend difference_type operator-(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it - y.m_it; }
|
||||
|
||||
inline friend move_iterator operator+(difference_type n, const move_iterator& x)
|
||||
{ return move_iterator(x.m_it + n); }
|
||||
|
||||
private:
|
||||
It m_it;
|
||||
};
|
||||
|
||||
//is_move_iterator
|
||||
namespace move_detail {
|
||||
|
||||
template <class I>
|
||||
struct is_move_iterator
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <class I>
|
||||
struct is_move_iterator< ::boost::move_iterator<I> >
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
} //namespace move_detail {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move_iterator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//!
|
||||
//! <b>Returns</b>: move_iterator<It>(i).
|
||||
template<class It>
|
||||
inline move_iterator<It> make_move_iterator(const It &it)
|
||||
{ return move_iterator<It>(it); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// back_move_insert_iterator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//! A move insert iterator that move constructs elements at the
|
||||
//! back of a container
|
||||
template <typename C> // C models Container
|
||||
class back_move_insert_iterator
|
||||
{
|
||||
C* container_m;
|
||||
|
||||
public:
|
||||
typedef C container_type;
|
||||
typedef typename C::value_type value_type;
|
||||
typedef typename C::reference reference;
|
||||
typedef typename C::pointer pointer;
|
||||
typedef typename C::difference_type difference_type;
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
|
||||
explicit back_move_insert_iterator(C& x) : container_m(&x) { }
|
||||
|
||||
back_move_insert_iterator& operator=(reference x)
|
||||
{ container_m->push_back(boost::move(x)); return *this; }
|
||||
|
||||
back_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x)
|
||||
{ reference rx = x; return this->operator=(rx); }
|
||||
|
||||
back_move_insert_iterator& operator*() { return *this; }
|
||||
back_move_insert_iterator& operator++() { return *this; }
|
||||
back_move_insert_iterator& operator++(int) { return *this; }
|
||||
};
|
||||
|
||||
//!
|
||||
//! <b>Returns</b>: back_move_insert_iterator<C>(x).
|
||||
template <typename C> // C models Container
|
||||
inline back_move_insert_iterator<C> back_move_inserter(C& x)
|
||||
{
|
||||
return back_move_insert_iterator<C>(x);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// front_move_insert_iterator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! A move insert iterator that move constructs elements int the
|
||||
//! front of a container
|
||||
template <typename C> // C models Container
|
||||
class front_move_insert_iterator
|
||||
{
|
||||
C* container_m;
|
||||
|
||||
public:
|
||||
typedef C container_type;
|
||||
typedef typename C::value_type value_type;
|
||||
typedef typename C::reference reference;
|
||||
typedef typename C::pointer pointer;
|
||||
typedef typename C::difference_type difference_type;
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
|
||||
explicit front_move_insert_iterator(C& x) : container_m(&x) { }
|
||||
|
||||
front_move_insert_iterator& operator=(reference x)
|
||||
{ container_m->push_front(boost::move(x)); return *this; }
|
||||
|
||||
front_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x)
|
||||
{ reference rx = x; return this->operator=(rx); }
|
||||
|
||||
front_move_insert_iterator& operator*() { return *this; }
|
||||
front_move_insert_iterator& operator++() { return *this; }
|
||||
front_move_insert_iterator& operator++(int) { return *this; }
|
||||
};
|
||||
|
||||
//!
|
||||
//! <b>Returns</b>: front_move_insert_iterator<C>(x).
|
||||
template <typename C> // C models Container
|
||||
inline front_move_insert_iterator<C> front_move_inserter(C& x)
|
||||
{
|
||||
return front_move_insert_iterator<C>(x);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// insert_move_iterator
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
template <typename C> // C models Container
|
||||
class move_insert_iterator
|
||||
{
|
||||
C* container_m;
|
||||
typename C::iterator pos_;
|
||||
|
||||
public:
|
||||
typedef C container_type;
|
||||
typedef typename C::value_type value_type;
|
||||
typedef typename C::reference reference;
|
||||
typedef typename C::pointer pointer;
|
||||
typedef typename C::difference_type difference_type;
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
|
||||
explicit move_insert_iterator(C& x, typename C::iterator pos)
|
||||
: container_m(&x), pos_(pos)
|
||||
{}
|
||||
|
||||
move_insert_iterator& operator=(reference x)
|
||||
{
|
||||
pos_ = container_m->insert(pos_, ::boost::move(x));
|
||||
++pos_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
move_insert_iterator& operator=(BOOST_RV_REF(value_type) x)
|
||||
{ reference rx = x; return this->operator=(rx); }
|
||||
|
||||
move_insert_iterator& operator*() { return *this; }
|
||||
move_insert_iterator& operator++() { return *this; }
|
||||
move_insert_iterator& operator++(int) { return *this; }
|
||||
};
|
||||
|
||||
//!
|
||||
//! <b>Returns</b>: move_insert_iterator<C>(x, it).
|
||||
template <typename C> // C models Container
|
||||
inline move_insert_iterator<C> move_inserter(C& x, typename C::iterator it)
|
||||
{
|
||||
return move_insert_iterator<C>(x, it);
|
||||
}
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_ITERATOR_HPP
|
||||
248
include/boost/move/make_unique.hpp
Normal file
248
include/boost/move/make_unique.hpp
Normal 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
|
||||
35
include/boost/move/move.hpp
Normal file
35
include/boost/move/move.hpp
Normal 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
|
||||
77
include/boost/move/traits.hpp
Normal file
77
include/boost/move/traits.hpp
Normal 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 <T>::value == true</i>)
|
||||
//! means that if T is used as argument of a move construction/assignment,
|
||||
//! there is no need to call T's destructor.
|
||||
//! This optimization tipically is used to improve containers' performance.
|
||||
//!
|
||||
//! By default this trait is true if the type has trivial destructor,
|
||||
//! every class should specialize this trait if it wants to improve performance
|
||||
//! when inserted in containers.
|
||||
template <class T>
|
||||
struct has_trivial_destructor_after_move
|
||||
: ::boost::move_detail::is_trivially_destructible<T>
|
||||
{};
|
||||
|
||||
//! By default this traits returns
|
||||
//! <pre>boost::is_nothrow_move_constructible<T>::value && boost::is_nothrow_move_assignable<T>::value </pre>.
|
||||
//! Classes with non-throwing move constructor
|
||||
//! and assignment can specialize this trait to obtain some performance improvements.
|
||||
template <class T>
|
||||
struct has_nothrow_move
|
||||
{
|
||||
static const bool value = boost::move_detail::is_nothrow_move_constructible<T>::value &&
|
||||
boost::move_detail::is_nothrow_move_assignable<T>::value;
|
||||
};
|
||||
|
||||
namespace move_detail {
|
||||
|
||||
template <class T>
|
||||
struct is_nothrow_move_constructible_or_uncopyable
|
||||
{
|
||||
//The standard requires is_nothrow_move_constructible for move_if_noexcept
|
||||
//but a user (usually in C++03) might specialize has_nothrow_move which includes it
|
||||
static const bool value = is_nothrow_move_constructible<T>::value ||
|
||||
has_nothrow_move<T>::value ||
|
||||
!is_copy_constructible<T>::value;
|
||||
};
|
||||
|
||||
} //move_detail {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_TRAITS_HPP
|
||||
870
include/boost/move/unique_ptr.hpp
Normal file
870
include/boost/move/unique_ptr.hpp
Normal file
@@ -0,0 +1,870 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 <cassert>
|
||||
|
||||
#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;
|
||||
|
||||
inline unique_ptr_data() BOOST_NOEXCEPT
|
||||
: m_p(), d()
|
||||
{}
|
||||
|
||||
inline explicit unique_ptr_data(P p) BOOST_NOEXCEPT
|
||||
: m_p(p), d()
|
||||
{}
|
||||
|
||||
inline unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
|
||||
: m_p(p), d(d1)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
inline unique_ptr_data(P p, BOOST_FWD_REF(U) d1) BOOST_NOEXCEPT
|
||||
: m_p(p), d(::boost::forward<U>(d1))
|
||||
{}
|
||||
|
||||
inline del_ref deleter() { return d; }
|
||||
inline 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;
|
||||
|
||||
inline unique_ptr_data() BOOST_NOEXCEPT
|
||||
: D(), m_p()
|
||||
{}
|
||||
|
||||
inline explicit unique_ptr_data(P p) BOOST_NOEXCEPT
|
||||
: D(), m_p(p)
|
||||
{}
|
||||
|
||||
inline unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
|
||||
: D(d1), m_p(p)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
inline unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
|
||||
: D(::boost::forward<U>(d)), m_p(p)
|
||||
{}
|
||||
|
||||
inline del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); }
|
||||
inline 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.
|
||||
inline 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_MOVE_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
|
||||
BOOST_MOVE_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Same as <tt>unique_ptr()</tt> (default constructor).
|
||||
//!
|
||||
inline 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_MOVE_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
|
||||
BOOST_MOVE_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>
|
||||
inline 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_MOVE_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_MOVE_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
|
||||
BOOST_MOVE_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>
|
||||
inline 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_MOVE_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>
|
||||
inline 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>
|
||||
inline 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_MOVE_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>
|
||||
inline 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.
|
||||
inline 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>
|
||||
inline 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_MOVE_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_MOVE_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.
|
||||
inline BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
|
||||
operator[](std::size_t i) const BOOST_NOEXCEPT
|
||||
{
|
||||
assert( bmupmu::extent<T>::value == 0 || i < bmupmu::extent<T>::value );
|
||||
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.
|
||||
inline pointer operator->() const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_MOVE_STATIC_ASSERT((!bmupmu::is_array<T>::value));
|
||||
assert(m_data.m_p);
|
||||
return m_data.m_p;
|
||||
}
|
||||
|
||||
//! <b>Returns</b>: The stored pointer.
|
||||
//!
|
||||
inline pointer get() const BOOST_NOEXCEPT
|
||||
{ return m_data.m_p; }
|
||||
|
||||
//! <b>Returns</b>: A reference to the stored deleter.
|
||||
//!
|
||||
inline 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.
|
||||
//!
|
||||
inline 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.
|
||||
//!
|
||||
inline explicit operator bool
|
||||
#else
|
||||
inline 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.
|
||||
inline 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_MOVE_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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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>
|
||||
inline 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
|
||||
150
include/boost/move/utility.hpp
Normal file
150
include/boost/move/utility.hpp
Normal 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_INTRINSIC_CAST 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_INTRINSIC_CAST 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
|
||||
323
include/boost/move/utility_core.hpp
Normal file
323
include/boost/move/utility_core.hpp
Normal file
@@ -0,0 +1,323 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
|
||||
#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_INTRINSIC_CAST
|
||||
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_INTRINSIC_CAST
|
||||
T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
|
||||
{ return static_cast<T&&>(t); }
|
||||
|
||||
template <class T>
|
||||
BOOST_MOVE_INTRINSIC_CAST
|
||||
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_MOVE_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_MOVE_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
|
||||
Reference in New Issue
Block a user