update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -14,6 +14,12 @@
#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"
#endif
namespace boost {
namespace movelib {
@@ -23,21 +29,22 @@ namespace detail_adaptive {
template<class RandIt, class Compare, class XBuf>
inline void adaptive_merge_combine_blocks( RandIt first
, typename iterator_traits<RandIt>::size_type len1
, typename iterator_traits<RandIt>::size_type len2
, typename iterator_traits<RandIt>::size_type collected
, typename iterator_traits<RandIt>::size_type n_keys
, typename iterator_traits<RandIt>::size_type l_block
, 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 iterator_traits<RandIt>::size_type size_type;
size_type const len = len1+len2;
size_type const l_combine = len-collected;
size_type const l_combine1 = len1-collected;
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;
@@ -47,7 +54,7 @@ inline void adaptive_merge_combine_blocks( RandIt first
if(xbuf.size() < l_block){
xbuf.initialize_until(l_block, *first);
}
BOOST_ASSERT(xbuf.size() >= l_block);
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
@@ -63,7 +70,8 @@ inline void adaptive_merge_combine_blocks( RandIt first
, 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);
( 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{
@@ -84,7 +92,7 @@ inline void adaptive_merge_combine_blocks( RandIt first
, l_combine1, l_block, xbuf
, n_block_a, n_block_b, l_irreg1, l_irreg2, true); //Outputs
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" A combine: ", len);
BOOST_ASSERT(xbuf.size() >= l_block);
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();
@@ -94,22 +102,21 @@ inline void adaptive_merge_combine_blocks( RandIt first
template<class RandIt, class Compare, class XBuf>
inline void adaptive_merge_final_merge( RandIt first
, typename iterator_traits<RandIt>::size_type len1
, typename iterator_traits<RandIt>::size_type len2
, typename iterator_traits<RandIt>::size_type collected
, typename iterator_traits<RandIt>::size_type l_intbuf
, typename iterator_traits<RandIt>::size_type l_block
, bool use_internal_buf
, 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 iterator_traits<RandIt>::size_type size_type;
(void)l_block;
(void)use_internal_buf;
size_type n_keys = collected-l_intbuf;
size_type len = len1+len2;
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;
@@ -125,9 +132,9 @@ inline static SizeType adaptive_merge_n_keys_without_external_keys(SizeType l_bl
{
typedef SizeType size_type;
//This is the minimum number of keys to implement the ideal algorithm
size_type n_keys = len1/l_block+len2/l_block;
const size_type second_half_blocks = len2/l_block;
const size_type first_half_aux = len1-l_intbuf;
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;
}
@@ -140,7 +147,7 @@ inline static SizeType adaptive_merge_n_keys_with_external_keys(SizeType l_block
{
typedef SizeType size_type;
//This is the minimum number of keys to implement the ideal algorithm
size_type n_keys = (len1-l_intbuf)/l_block + len2/l_block;
size_type n_keys = size_type((len1-l_intbuf)/l_block + len2/l_block);
return n_keys;
}
@@ -157,7 +164,7 @@ inline SizeType adaptive_merge_n_keys_intbuf(SizeType &rl_block, SizeType len1,
//This is the minimum number of keys to implement the ideal algorithm
size_type n_keys = adaptive_merge_n_keys_without_external_keys(l_block, len1, len2, l_intbuf);
BOOST_ASSERT(n_keys >= ((len1-l_intbuf-n_keys)/l_block + len2/l_block));
assert(n_keys >= ((len1-l_intbuf-n_keys)/l_block + len2/l_block));
if(xbuf.template supports_aligned_trailing<size_type>
( l_block
@@ -216,19 +223,20 @@ inline SizeType adaptive_merge_n_keys_intbuf(SizeType &rl_block, SizeType len1,
template<class RandIt, class Compare, class XBuf>
void adaptive_merge_impl
( RandIt first
, typename iterator_traits<RandIt>::size_type len1
, typename iterator_traits<RandIt>::size_type len2
, typename iter_size<RandIt>::type len1
, typename iter_size<RandIt>::type len2
, Compare comp
, XBuf & xbuf
)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
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);
buffered_merge( first, first+len1
, first + len1+len2, comp, xbuf);
}
else{
const size_type len = len1+len2;
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));
@@ -243,7 +251,7 @@ void adaptive_merge_impl
//internal buffer is needed so l_intbuf will remain 0.
size_type l_intbuf = 0;
size_type n_keys = adaptive_merge_n_keys_intbuf(l_block, len1, len2, xbuf, l_intbuf);
size_type const to_collect = l_intbuf+n_keys;
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);
@@ -309,9 +317,9 @@ void adaptive_merge_impl
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 iterator_traits<RandIt>::size_type uninitialized_len = 0)
, typename iter_size<RandIt>::type uninitialized_len = 0)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
typedef typename iterator_traits<RandIt>::value_type value_type;
if (first == middle || middle == last){
@@ -347,6 +355,10 @@ void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp
} //namespace movelib {
} //namespace boost {
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#include <boost/move/detail/config_end.hpp>
#endif //#define BOOST_MOVE_ADAPTIVE_MERGE_HPP

View File

@@ -13,7 +13,14 @@
#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"
#endif
namespace boost {
namespace movelib {
@@ -23,7 +30,7 @@ namespace detail_adaptive {
template<class RandIt>
void move_data_backward( RandIt cur_pos
, typename iterator_traits<RandIt>::size_type const l_data
, typename iter_size<RandIt>::type const l_data
, RandIt new_pos
, bool const xbuf_used)
{
@@ -40,7 +47,7 @@ void move_data_backward( RandIt cur_pos
template<class RandIt>
void move_data_forward( RandIt cur_pos
, typename iterator_traits<RandIt>::size_type const l_data
, typename iter_size<RandIt>::type const l_data
, RandIt new_pos
, bool const xbuf_used)
{
@@ -76,29 +83,29 @@ void move_data_forward( RandIt cur_pos
// As a last step, if auxiliary memory is available in-place merge is performed.
// until all is merged or auxiliary memory is not large enough.
template<class RandIt, class Compare, class XBuf>
typename iterator_traits<RandIt>::size_type
typename iter_size<RandIt>::type
adaptive_sort_build_blocks
( RandIt const first
, typename iterator_traits<RandIt>::size_type const len
, typename iterator_traits<RandIt>::size_type const l_base
, typename iterator_traits<RandIt>::size_type const l_build_buf
, 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 iterator_traits<RandIt>::size_type size_type;
BOOST_ASSERT(l_build_buf <= len);
BOOST_ASSERT(0 == ((l_build_buf / l_base)&(l_build_buf/l_base-1)));
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 = len - l_build_buf;
size_type const elements_in_blocks = size_type(len - l_build_buf);
//////////////////////////////////
// Start of merge to left step
//////////////////////////////////
size_type l_merged = 0u;
BOOST_ASSERT(l_build_buf);
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;
@@ -111,7 +118,7 @@ typename iterator_traits<RandIt>::size_type
//Now combine them using the buffer. Elements from buffer can be
//overwritten since they've been saved to xbuf
l_merged = op_merge_left_step_multiple
( first_block - l_merged, elements_in_blocks, l_merged, l_build_buf, kbuf - l_merged, comp, move_op());
( 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
@@ -121,15 +128,15 @@ typename iterator_traits<RandIt>::size_type
}
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);
rotate_gcd(first_block-l_merged, first_block, first_block+elements_in_blocks);
}
//Now combine elements using the buffer. Elements from buffer can't be
//overwritten since xbuf was not big enough, so merge swapping elements.
l_merged = op_merge_left_step_multiple
(first_block - l_merged, elements_in_blocks, l_merged, l_build_buf, l_build_buf - l_merged, comp, swap_op());
(first_block-l_merged, elements_in_blocks, l_merged, l_build_buf, size_type(l_build_buf - l_merged), comp, swap_op());
BOOST_ASSERT(l_merged == l_build_buf);
assert(l_merged == l_build_buf);
//////////////////////////////////
// Start of merge to right step
@@ -148,7 +155,7 @@ typename iterator_traits<RandIt>::size_type
}
xbuf.clear();
//2*l_build_buf or total already merged
return min_value<size_type>(elements_in_blocks, 2*l_build_buf);
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>
@@ -156,31 +163,31 @@ void adaptive_sort_combine_blocks
( RandItKeys const keys
, KeyCompare key_comp
, RandIt const first
, typename iterator_traits<RandIt>::size_type const len
, typename iterator_traits<RandIt>::size_type const l_prev_merged
, typename iterator_traits<RandIt>::size_type const l_block
, 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)
{
(void)xbuf;
typedef typename iterator_traits<RandIt>::size_type size_type;
boost::movelib::ignore(xbuf);
typedef typename iter_size<RandIt>::type size_type;
size_type const l_reg_combined = 2*l_prev_merged;
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;
(void)l_total_combined;
BOOST_ASSERT(l_total_combined <= len);
boost::movelib::ignore(l_total_combined);
assert(l_total_combined <= len);
size_type const max_i = n_reg_combined + (l_irreg_combined != 0);
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; ++combined_i, combined_first += l_reg_combined) {
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;
@@ -202,11 +209,15 @@ void adaptive_sort_combine_blocks
(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 += l_reg_combined*(max_i-1);
for( size_type combined_i = max_i; combined_i--; combined_first -= l_reg_combined) {
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;
@@ -222,6 +233,8 @@ void adaptive_sort_combine_blocks
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;
}
}
}
@@ -232,18 +245,19 @@ void adaptive_sort_combine_blocks
template<class RandIt, class Compare, class XBuf>
bool adaptive_sort_combine_all_blocks
( RandIt keys
, typename iterator_traits<RandIt>::size_type &n_keys
, typename iter_size<RandIt>::type &n_keys
, RandIt const buffer
, typename iterator_traits<RandIt>::size_type const l_buf_plus_data
, typename iterator_traits<RandIt>::size_type l_merged
, typename iterator_traits<RandIt>::size_type &l_intbuf
, 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 iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
RandIt const first = buffer + l_intbuf;
size_type const l_data = l_buf_plus_data - l_intbuf;
size_type const l_unique = l_intbuf+n_keys;
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){
@@ -255,7 +269,7 @@ bool adaptive_sort_combine_all_blocks
bool prev_use_internal_buf = true;
for( size_type n = 0; l_data > l_merged
; l_merged*=2
; 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
@@ -264,9 +278,9 @@ bool adaptive_sort_combine_all_blocks
//Otherwise, just give up and and use all keys to merge using rotations (use_internal_buf = false)
bool use_internal_buf = false;
size_type const l_block = lblock_for_combine(l_intbuf, n_keys, size_type(2*l_merged), use_internal_buf);
BOOST_ASSERT(!l_intbuf || (l_block == l_intbuf));
BOOST_ASSERT(n == 0 || (!use_internal_buf || prev_use_internal_buf) );
BOOST_ASSERT(n == 0 || (!use_internal_buf || l_prev_block == l_block) );
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);
@@ -279,11 +293,11 @@ bool adaptive_sort_combine_all_blocks
RandIt const buf_end = first+l_prev_total_combined;
RandIt const buf_beg = buf_end-l_block;
if(l_prev_total_combined > l_total_combined){
size_type const l_diff = l_prev_total_combined - l_total_combined;
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 = l_total_combined - l_prev_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);
}
}
@@ -292,7 +306,7 @@ bool adaptive_sort_combine_all_blocks
//Combine to form l_merged*2 segments
if(n_keys){
size_type upper_n_keys_this_iter = 2*l_merged/l_block;
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
@@ -318,11 +332,11 @@ bool adaptive_sort_combine_all_blocks
l_prev_block = l_block;
prev_use_internal_buf = use_internal_buf;
}
BOOST_ASSERT(l_prev_total_combined == l_data);
assert(l_prev_total_combined == l_data);
bool const buffer_right = prev_use_internal_buf && prev_merge_left;
l_intbuf = prev_use_internal_buf ? l_prev_block : 0u;
n_keys = l_unique - l_intbuf;
n_keys = size_type(l_unique - l_intbuf);
//Restore data from to external common buffer if used
if(common_xbuf){
if(buffer_right){
@@ -339,21 +353,22 @@ bool adaptive_sort_combine_all_blocks
template<class RandIt, class Compare, class XBuf>
void adaptive_sort_final_merge( bool buffer_right
, RandIt const first
, typename iterator_traits<RandIt>::size_type const l_intbuf
, typename iterator_traits<RandIt>::size_type const n_keys
, typename iterator_traits<RandIt>::size_type const len
, typename iter_size<RandIt>::type const l_intbuf
, typename iter_size<RandIt>::type const n_keys
, typename iter_size<RandIt>::type const len
, XBuf & xbuf
, Compare comp)
{
//BOOST_ASSERT(n_keys || xbuf.size() == l_intbuf);
//assert(n_keys || xbuf.size() == l_intbuf);
xbuf.clear();
typedef typename iterator_traits<RandIt>::size_type size_type;
size_type const n_key_plus_buf = l_intbuf+n_keys;
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);
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);
}
@@ -364,7 +379,8 @@ void adaptive_sort_final_merge( bool buffer_right
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+n_keys, first+n_key_plus_buf
, first+len, comp, xbuf);
stable_merge(first, first+n_keys, first+len, comp, xbuf);
}
else{
@@ -381,7 +397,7 @@ bool adaptive_sort_build_params
, XBuf & xbuf
)
{
typedef Unsigned size_type;
typedef typename iter_size<RandIt>::type size_type;
//Calculate ideal parameters and try to collect needed unique keys
l_base = 0u;
@@ -396,20 +412,21 @@ bool adaptive_sort_build_params
//The internal buffer can be expanded if there is enough external memory
while(xbuf.capacity() >= l_intbuf*2){
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 = l_intbuf-1;
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 += 1;
BOOST_ASSERT(n_min_ideal_keys <= l_intbuf);
++n_min_ideal_keys;
assert(n_min_ideal_keys <= l_intbuf);
if(xbuf.template supports_aligned_trailing<size_type>(l_intbuf, (len-l_intbuf-1)/l_intbuf+1)){
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;
}
@@ -422,7 +439,7 @@ bool adaptive_sort_build_params
//(to be used for keys in combine_all_blocks) as the whole l_build_buf
//will be backuped in the buffer during build_blocks.
bool const non_unique_buf = xbuf.capacity() >= l_intbuf;
size_type const to_collect = non_unique_buf ? n_min_ideal_keys : l_intbuf*2;
size_type 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"
@@ -433,23 +450,23 @@ bool adaptive_sort_build_params
}
else if(collected == 2*l_intbuf){
//l_intbuf*2 elements found. Use all of them in the build phase
l_build_buf = l_intbuf*2;
l_build_buf = size_type(l_intbuf*2);
n_keys = l_intbuf;
}
else if(collected == (n_min_ideal_keys+l_intbuf)){
else if(collected >= (n_min_ideal_keys+l_intbuf)){
l_build_buf = l_intbuf;
n_keys = n_min_ideal_keys;
n_keys = size_type(collected - l_intbuf);
}
//If collected keys are not enough, try to fix n_keys and l_intbuf. If no fix
//is possible (due to very low unique keys), then go to a slow sort based on rotations.
else{
BOOST_ASSERT(collected < (n_min_ideal_keys+l_intbuf));
assert(collected < (n_min_ideal_keys+l_intbuf));
if(collected < 4){ //No combination possible with less that 4 keys
return false;
}
n_keys = l_intbuf;
while(n_keys&(n_keys-1)){
n_keys &= n_keys-1; // make it power or 2
while(n_keys & (n_keys-1u)){
n_keys &= size_type(n_keys-1u); // make it power or 2
}
while(n_keys > collected){
n_keys/=2;
@@ -459,7 +476,7 @@ bool adaptive_sort_build_params
l_intbuf = 0;
l_build_buf = n_keys;
}
BOOST_ASSERT((n_keys+l_intbuf) >= l_build_buf);
assert((n_keys+l_intbuf) >= l_build_buf);
}
return true;
@@ -524,12 +541,12 @@ bool adaptive_sort_build_params
template<class RandIt, class Compare, class XBuf>
void adaptive_sort_impl
( RandIt first
, typename iterator_traits<RandIt>::size_type const len
, typename iter_size<RandIt>::type const len
, Compare comp
, XBuf & xbuf
)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
//Small sorts go directly to insertion sort
if(len <= size_type(AdaptiveSortInsertionSortThreshold)){
@@ -540,7 +557,7 @@ void adaptive_sort_impl
}
else{
//Make sure it is at least four
BOOST_STATIC_ASSERT(AdaptiveSortInsertionSortThreshold >= 4);
BOOST_MOVE_STATIC_ASSERT(AdaptiveSortInsertionSortThreshold >= 4);
size_type l_base = 0;
size_type l_intbuf = 0;
@@ -553,21 +570,23 @@ void adaptive_sort_impl
stable_sort(first, first+len, comp, xbuf);
}
else{
BOOST_ASSERT(l_build_buf);
assert(l_build_buf);
//Otherwise, continue the adaptive_sort
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L1("\n After collect_unique: ", len);
size_type const n_key_plus_buf = l_intbuf+n_keys;
size_type const n_key_plus_buf = size_type(l_intbuf+n_keys);
//l_build_buf is always power of two if l_intbuf is zero
BOOST_ASSERT(l_intbuf || (0 == (l_build_buf & (l_build_buf-1))));
assert(l_intbuf || (0 == (l_build_buf & (l_build_buf-1))));
//Classic merge sort until internal buffer and xbuf are exhausted
size_type const l_merged = adaptive_sort_build_blocks
(first+n_key_plus_buf-l_build_buf, len-n_key_plus_buf+l_build_buf, l_base, l_build_buf, xbuf, comp);
( 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, len-n_keys, l_merged, l_intbuf, xbuf, comp);
(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);
@@ -607,9 +626,9 @@ void adaptive_sort_impl
template<class RandIt, class RandRawIt, class Compare>
void adaptive_sort( RandIt first, RandIt last, Compare comp
, RandRawIt uninitialized
, typename iterator_traits<RandIt>::size_type uninitialized_len)
, typename iter_size<RandIt>::type uninitialized_len)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
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);
@@ -628,4 +647,8 @@ void adaptive_sort( RandIt first, RandIt last, Compare comp)
#include <boost/move/detail/config_end.hpp>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#endif //#define BOOST_MOVE_ADAPTIVE_SORT_HPP

View File

@@ -43,6 +43,7 @@
#define BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
#include <boost/move/detail/config_begin.hpp>
#include <boost/move/detail/reverse_iterator.hpp>
#include <boost/move/algo/move.hpp>
#include <boost/move/algo/detail/merge.hpp>
@@ -52,8 +53,14 @@
#include <boost/move/algo/detail/heap_sort.hpp>
#include <boost/move/algo/detail/merge.hpp>
#include <boost/move/algo/detail/is_sorted.hpp>
#include <boost/assert.hpp>
#include <cassert>
#include <boost/cstdint.hpp>
#include <limits.h>
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#ifndef BOOST_MOVE_ADAPTIVE_SORT_STATS_LEVEL
#define BOOST_MOVE_ADAPTIVE_SORT_STATS_LEVEL 1
@@ -81,7 +88,7 @@
#endif
#ifdef BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANT BOOST_ASSERT
#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANT assert
#else
#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(L)
#endif
@@ -110,7 +117,7 @@ namespace detail_adaptive {
static const std::size_t AdaptiveSortInsertionSortThreshold = 16;
//static const std::size_t AdaptiveSortInsertionSortThreshold = 4;
BOOST_STATIC_ASSERT((AdaptiveSortInsertionSortThreshold&(AdaptiveSortInsertionSortThreshold-1)) == 0);
BOOST_MOVE_STATIC_ASSERT((AdaptiveSortInsertionSortThreshold&(AdaptiveSortInsertionSortThreshold-1)) == 0);
#if defined BOOST_HAS_INTPTR_T
typedef ::boost::uintptr_t uintptr_t;
@@ -131,13 +138,13 @@ const T &max_value(const T &a, const T &b)
}
template<class ForwardIt, class Pred, class V>
typename iterator_traits<ForwardIt>::size_type
typename iter_size<ForwardIt>::type
count_if_with(ForwardIt first, ForwardIt last, Pred pred, const V &v)
{
typedef typename iterator_traits<ForwardIt>::size_type size_type;
typedef typename iter_size<ForwardIt>::type size_type;
size_type count = 0;
while(first != last) {
count += static_cast<size_type>(0 != pred(*first, v));
count = size_type(count + static_cast<size_type>(0 != pred(*first, v)));
++first;
}
return count;
@@ -167,7 +174,8 @@ void swap_and_update_key
{
if(begin != with){
::boost::adl_move_swap_ranges(begin, end, with);
::boost::adl_move_swap(*key_next, *key_range2);
if(key_next != key_range2) //Avoid potential self-swapping
::boost::adl_move_swap(*key_next, *key_range2);
if(key_next == key_mid){
key_mid = key_range2;
}
@@ -209,7 +217,8 @@ RandIt2 buffer_and_update_key
while(begin != end) {
op(three_way_t(), begin++, with++, buffer++);
}
::boost::adl_move_swap(*key_next, *key_range2);
if (key_next != key_range2) //Avoid potential self-swapping
::boost::adl_move_swap(*key_next, *key_range2);
if (key_next == key_mid) {
key_mid = key_range2;
}
@@ -264,28 +273,28 @@ RandIt partial_merge_bufferless
template<class SizeType>
static SizeType needed_keys_count(SizeType n_block_a, SizeType n_block_b)
{
return n_block_a + n_block_b;
return SizeType(n_block_a + n_block_b);
}
template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
typename iterator_traits<RandIt>::size_type
typename iter_size<RandIt>::type
find_next_block
( RandItKeys const key_first
, KeyCompare key_comp
, RandIt const first
, typename iterator_traits<RandIt>::size_type const l_block
, typename iterator_traits<RandIt>::size_type const ix_first_block
, typename iterator_traits<RandIt>::size_type const ix_last_block
, typename iter_size<RandIt>::type const l_block
, typename iter_size<RandIt>::type const ix_first_block
, typename iter_size<RandIt>::type const ix_last_block
, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
typedef typename iterator_traits<RandIt>::value_type value_type;
typedef typename iterator_traits<RandItKeys>::value_type key_type;
BOOST_ASSERT(ix_first_block <= ix_last_block);
assert(ix_first_block <= ix_last_block);
size_type ix_min_block = 0u;
for (size_type szt_i = ix_first_block; szt_i < ix_last_block; ++szt_i) {
const value_type &min_val = first[ix_min_block*l_block];
const value_type &cur_val = first[szt_i*l_block];
const value_type &min_val = first[size_type(ix_min_block*l_block)];
const value_type &cur_val = first[size_type(szt_i*l_block)];
const key_type &min_key = key_first[ix_min_block];
const key_type &cur_key = key_first[szt_i];
@@ -304,49 +313,55 @@ void merge_blocks_bufferless
( RandItKeys const key_first
, KeyCompare key_comp
, RandIt const first
, typename iterator_traits<RandIt>::size_type const l_block
, typename iterator_traits<RandIt>::size_type const l_irreg1
, typename iterator_traits<RandIt>::size_type const n_block_a
, typename iterator_traits<RandIt>::size_type const n_block_b
, typename iterator_traits<RandIt>::size_type const l_irreg2
, typename iter_size<RandIt>::type const l_block
, typename iter_size<RandIt>::type const l_irreg1
, typename iter_size<RandIt>::type const n_block_a
, typename iter_size<RandIt>::type const n_block_b
, typename iter_size<RandIt>::type const l_irreg2
, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
size_type const key_count = needed_keys_count(n_block_a, n_block_b); (void)key_count;
//BOOST_ASSERT(n_block_a || n_block_b);
typedef typename iter_size<RandIt>::type size_type;
size_type const key_count = needed_keys_count(n_block_a, n_block_b);
::boost::movelib::ignore(key_count);
//assert(n_block_a || n_block_b);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted_and_unique(key_first, key_first + key_count, key_comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + key_count, key_comp, key_first[n_block_a]));
size_type n_bef_irreg2 = 0;
bool l_irreg_pos_count = true;
RandItKeys key_mid(key_first + n_block_a);
RandIt const first_irr2 = first + l_irreg1 + (n_block_a+n_block_b)*l_block;
RandIt const first_irr2 = first + size_type(l_irreg1 + (n_block_a+n_block_b)*l_block);
RandIt const last_irr2 = first_irr2 + l_irreg2;
{ //Selection sort blocks
size_type n_block_left = n_block_b + n_block_a;
size_type n_block_left = size_type(n_block_b + n_block_a);
RandItKeys key_range2(key_first);
size_type min_check = n_block_a == n_block_left ? 0u : n_block_a;
size_type max_check = min_value<size_type>(min_check+1, n_block_left);
for (RandIt f = first+l_irreg1; n_block_left; --n_block_left, ++key_range2, f += l_block, min_check -= min_check != 0, max_check -= max_check != 0) {
size_type max_check = min_value<size_type>(size_type(min_check+1), n_block_left);
for ( RandIt f = first+l_irreg1; n_block_left; --n_block_left) {
size_type const next_key_idx = find_next_block(key_range2, key_comp, f, l_block, min_check, max_check, comp);
RandItKeys const key_next(key_range2 + next_key_idx);
max_check = min_value<size_type>(max_value<size_type>(max_check, next_key_idx+size_type(2)), n_block_left);
max_check = min_value<size_type>(max_value<size_type>(max_check, size_type(next_key_idx+2)), n_block_left);
RandIt const first_min = f + next_key_idx*l_block;
RandIt const first_min = f + size_type(next_key_idx*l_block);
//Check if irregular b block should go here.
//If so, break to the special code handling the irregular block
if (l_irreg_pos_count && l_irreg2 && comp(*first_irr2, *first_min)){
l_irreg_pos_count = false;
}
n_bef_irreg2 += l_irreg_pos_count;
n_bef_irreg2 = size_type(n_bef_irreg2+l_irreg_pos_count);
swap_and_update_key(key_next, key_range2, key_mid, f, f + l_block, first_min);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(f, f+l_block, comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first_min, first_min + l_block, comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((f == (first+l_irreg1)) || !comp(*f, *(f-l_block)));
//Update context
++key_range2;
f += l_block;
min_check = size_type(min_check - (min_check != 0));
max_check = size_type(max_check - (max_check != 0));
}
}
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first+l_irreg1+n_bef_irreg2*l_block, first_irr2, comp));
@@ -375,14 +390,15 @@ void merge_blocks_bufferless
//
// Returns the number of collected keys
template<class RandIt, class Compare, class XBuf>
typename iterator_traits<RandIt>::size_type
typename iter_size<RandIt>::type
collect_unique
( RandIt const first, RandIt const last
, typename iterator_traits<RandIt>::size_type const max_collected, Compare comp
, typename iter_size<RandIt>::type const max_collected, Compare comp
, XBuf & xbuf)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
size_type h = 0;
if(max_collected){
++h; // first key is always here
RandIt h0 = first;
@@ -428,22 +444,28 @@ typename iterator_traits<RandIt>::size_type
}
template<class Unsigned>
Unsigned floor_sqrt(Unsigned const n)
Unsigned floor_sqrt(Unsigned n)
{
Unsigned x = n;
Unsigned y = x/2 + (x&1);
while (y < x){
x = y;
y = (x + n / x)/2;
Unsigned rem = 0, root = 0;
const unsigned bits = sizeof(Unsigned)*CHAR_BIT;
for (unsigned i = bits / 2; i > 0; i--) {
root = Unsigned(root << 1u);
rem = Unsigned(Unsigned(rem << 2u) | Unsigned(n >> (bits - 2u)));
n = Unsigned(n << 2u);
if (root < rem) {
rem = Unsigned(rem - Unsigned(root | 1u));
root = Unsigned(root + 2u);
}
}
return x;
return Unsigned(root >> 1u);
}
template<class Unsigned>
Unsigned ceil_sqrt(Unsigned const n)
{
Unsigned r = floor_sqrt(n);
return r + Unsigned((n%r) != 0);
return Unsigned(r + Unsigned((n%r) != 0));
}
template<class Unsigned>
@@ -457,7 +479,7 @@ Unsigned floor_merge_multiple(Unsigned const n, Unsigned &base, Unsigned &pow)
}
base = s;
pow = p;
return s << p;
return Unsigned(s << p);
}
template<class Unsigned>
@@ -474,7 +496,7 @@ Unsigned ceil_merge_multiple(Unsigned const n, Unsigned &base, Unsigned &pow)
++pow;
}
}
return base << pow;
return Unsigned(base << pow);
}
template<class Unsigned>
@@ -517,26 +539,27 @@ template<class RandIt, class Compare>
void slow_stable_sort
( RandIt const first, RandIt const last, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
size_type L = size_type(last - first);
{ //Use insertion sort to merge first elements
size_type m = 0;
while((L - m) > size_type(AdaptiveSortInsertionSortThreshold)){
insertion_sort(first+m, first+m+size_type(AdaptiveSortInsertionSortThreshold), comp);
m += AdaptiveSortInsertionSortThreshold;
m = size_type(m + AdaptiveSortInsertionSortThreshold);
}
insertion_sort(first+m, last, comp);
}
size_type h = AdaptiveSortInsertionSortThreshold;
for(bool do_merge = L > h; do_merge; h*=2){
for(bool do_merge = L > h; do_merge; h = size_type(h*2)){
do_merge = (L - h) > h;
size_type p0 = 0;
if(do_merge){
size_type const h_2 = 2*h;
size_type const h_2 = size_type(2*h);
while((L-p0) > h_2){
merge_bufferless(first+p0, first+p0+h, first+p0+h_2, comp);
p0 += h_2;
p0 = size_type(p0 + h_2);
}
}
if((L-p0) > h){
@@ -552,7 +575,7 @@ template<class Unsigned>
Unsigned lblock_for_combine
(Unsigned const l_block, Unsigned const n_keys, Unsigned const l_data, bool &use_buf)
{
BOOST_ASSERT(l_data > 1);
assert(l_data > 1);
//We need to guarantee lblock >= l_merged/(n_keys/2) keys for the combination.
//We have at least 4 keys guaranteed (which are the minimum to merge 2 ranges)
@@ -563,12 +586,12 @@ Unsigned lblock_for_combine
if(!l_block){
//If l_block == 0 then n_keys is power of two
//(guaranteed by build_params(...))
BOOST_ASSERT(n_keys >= 4);
//BOOST_ASSERT(0 == (n_keys &(n_keys-1)));
assert(n_keys >= 4);
//assert(0 == (n_keys &(n_keys-1)));
//See if half keys are at least 4 and if half keys fulfill
Unsigned const new_buf = n_keys/2;
Unsigned const new_keys = n_keys-new_buf;
Unsigned const new_keys = Unsigned(n_keys-new_buf);
use_buf = new_keys >= 4 && new_keys >= l_data/new_buf;
if(use_buf){
return new_buf;
@@ -586,9 +609,9 @@ Unsigned lblock_for_combine
template<class RandIt, class Compare, class XBuf>
void stable_sort( RandIt first, RandIt last, Compare comp, XBuf & xbuf)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
size_type const len = size_type(last - first);
size_type const half_len = len/2 + (len&1);
size_type const half_len = size_type(len/2u + (len&1u));
if(std::size_t(xbuf.capacity() - xbuf.size()) >= half_len) {
merge_sort(first, last, comp, xbuf.data()+xbuf.size());
}
@@ -602,7 +625,8 @@ void unstable_sort( RandIt first, RandIt last
, Comp comp
, XBuf & xbuf)
{
heap_sort(first, last, comp);(void)xbuf;
heap_sort(first, last, comp);
::boost::movelib::ignore(xbuf);
}
template<class RandIt, class Compare, class XBuf>
@@ -611,8 +635,8 @@ void stable_merge
, Compare comp
, XBuf &xbuf)
{
BOOST_ASSERT(xbuf.empty());
typedef typename iterator_traits<RandIt>::size_type size_type;
assert(xbuf.empty());
typedef typename iter_size<RandIt>::type size_type;
size_type const len1 = size_type(middle-first);
size_type const len2 = size_type(last-middle);
size_type const l_min = min_value<size_type>(len1, len2);
@@ -633,7 +657,7 @@ void initialize_keys( RandIt first, RandIt last
, XBuf & xbuf)
{
unstable_sort(first, last, comp, xbuf);
BOOST_ASSERT(boost::movelib::is_sorted_and_unique(first, last, comp));
assert(boost::movelib::is_sorted_and_unique(first, last, comp));
}
template<class RandIt, class U>
@@ -654,11 +678,11 @@ Unsigned calculate_total_combined(Unsigned const len, Unsigned const l_prev_merg
{
typedef Unsigned size_type;
size_type const l_combined = 2*l_prev_merged;
size_type l_irreg_combined = len%l_combined;
size_type const l_combined = size_type(2*l_prev_merged);
size_type l_irreg_combined = size_type(len%l_combined);
size_type l_total_combined = len;
if(l_irreg_combined <= l_prev_merged){
l_total_combined -= l_irreg_combined;
l_total_combined = size_type(l_total_combined - l_irreg_combined);
l_irreg_combined = 0;
}
if(pl_irreg_combined)
@@ -685,13 +709,13 @@ void combine_params
typedef SizeType size_type;
//Initial parameters for selection sort blocks
l_irreg1 = l_prev_merged%l_block;
l_irreg2 = (l_combined-l_irreg1)%l_block;
BOOST_ASSERT(((l_combined-l_irreg1-l_irreg2)%l_block) == 0);
size_type const n_reg_block = (l_combined-l_irreg1-l_irreg2)/l_block;
l_irreg1 = size_type(l_prev_merged%l_block);
l_irreg2 = size_type((l_combined-l_irreg1)%l_block);
assert(((l_combined-l_irreg1-l_irreg2)%l_block) == 0);
size_type const n_reg_block = size_type((l_combined-l_irreg1-l_irreg2)/l_block);
n_block_a = l_prev_merged/l_block;
n_block_b = n_reg_block - n_block_a;
BOOST_ASSERT(n_reg_block>=n_block_a);
n_block_b = size_type(n_reg_block - n_block_a);
assert(n_reg_block>=n_block_a);
//Key initialization
if (do_initialize_keys) {
@@ -882,7 +906,7 @@ RandIt op_partial_merge_and_save_impl
first1 = last1;
}
else{
BOOST_ASSERT((last1-first1) == (buf_last1 - buf_first1));
assert((last1-first1) == (buf_last1 - buf_first1));
}
//Now merge from buffer
@@ -930,26 +954,28 @@ OutputIt op_merge_blocks_with_irreg
, RandIt2 &first_irr
, RandIt2 const last_irr
, OutputIt dest
, typename iterator_traits<RandIt>::size_type const l_block
, typename iterator_traits<RandIt>::size_type n_block_left
, typename iterator_traits<RandIt>::size_type min_check
, typename iterator_traits<RandIt>::size_type max_check
, typename iter_size<RandIt>::type const l_block
, typename iter_size<RandIt>::type n_block_left
, typename iter_size<RandIt>::type min_check
, typename iter_size<RandIt>::type max_check
, Compare comp, bool const is_stable, Op op)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
for(; n_block_left; --n_block_left, ++key_first, min_check -= min_check != 0, max_check -= max_check != 0){
for(; n_block_left; --n_block_left){
size_type next_key_idx = find_next_block(key_first, key_comp, first_reg, l_block, min_check, max_check, comp);
max_check = min_value<size_type>(max_value<size_type>(max_check, next_key_idx+size_type(2)), n_block_left);
max_check = min_value(max_value(max_check, size_type(next_key_idx+2u)), n_block_left);
RandIt const last_reg = first_reg + l_block;
RandIt first_min = first_reg + next_key_idx*l_block;
RandIt const last_min = first_min + l_block; (void)last_min;
RandIt first_min = first_reg + size_type(next_key_idx*l_block);
RandIt const last_min = first_min + l_block;
boost::movelib::ignore(last_min);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first_reg, last_reg, comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!next_key_idx || boost::movelib::is_sorted(first_min, last_min, comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((!next_key_idx || !comp(*first_reg, *first_min )));
OutputIt orig_dest = dest; (void)orig_dest;
OutputIt orig_dest = dest;
boost::movelib::ignore(orig_dest);
dest = next_key_idx ? op_partial_merge_and_swap(first_irr, last_irr, first_reg, last_reg, first_min, dest, comp, op, is_stable)
: op_partial_merge (first_irr, last_irr, first_reg, last_reg, dest, comp, op, is_stable);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(orig_dest, dest, comp));
@@ -968,6 +994,9 @@ OutputIt op_merge_blocks_with_irreg
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(orig_dest, dest, comp));
first_reg = last_reg;
++key_first;
min_check = size_type(min_check - (min_check != 0));
max_check = size_type(max_check - (max_check != 0));
}
return dest;
}
@@ -987,29 +1016,32 @@ void op_merge_blocks_left
( RandItKeys const key_first
, KeyCompare key_comp
, RandIt const first
, typename iterator_traits<RandIt>::size_type const l_block
, typename iterator_traits<RandIt>::size_type const l_irreg1
, typename iterator_traits<RandIt>::size_type const n_block_a
, typename iterator_traits<RandIt>::size_type const n_block_b
, typename iterator_traits<RandIt>::size_type const l_irreg2
, typename iter_size<RandIt>::type const l_block
, typename iter_size<RandIt>::type const l_irreg1
, typename iter_size<RandIt>::type const n_block_a
, typename iter_size<RandIt>::type const n_block_b
, typename iter_size<RandIt>::type const l_irreg2
, Compare comp, Op op)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
size_type const key_count = needed_keys_count(n_block_a, n_block_b); (void)key_count;
// BOOST_ASSERT(n_block_a || n_block_b);
typedef typename iter_size<RandIt>::type size_type;
size_type const key_count = needed_keys_count(n_block_a, n_block_b);
boost::movelib::ignore(key_count);
// assert(n_block_a || n_block_b);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted_and_unique(key_first, key_first + key_count, key_comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + key_count, key_comp, key_first[n_block_a]));
size_type n_block_b_left = n_block_b;
size_type n_block_a_left = n_block_a;
size_type n_block_left = n_block_b + n_block_a;
size_type n_block_left = size_type(n_block_b + n_block_a);
RandItKeys key_mid(key_first + n_block_a);
RandIt buffer = first - l_block;
RandIt first1 = first;
RandIt last1 = first1 + l_irreg1;
RandIt first2 = last1;
RandIt const irreg2 = first2 + n_block_left*l_block;
RandIt const irreg2 = first2 + size_type(n_block_left*l_block);
bool is_range1_A = true;
RandItKeys key_range2(key_first);
@@ -1018,12 +1050,14 @@ void op_merge_blocks_left
//Process all regular blocks before the irregular B block
////////////////////////////////////////////////////////////////////////////
size_type min_check = n_block_a == n_block_left ? 0u : n_block_a;
size_type max_check = min_value<size_type>(min_check+size_type(1), n_block_left);
for (; n_block_left; --n_block_left, ++key_range2, min_check -= min_check != 0, max_check -= max_check != 0) {
size_type max_check = min_value<size_type>(size_type(min_check+1u), n_block_left);
for (; n_block_left; --n_block_left) {
size_type const next_key_idx = find_next_block(key_range2, key_comp, first2, l_block, min_check, max_check, comp);
max_check = min_value<size_type>(max_value<size_type>(max_check, next_key_idx+size_type(2)), n_block_left);
RandIt const first_min = first2 + next_key_idx*l_block;
RandIt const last_min = first_min + l_block; (void)last_min;
max_check = min_value<size_type>(max_value<size_type>(max_check, size_type(next_key_idx+2u)), n_block_left);
RandIt const first_min = first2 + size_type(next_key_idx*l_block);
RandIt const last_min = first_min + l_block;
boost::movelib::ignore(last_min);
RandIt const last2 = first2 + l_block;
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first1, last1, comp));
@@ -1045,7 +1079,7 @@ void op_merge_blocks_left
(!is_buffer_middle && size_type(first1-buffer) == l_block && first2 == last1));
if(is_range1_A == is_range2_A){
BOOST_ASSERT((first1 == last1) || !comp(*first_min, last1[-1]));
assert((first1 == last1) || !comp(*first_min, last1[typename iterator_traits<RandIt>::difference_type(-1)]));
if(!is_buffer_middle){
buffer = op(forward_t(), first1, last1, buffer);
}
@@ -1068,7 +1102,8 @@ void op_merge_blocks_left
unmerged = op_partial_merge_and_save
(buffer, buffer+(last1-first1), first2, last2, first_min, buf_beg, buf_end, comp, op, is_range1_A);
}
(void)unmerged;
boost::movelib::ignore(unmerged);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first-l_block, unmerged, comp));
swap_and_update_key( key_next, key_range2, key_mid, first2, last2
@@ -1090,10 +1125,14 @@ void op_merge_blocks_left
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT( (is_range2_A && n_block_a_left) || (!is_range2_A && n_block_b_left));
is_range2_A ? --n_block_a_left : --n_block_b_left;
first2 = last2;
//Update context
++key_range2;
min_check = size_type(min_check - (min_check != 0));
max_check = size_type(max_check - (max_check != 0));
}
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_range2 + n_block_left, key_comp, *key_mid));
BOOST_ASSERT(!n_block_b_left);
assert(!n_block_b_left);
////////////////////////////////////////////////////////////////////////////
//Process remaining range 1 left before the irregular B block
@@ -1126,7 +1165,8 @@ void op_merge_blocks_left
buffer = op_merge_blocks_with_irreg
( key_range2, key_mid, key_comp, first2, first_irr2, last_irr2
, buffer, l_block, n_block_left, min_check, max_check, comp, false, op);
buffer = op(forward_t(), first_irr2, last_irr2, buffer);(void)buffer;
buffer = op(forward_t(), first_irr2, last_irr2, buffer);
boost::movelib::ignore(buffer);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first-l_block, buffer, comp));
}
@@ -1142,11 +1182,11 @@ void merge_blocks_left
( RandItKeys const key_first
, KeyCompare key_comp
, RandIt const first
, typename iterator_traits<RandIt>::size_type const l_block
, typename iterator_traits<RandIt>::size_type const l_irreg1
, typename iterator_traits<RandIt>::size_type const n_block_a
, typename iterator_traits<RandIt>::size_type const n_block_b
, typename iterator_traits<RandIt>::size_type const l_irreg2
, typename iter_size<RandIt>::type const l_block
, typename iter_size<RandIt>::type const l_irreg1
, typename iter_size<RandIt>::type const n_block_a
, typename iter_size<RandIt>::type const n_block_b
, typename iter_size<RandIt>::type const l_irreg2
, Compare comp
, bool const xbuf_used)
{
@@ -1173,17 +1213,18 @@ void merge_blocks_right
( RandItKeys const key_first
, KeyCompare key_comp
, RandIt const first
, typename iterator_traits<RandIt>::size_type const l_block
, typename iterator_traits<RandIt>::size_type const n_block_a
, typename iterator_traits<RandIt>::size_type const n_block_b
, typename iterator_traits<RandIt>::size_type const l_irreg2
, typename iter_size<RandIt>::type const l_block
, typename iter_size<RandIt>::type const n_block_a
, typename iter_size<RandIt>::type const n_block_b
, typename iter_size<RandIt>::type const l_irreg2
, Compare comp
, bool const xbuf_used)
{
typedef typename iter_size<RandIt>::type size_type;
merge_blocks_left
( (make_reverse_iterator)(key_first + needed_keys_count(n_block_a, n_block_b))
, inverse<KeyCompare>(key_comp)
, (make_reverse_iterator)(first + ((n_block_a+n_block_b)*l_block+l_irreg2))
, (make_reverse_iterator)(first + size_type((n_block_a+n_block_b)*l_block+l_irreg2))
, l_block
, l_irreg2
, n_block_b
@@ -1206,24 +1247,25 @@ void op_merge_blocks_with_buf
( RandItKeys key_first
, KeyCompare key_comp
, RandIt const first
, typename iterator_traits<RandIt>::size_type const l_block
, typename iterator_traits<RandIt>::size_type const l_irreg1
, typename iterator_traits<RandIt>::size_type const n_block_a
, typename iterator_traits<RandIt>::size_type const n_block_b
, typename iterator_traits<RandIt>::size_type const l_irreg2
, typename iter_size<RandIt>::type const l_block
, typename iter_size<RandIt>::type const l_irreg1
, typename iter_size<RandIt>::type const n_block_a
, typename iter_size<RandIt>::type const n_block_b
, typename iter_size<RandIt>::type const l_irreg2
, Compare comp
, Op op
, RandItBuf const buf_first)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
size_type const key_count = needed_keys_count(n_block_a, n_block_b); (void)key_count;
//BOOST_ASSERT(n_block_a || n_block_b);
typedef typename iter_size<RandIt>::type size_type;
size_type const key_count = needed_keys_count(n_block_a, n_block_b);
boost::movelib::ignore(key_count);
//assert(n_block_a || n_block_b);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted_and_unique(key_first, key_first + key_count, key_comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + key_count, key_comp, key_first[n_block_a]));
size_type n_block_b_left = n_block_b;
size_type n_block_a_left = n_block_a;
size_type n_block_left = n_block_b + n_block_a;
size_type n_block_left = size_type(n_block_b + n_block_a);
RandItKeys key_mid(key_first + n_block_a);
RandItBuf buffer = buf_first;
@@ -1231,9 +1273,10 @@ void op_merge_blocks_with_buf
RandIt first1 = first;
RandIt last1 = first1 + l_irreg1;
RandIt first2 = last1;
RandIt const first_irr2 = first2 + n_block_left*l_block;
RandIt const first_irr2 = first2 + size_type(n_block_left*l_block);
bool is_range1_A = true;
const size_type len = l_block * n_block_a + l_block * n_block_b + l_irreg1 + l_irreg2; (void)len;
const size_type len = size_type(l_block * n_block_a + l_block * n_block_b + l_irreg1 + l_irreg2);
boost::movelib::ignore(len);
RandItKeys key_range2(key_first);
@@ -1241,15 +1284,17 @@ void op_merge_blocks_with_buf
//Process all regular blocks before the irregular B block
////////////////////////////////////////////////////////////////////////////
size_type min_check = n_block_a == n_block_left ? 0u : n_block_a;
size_type max_check = min_value<size_type>(min_check+size_type(1), n_block_left);
for (; n_block_left; --n_block_left, ++key_range2, min_check -= min_check != 0, max_check -= max_check != 0) {
size_type max_check = min_value(size_type(min_check+1), n_block_left);
for (; n_block_left; --n_block_left) {
size_type const next_key_idx = find_next_block(key_range2, key_comp, first2, l_block, min_check, max_check, comp);
max_check = min_value<size_type>(max_value<size_type>(max_check, next_key_idx+size_type(2)), n_block_left);
RandIt first_min = first2 + next_key_idx*l_block;
RandIt const last_min = first_min + l_block; (void)last_min;
max_check = min_value(max_value(max_check, size_type(next_key_idx+2)), n_block_left);
RandIt first_min = first2 + size_type(next_key_idx*l_block);
RandIt const last_min = first_min + l_block;
boost::movelib::ignore(last_min);
RandIt const last2 = first2 + l_block;
bool const buffer_empty = buffer == buffer_end; (void)buffer_empty;
bool const buffer_empty = buffer == buffer_end;
boost::movelib::ignore(buffer_empty);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(buffer_empty ? boost::movelib::is_sorted(first1, last1, comp) : boost::movelib::is_sorted(buffer, buffer_end, comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first2, last2, comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_left || boost::movelib::is_sorted(first_min, last_min, comp));
@@ -1270,7 +1315,8 @@ void op_merge_blocks_with_buf
RandIt res = op(forward_t(), buffer, buffer_end, first1);
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_blocks_w_fwd: ", len);
buffer = buffer_end = buf_first;
BOOST_ASSERT(buffer_empty || res == last1); (void)res;
assert(buffer_empty || res == last1);
boost::movelib::ignore(res);
//swap_and_update_key(key_next, key_range2, key_mid, first2, last2, first_min);
buffer_end = buffer_and_update_key(key_next, key_range2, key_mid, first2, last2, first_min, buffer = buf_first, op);
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_blocks_w_swp: ", len);
@@ -1283,7 +1329,7 @@ void op_merge_blocks_with_buf
RandIt const unmerged = op_partial_merge_and_save(first1, last1, first2, last2, first_min, buffer, buffer_end, comp, op, is_range1_A);
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_blocks_w_mrs: ", len);
bool const is_range_1_empty = buffer == buffer_end;
BOOST_ASSERT(is_range_1_empty || (buffer_end-buffer) == (last1+l_block-unmerged));
assert(is_range_1_empty || (buffer_end-buffer) == (last1+l_block-unmerged));
if(is_range_1_empty){
buffer = buffer_end = buf_first;
first_min = last_min - (last2 - first2);
@@ -1302,12 +1348,17 @@ void op_merge_blocks_with_buf
first1 = unmerged;
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, unmerged, comp));
}
BOOST_ASSERT( (is_range2_A && n_block_a_left) || (!is_range2_A && n_block_b_left));
assert( (is_range2_A && n_block_a_left) || (!is_range2_A && n_block_b_left));
is_range2_A ? --n_block_a_left : --n_block_b_left;
last1 += l_block;
first2 = last2;
//Update context
++key_range2;
min_check = size_type(min_check - (min_check != 0));
max_check = size_type(max_check - (max_check != 0));
}
RandIt res = op(forward_t(), buffer, buffer_end, first1); (void)res;
RandIt res = op(forward_t(), buffer, buffer_end, first1);
boost::movelib::ignore(res);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, res, comp));
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_blocks_w_fwd: ", len);
@@ -1330,7 +1381,7 @@ void op_merge_blocks_with_buf
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_blocks_w_irg: ", len);
buffer_end = rbuf_beg.base();
BOOST_ASSERT((dest-last1) == (buffer_end-buffer));
assert((dest-last1) == (buffer_end-buffer));
op_merge_with_left_placed(is_range1_A ? first1 : last1, last1, dest, buffer, buffer_end, comp, op);
BOOST_MOVE_ADAPTIVE_SORT_PRINT_L2(" merge_with_left_plc:", len);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(first, last_irr2, comp));
@@ -1347,20 +1398,21 @@ void op_merge_blocks_with_buf
//////////////////////////////////
template<class RandIt, class Compare, class Op>
typename iterator_traits<RandIt>::size_type
typename iter_size<RandIt>::type
op_insertion_sort_step_left
( RandIt const first
, typename iterator_traits<RandIt>::size_type const length
, typename iterator_traits<RandIt>::size_type const step
, typename iter_size<RandIt>::type const length
, typename iter_size<RandIt>::type const step
, Compare comp, Op op)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
size_type const s = min_value<size_type>(step, AdaptiveSortInsertionSortThreshold);
size_type m = 0;
while((length - m) > s){
while(size_type(length - m) > s){
insertion_sort_op(first+m, first+m+s, first+m-s, comp, op);
m += s;
m = size_type(m + s);
}
insertion_sort_op(first+m, first+length, first+m-s, comp, op);
return s;
@@ -1369,15 +1421,15 @@ typename iterator_traits<RandIt>::size_type
template<class RandIt, class Compare, class Op>
void op_merge_right_step_once
( RandIt first_block
, typename iterator_traits<RandIt>::size_type const elements_in_blocks
, typename iterator_traits<RandIt>::size_type const l_build_buf
, typename iter_size<RandIt>::type const elements_in_blocks
, typename iter_size<RandIt>::type const l_build_buf
, Compare comp
, Op op)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
size_type restk = elements_in_blocks%(2*l_build_buf);
size_type p = elements_in_blocks - restk;
BOOST_ASSERT(0 == (p%(2*l_build_buf)));
typedef typename iter_size<RandIt>::type size_type;
size_type restk = size_type(elements_in_blocks%(2*l_build_buf));
size_type p = size_type(elements_in_blocks - restk);
assert(0 == (p%(2*l_build_buf)));
if(restk <= l_build_buf){
op(backward_t(),first_block+p, first_block+p+restk, first_block+p+restk+l_build_buf);
@@ -1386,8 +1438,10 @@ void op_merge_right_step_once
op_merge_right(first_block+p, first_block+p+l_build_buf, first_block+p+restk, first_block+p+restk+l_build_buf, comp, op);
}
while(p>0){
p -= 2*l_build_buf;
op_merge_right(first_block+p, first_block+p+l_build_buf, first_block+p+2*l_build_buf, first_block+p+3*l_build_buf, comp, op);
p = size_type(p - 2u*l_build_buf);
op_merge_right( first_block+p, first_block+size_type(p+l_build_buf)
, first_block+size_type(p+2*l_build_buf)
, first_block+size_type(p+3*l_build_buf), comp, op);
}
}
@@ -1402,20 +1456,20 @@ void op_merge_right_step_once
//////////////////////////////////
//////////////////////////////////
template<class RandIt, class Compare>
typename iterator_traits<RandIt>::size_type
typename iter_size<RandIt>::type
insertion_sort_step
( RandIt const first
, typename iterator_traits<RandIt>::size_type const length
, typename iterator_traits<RandIt>::size_type const step
, typename iter_size<RandIt>::type const length
, typename iter_size<RandIt>::type const step
, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
size_type const s = min_value<size_type>(step, AdaptiveSortInsertionSortThreshold);
size_type m = 0;
while((length - m) > s){
insertion_sort(first+m, first+m+s, comp);
m += s;
m = size_type(m + s);
}
insertion_sort(first+m, first+length, comp);
return s;
@@ -1431,36 +1485,40 @@ typename iterator_traits<RandIt>::size_type
//////////////////////////////////
//////////////////////////////////
template<class RandIt, class Compare, class Op>
typename iterator_traits<RandIt>::size_type
typename iter_size<RandIt>::type
op_merge_left_step_multiple
( RandIt first_block
, typename iterator_traits<RandIt>::size_type const elements_in_blocks
, typename iterator_traits<RandIt>::size_type l_merged
, typename iterator_traits<RandIt>::size_type const l_build_buf
, typename iterator_traits<RandIt>::size_type l_left_space
, typename iter_size<RandIt>::type const elements_in_blocks
, typename iter_size<RandIt>::type l_merged
, typename iter_size<RandIt>::type const l_build_buf
, typename iter_size<RandIt>::type l_left_space
, Compare comp
, Op op)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
for(; l_merged < l_build_buf && l_left_space >= l_merged; l_merged*=2){
typedef typename iter_size<RandIt>::type size_type;
for(; l_merged < l_build_buf && l_left_space >= l_merged; l_merged = size_type(l_merged*2u)){
size_type p0=0;
RandIt pos = first_block;
while((elements_in_blocks - p0) > 2*l_merged) {
op_merge_left(pos-l_merged, pos, pos+l_merged, pos+2*l_merged, comp, op);
op_merge_left(pos-l_merged, pos, pos+l_merged, pos+size_type(2*l_merged), comp, op);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(pos-l_merged, pos+l_merged, comp));
p0 += 2*l_merged;
p0 = size_type(p0 + 2u*l_merged);
pos = first_block+p0;
}
if((elements_in_blocks-p0) > l_merged) {
op_merge_left(pos-l_merged, pos, pos+l_merged, first_block+elements_in_blocks, comp, op);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(pos-l_merged, pos-l_merged+(first_block+elements_in_blocks-pos), comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT
(boost::movelib::is_sorted
(pos-l_merged, pos+size_type((first_block+elements_in_blocks-pos))-l_merged, comp));
}
else {
op(forward_t(), pos, first_block+elements_in_blocks, pos-l_merged);
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(boost::movelib::is_sorted(pos-l_merged, first_block+elements_in_blocks-l_merged, comp));
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT
(boost::movelib::is_sorted
(pos-l_merged, first_block+size_type(elements_in_blocks-l_merged), comp));
}
first_block -= l_merged;
l_left_space -= l_merged;
first_block -= l_merged;
l_left_space = size_type(l_left_space - l_merged);
}
return l_merged;
}
@@ -1470,6 +1528,10 @@ typename iterator_traits<RandIt>::size_type
} //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_SORT_MERGE_HPP

View File

@@ -22,6 +22,7 @@
#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 {

View File

@@ -23,42 +23,49 @@
#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::iterator_traits<RandomAccessIterator>::size_type size_type;
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 = 2 * (hole_index + 1);
size_type second_child = size_type(2u*(hole_index + 1u));
while (second_child < len) {
if (comp(*(first + second_child), *(first + (second_child - 1))))
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 = 2 * (second_child + 1);
second_child = size_type(2u * (second_child + 1u));
}
if (second_child == len) {
*(first + hole_index) = boost::move(*(first + (second_child - 1)));
hole_index = second_child - 1;
*(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 = (hole_index - 1) / 2;
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 = (hole_index - 1) / 2;
parent = size_type((hole_index - 1u) / 2u);
}
*(first + hole_index) = boost::move(value);
}
@@ -68,7 +75,7 @@ class heap_sort_helper
{
size_type const len = size_type(last - first);
if (len > 1) {
size_type parent = len/2u - 1u;
size_type parent = size_type(len/2u - 1u);
do {
value_type v(boost::move(*(first + parent)));
@@ -94,7 +101,7 @@ class heap_sort_helper
{
make_heap(first, last, comp);
sort_heap(first, last, comp);
BOOST_ASSERT(boost::movelib::is_sorted(first, last, comp));
assert(boost::movelib::is_sorted(first, last, comp));
}
};
@@ -106,6 +113,10 @@ BOOST_MOVE_FORCEINLINE void heap_sort(RandomAccessIterator first, RandomAccessIt
}} //namespace boost { namespace movelib{
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#include <boost/move/detail/config_end.hpp>
#endif //#ifndef BOOST_MOVE_DETAIL_HEAP_SORT_HPP

View File

@@ -33,6 +33,11 @@
#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
@@ -125,4 +130,8 @@ void insertion_sort_uninitialized_copy
}} //namespace boost { namespace movelib{
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#endif //#ifndef BOOST_MOVE_DETAIL_INSERT_SORT_HPP

View File

@@ -11,20 +11,25 @@
#ifndef BOOST_MOVE_MERGE_HPP
#define BOOST_MOVE_MERGE_HPP
#include <boost/move/algo/move.hpp>
#include <boost/move/adl_move_swap.hpp>
#include <boost/move/algo/detail/basic_op.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/detail/destruct_n.hpp>
#include <boost/move/algo/predicate.hpp>
#include <boost/move/algo/detail/search.hpp>
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/assert.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 iterator_traits<RandRawIt>::size_type>
template<class T, class RandRawIt = T*, class SizeType = typename iter_size<RandRawIt>::type>
class adaptive_xbuf
{
adaptive_xbuf(const adaptive_xbuf &);
@@ -38,28 +43,29 @@ class adaptive_xbuf
typedef RandRawIt iterator;
typedef SizeType size_type;
adaptive_xbuf()
BOOST_MOVE_FORCEINLINE adaptive_xbuf()
: m_ptr(), m_size(0), m_capacity(0)
{}
adaptive_xbuf(RandRawIt raw_memory, size_type capacity)
: m_ptr(raw_memory), m_size(0), m_capacity(capacity)
BOOST_MOVE_FORCEINLINE adaptive_xbuf(RandRawIt raw_memory, size_type cap)
: m_ptr(raw_memory), m_size(0), m_capacity(cap)
{}
template<class RandIt>
void move_assign(RandIt first, size_type n)
{
typedef typename iterator_traits<RandIt>::difference_type rand_diff_t;
if(n <= m_size){
boost::move(first, first+n, m_ptr);
size_type size = m_size;
while(size-- != n){
m_ptr[size].~T();
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+m_size, m_ptr);
boost::uninitialized_move(first+m_size, first+n, result);
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;
}
}
@@ -67,7 +73,7 @@ class adaptive_xbuf
template<class RandIt>
void push_back(RandIt first, size_type n)
{
BOOST_ASSERT(m_capacity - m_size >= n);
assert(m_capacity - m_size >= n);
boost::uninitialized_move(first, first+n, m_ptr+m_size);
m_size += n;
}
@@ -75,7 +81,7 @@ class adaptive_xbuf
template<class RandIt>
iterator add(RandIt it)
{
BOOST_ASSERT(m_size < m_capacity);
assert(m_size < m_capacity);
RandRawIt p_ret = m_ptr + m_size;
::new(&*p_ret) T(::boost::move(*it));
++m_size;
@@ -96,35 +102,35 @@ class adaptive_xbuf
}
}
void set_size(size_type size)
BOOST_MOVE_FORCEINLINE void set_size(size_type sz)
{
m_size = size;
m_size = sz;
}
void shrink_to_fit(size_type const size)
void shrink_to_fit(size_type const sz)
{
if(m_size > size){
for(size_type szt_i = size; szt_i != m_size; ++szt_i){
if(m_size > sz){
for(size_type szt_i = sz; szt_i != m_size; ++szt_i){
m_ptr[szt_i].~T();
}
m_size = size;
m_size = sz;
}
}
void initialize_until(size_type const size, T &t)
void initialize_until(size_type const sz, T &t)
{
BOOST_ASSERT(m_size < m_capacity);
if(m_size < size){
BOOST_TRY
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 != size; ++m_size){
for(; m_size != sz; ++m_size){
::new((void*)&m_ptr[m_size]) T(::boost::move(m_ptr[m_size-1]));
}
t = ::boost::move(m_ptr[m_size-1]);
}
BOOST_CATCH(...)
BOOST_MOVE_CATCH(...)
{
while(m_size)
{
@@ -132,28 +138,28 @@ class adaptive_xbuf
m_ptr[m_size].~T();
}
}
BOOST_CATCH_END
BOOST_MOVE_CATCH_END
}
}
private:
template<class RIt>
static bool is_raw_ptr(RIt)
BOOST_MOVE_FORCEINLINE static bool is_raw_ptr(RIt)
{
return false;
}
static bool is_raw_ptr(T*)
BOOST_MOVE_FORCEINLINE static bool is_raw_ptr(T*)
{
return true;
}
public:
template<class U>
bool supports_aligned_trailing(size_type size, size_type trail_count) const
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()+size));
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);
@@ -162,43 +168,43 @@ class adaptive_xbuf
}
template<class U>
U *aligned_trailing() const
BOOST_MOVE_FORCEINLINE U *aligned_trailing() const
{
return this->aligned_trailing<U>(this->size());
}
template<class U>
U *aligned_trailing(size_type pos) const
BOOST_MOVE_FORCEINLINE U *aligned_trailing(size_type pos) const
{
uintptr_t u_addr = uintptr_t(&*(this->data()+pos));
u_addr = ((u_addr + sizeof(U)-1)/sizeof(U))*sizeof(U);
return (U*)u_addr;
}
~adaptive_xbuf()
BOOST_MOVE_FORCEINLINE ~adaptive_xbuf()
{
this->clear();
}
size_type capacity() const
BOOST_MOVE_FORCEINLINE size_type capacity() const
{ return m_capacity; }
iterator data() const
BOOST_MOVE_FORCEINLINE iterator data() const
{ return m_ptr; }
iterator begin() const
BOOST_MOVE_FORCEINLINE iterator begin() const
{ return m_ptr; }
iterator end() const
BOOST_MOVE_FORCEINLINE iterator end() const
{ return m_ptr+m_size; }
size_type size() const
BOOST_MOVE_FORCEINLINE size_type size() const
{ return m_size; }
bool empty() const
BOOST_MOVE_FORCEINLINE bool empty() const
{ return !m_size; }
void clear()
BOOST_MOVE_FORCEINLINE void clear()
{
this->shrink_to_fit(0u);
}
@@ -226,8 +232,9 @@ class range_xbuf
template<class RandIt>
void move_assign(RandIt first, size_type n)
{
BOOST_ASSERT(size_type(n) <= size_type(m_cap-m_first));
m_last = Op()(forward_t(), first, first+n, m_first);
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()
@@ -262,10 +269,10 @@ class range_xbuf
return pos;
}
void set_size(size_type size)
void set_size(size_type sz)
{
m_last = m_first;
m_last += size;
m_last += sz;
}
private:
@@ -307,26 +314,28 @@ Unsigned gcd(Unsigned x, Unsigned y)
else{
Unsigned z = 1;
while((!(x&1)) & (!(y&1))){
z <<=1, x>>=1, y>>=1;
z = Unsigned(z << 1);
x = Unsigned(x >> 1);
y = Unsigned(y >> 1);
}
while(x && y){
if(!(x&1))
x >>=1;
x = Unsigned(x >> 1);
else if(!(y&1))
y >>=1;
y = Unsigned (y >> 1);
else if(x >=y)
x = (x-y) >> 1;
x = Unsigned((x-y) >> 1u);
else
y = (y-x) >> 1;
y = Unsigned((y-x) >> 1);
}
return z*(x+y);
return Unsigned(z*(x+y));
}
}
template<typename RandIt>
RandIt rotate_gcd(RandIt first, RandIt middle, RandIt last)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
typedef typename iterator_traits<RandIt>::value_type value_type;
if(first == middle)
@@ -350,7 +359,7 @@ RandIt rotate_gcd(RandIt first, RandIt middle, RandIt last)
*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);
it_k = left > middle_pos ? it_j + middle_pos : first + middle_pos - left;
} while(it_k != it_i);
*it_j = boost::move(temp);
}
@@ -358,57 +367,6 @@ RandIt rotate_gcd(RandIt first, RandIt middle, RandIt last)
return ret;
}
template <class RandIt, class T, class Compare>
RandIt lower_bound
(RandIt first, const RandIt last, const T& key, Compare comp)
{
typedef typename iterator_traits
<RandIt>::size_type size_type;
size_type len = size_type(last - first);
RandIt middle;
while (len) {
size_type step = len >> 1;
middle = first;
middle += step;
if (comp(*middle, key)) {
first = ++middle;
len -= step + 1;
}
else{
len = step;
}
}
return first;
}
template <class RandIt, class T, class Compare>
RandIt upper_bound
(RandIt first, const RandIt last, const T& key, Compare comp)
{
typedef typename iterator_traits
<RandIt>::size_type size_type;
size_type len = size_type(last - first);
RandIt middle;
while (len) {
size_type step = len >> 1;
middle = first;
middle += step;
if (!comp(key, *middle)) {
first = ++middle;
len -= step + 1;
}
else{
len = step;
}
}
return first;
}
template<class RandIt, class Compare, class Op>
void op_merge_left( RandIt buf_first
, RandIt first1
@@ -521,7 +479,7 @@ void op_buffered_merge
, Buf &xbuf)
{
if(first != middle && middle != last && comp(*middle, middle[-1])){
typedef typename iterator_traits<RandIt>::size_type size_type;
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){
@@ -586,11 +544,11 @@ static const std::size_t MergeBufferlessONLogNRotationThreshold = 16u;
template <class RandIt, class Compare>
void merge_bufferless_ONlogN_recursive
( RandIt first, RandIt middle, RandIt last
, typename iterator_traits<RandIt>::size_type len1
, typename iterator_traits<RandIt>::size_type len2
, typename iter_size<RandIt>::type len1
, typename iter_size<RandIt>::type len2
, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
while(1) {
//trivial cases
@@ -629,16 +587,17 @@ void merge_bufferless_ONlogN_recursive
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 = len11+len22;
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);
merge_bufferless_ONlogN_recursive(first, first_cut, new_middle, len11, len22, comp);
first = new_middle;
middle = second_cut;
len1 -= len11;
len2 -= len22;
len1 = size_type(len1-len11);
len2 = size_type(len2-len22);
}
else {
merge_bufferless_ONlogN_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
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;
@@ -652,7 +611,7 @@ void merge_bufferless_ONlogN_recursive
template<class RandIt, class Compare>
void merge_bufferless_ONlogN(RandIt first, RandIt middle, RandIt last, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
merge_bufferless_ONlogN_recursive
(first, middle, last, size_type(middle - first), size_type(last - middle), comp);
}
@@ -675,12 +634,12 @@ void op_merge_with_right_placed
, InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
, Compare comp, Op op)
{
BOOST_ASSERT((last - first) == (r_first - dest_first));
assert((last - first) == (r_first - dest_first));
while ( first != last ) {
if (r_first == r_last) {
InputOutIterator end = op(forward_t(), first, last, dest_first);
BOOST_ASSERT(end == r_last);
(void)end;
assert(end == r_last);
boost::movelib::ignore(end);
return;
}
else if (comp(*r_first, *first)) {
@@ -712,12 +671,12 @@ void op_merge_with_left_placed
, BidirIterator const r_first, BidirIterator r_last
, Compare comp, Op op)
{
BOOST_ASSERT((dest_last - last) == (r_last - r_first));
assert((dest_last - last) == (r_last - r_first));
while( r_first != r_last ) {
if(first == last) {
BidirOutIterator res = op(backward_t(), r_first, r_last, dest_last);
BOOST_ASSERT(last == res);
(void)res;
assert(last == res);
boost::movelib::ignore(res);
return;
}
--r_last;
@@ -766,7 +725,7 @@ void uninitialized_merge_with_right_placed
, InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
, Compare comp)
{
BOOST_ASSERT((last - first) == (r_first - dest_first));
assert((last - first) == (r_first - dest_first));
typedef typename iterator_traits<InputOutIterator>::value_type value_type;
InputOutIterator const original_r_first = r_first;
@@ -780,8 +739,8 @@ void uninitialized_merge_with_right_placed
}
d.release();
InputOutIterator end = ::boost::move(first, last, original_r_first);
BOOST_ASSERT(end == r_last);
(void)end;
assert(end == r_last);
boost::movelib::ignore(end);
return;
}
else if (comp(*r_first, *first)) {
@@ -800,61 +759,16 @@ void uninitialized_merge_with_right_placed
merge_with_right_placed(first, last, original_r_first, r_first, r_last, comp);
}
/*
// [r_first, r_last) are already in the right part of the destination range.
// [dest_first, r_first) is uninitialized memory
template <class Compare, class BidirOutIterator, class BidirIterator>
void uninitialized_merge_with_left_placed
( BidirOutIterator dest_first, BidirOutIterator r_first, BidirOutIterator r_last
, BidirIterator first, BidirIterator last
, Compare comp)
{
BOOST_ASSERT((last - first) == (r_last - r_first));
typedef typename iterator_traits<BidirOutIterator>::value_type value_type;
BidirOutIterator const original_r_last = r_last;
destruct_n<value_type> d(&*dest_last);
while ( first != last && dest_first != original_r_first ) {
if (r_first == r_last) {
for(; dest_first != original_r_first; ++dest_first, ++first){
::new(&*dest_first) value_type(::boost::move(*first));
d.incr();
}
d.release();
BidirOutIterator end = ::boost::move(first, last, original_r_first);
BOOST_ASSERT(end == r_last);
(void)end;
return;
}
else if (comp(*r_first, *first)) {
::new(&*dest_first) value_type(::boost::move(*r_first));
d.incr();
++r_first;
}
else {
::new(&*dest_first) value_type(::boost::move(*first));
d.incr();
++first;
}
++dest_first;
}
d.release();
merge_with_right_placed(first, last, original_r_first, r_first, r_last, comp);
}
*/
/// This is a helper function for the merge routines.
template<typename BidirectionalIterator1, typename BidirectionalIterator2>
BidirectionalIterator1
rotate_adaptive(BidirectionalIterator1 first,
BidirectionalIterator1 middle,
BidirectionalIterator1 last,
typename iterator_traits<BidirectionalIterator1>::size_type len1,
typename iterator_traits<BidirectionalIterator1>::size_type len2,
typename iter_size<BidirectionalIterator1>::type len1,
typename iter_size<BidirectionalIterator1>::type len2,
BidirectionalIterator2 buffer,
typename iterator_traits<BidirectionalIterator1>::size_type buffer_size)
typename iter_size<BidirectionalIterator1>::type buffer_size)
{
if (len1 > len2 && len2 <= buffer_size)
{
@@ -889,58 +803,57 @@ template<typename BidirectionalIterator,
(BidirectionalIterator first,
BidirectionalIterator middle,
BidirectionalIterator last,
typename iterator_traits<BidirectionalIterator>::size_type len1,
typename iterator_traits<BidirectionalIterator>::size_type len2,
typename iter_size<BidirectionalIterator>::type len1,
typename iter_size<BidirectionalIterator>::type len2,
Pointer buffer,
typename iterator_traits<BidirectionalIterator>::size_type buffer_size,
typename iter_size<BidirectionalIterator>::type buffer_size,
Compare comp)
{
typedef typename iterator_traits<BidirectionalIterator>::size_type size_type;
typedef typename iter_size<BidirectionalIterator>::type size_type;
//trivial cases
if (!len2 || !len1) {
return;
// no-op
}
else if (len1 <= buffer_size || len2 <= buffer_size)
{
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);
return;
}
else if (size_type(len1 + len2) < MergeBufferlessONLogNRotationThreshold) {
merge_bufferless_ON2(first, middle, last, comp);
return;
}
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 = second_cut - middle;
}
else
{
len22 = len2 / 2;
second_cut += len22;
first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp);
len11 = first_cut - first;
}
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,
len1 - len11, len2 - len22, buffer, buffer_size, comp);
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);
}
}
@@ -950,10 +863,10 @@ void merge_adaptive_ONlogN(BidirectionalIterator first,
BidirectionalIterator last,
Compare comp,
RandRawIt uninitialized,
typename iterator_traits<BidirectionalIterator>::size_type uninitialized_len)
typename iter_size<BidirectionalIterator>::type uninitialized_len)
{
typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
typedef typename iterator_traits<BidirectionalIterator>::size_type size_type;
typedef typename iter_size<BidirectionalIterator>::type size_type;
if (first == middle || middle == last)
return;
@@ -973,8 +886,11 @@ void merge_adaptive_ONlogN(BidirectionalIterator first,
}
}
} //namespace movelib {
} //namespace boost {
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#endif //#define BOOST_MOVE_MERGE_HPP

View File

@@ -34,6 +34,11 @@
#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 {
@@ -44,7 +49,7 @@ static const unsigned MergeSortInsertionSortThreshold = 16;
template <class RandIt, class Compare>
void inplace_stable_sort(RandIt first, RandIt last, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iter_size<RandIt>::type size_type;
if (size_type(last - first) <= size_type(MergeSortInsertionSortThreshold)) {
insertion_sort(first, last, comp);
return;
@@ -62,14 +67,14 @@ template<class RandIt, class RandIt2, class Compare>
void merge_sort_copy( RandIt first, RandIt last
, RandIt2 dest, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
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 = count/2;
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
@@ -84,7 +89,7 @@ void merge_sort_uninitialized_copy( RandIt first, RandIt last
, RandItRaw uninitialized
, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
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);
@@ -95,7 +100,7 @@ void merge_sort_uninitialized_copy( RandIt first, RandIt last
size_type const half = count/2;
merge_sort_uninitialized_copy(first + half, last, uninitialized + half, comp);
destruct_n<value_type, RandItRaw> d(uninitialized+half);
d.incr(count-half);
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
@@ -109,16 +114,16 @@ template<class RandIt, class RandItRaw, class Compare>
void merge_sort( RandIt first, RandIt last, Compare comp
, RandItRaw uninitialized)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
typedef typename iterator_traits<RandIt>::value_type value_type;
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 = count/2;
size_type const rest = count - half;
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;
@@ -137,15 +142,15 @@ void merge_sort( RandIt first, RandIt last, Compare comp
template<class RandIt, class RandItRaw, class Compare>
void merge_sort_with_constructed_buffer( RandIt first, RandIt last, Compare comp, RandItRaw buffer)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
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 = count/2;
size_type const rest = count - half;
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;
@@ -161,12 +166,12 @@ 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 iterator_traits<RandIt>::size_type size_type;
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 = (last - first) / 2;
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);
@@ -202,6 +207,10 @@ void stable_sort_adaptive_ONlogN2(BidirectionalIterator first,
}} //namespace boost { namespace movelib{
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#include <boost/move/detail/config_end.hpp>
#endif //#ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP

View File

@@ -47,6 +47,7 @@
#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>
@@ -56,6 +57,11 @@
#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 {
@@ -109,7 +115,7 @@ namespace pdqsort_detail {
template<class Iter, class Compare>
inline bool partial_insertion_sort(Iter begin, Iter end, Compare comp) {
typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
typedef typename boost::movelib::iterator_traits<Iter>::size_type size_type;
typedef typename boost::movelib:: iter_size<Iter>::type size_type;
if (begin == end) return true;
size_type limit = 0;
@@ -186,7 +192,8 @@ namespace pdqsort_detail {
// Put the pivot in the right place.
Iter pivot_pos = first - 1;
*begin = boost::move(*pivot_pos);
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);
@@ -225,10 +232,10 @@ namespace pdqsort_detail {
template<class Iter, class Compare>
void pdqsort_loop( Iter begin, Iter end, Compare comp
, typename boost::movelib::iterator_traits<Iter>::size_type bad_allowed
, typename boost::movelib:: iter_size<Iter>::type bad_allowed
, bool leftmost = true)
{
typedef typename boost::movelib::iterator_traits<Iter>::size_type size_type;
typedef typename boost::movelib:: iter_size<Iter>::type size_type;
// Use a while loop for tail recursion elimination.
while (true) {
@@ -322,13 +329,17 @@ template<class Iter, class Compare>
void pdqsort(Iter begin, Iter end, Compare comp)
{
if (begin == end) return;
typedef typename boost::movelib::iterator_traits<Iter>::size_type size_type;
typedef typename boost::movelib:: iter_size<Iter>::type size_type;
pdqsort_detail::pdqsort_loop<Iter, Compare>(begin, end, comp, pdqsort_detail::log2(size_type(end - begin)));
}
} //namespace movelib {
} //namespace boost {
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
#include <boost/move/detail/config_end.hpp>
#endif //BOOST_MOVE_ALGO_PDQSORT_HPP

View File

@@ -0,0 +1,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

View File

@@ -15,8 +15,12 @@
#include <boost/move/iterator.hpp>
#include <boost/move/utility_core.hpp>
namespace boost {
#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>
@@ -174,7 +178,7 @@ ForwardOutputIt1 inplace_set_unique_difference
++first2;
}
else if (comp(*first1, *first2)){
//skip any adjacent equivalent elementin range 1
//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
@@ -199,7 +203,9 @@ ForwardOutputIt1 inplace_set_unique_difference
return first1;
}
#if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
#pragma GCC diagnostic pop
#endif
} //namespace movelib {
} //namespace boost {

View File

@@ -27,7 +27,10 @@
#include <boost/move/utility_core.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/move/detail/addressof.hpp>
#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
#include <algorithm>
#endif
namespace boost {
@@ -118,20 +121,20 @@ F uninitialized_move(I f, I l, F r
typedef typename boost::movelib::iterator_traits<I>::value_type input_value_type;
F back = r;
BOOST_TRY{
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_CATCH(...){
BOOST_MOVE_CATCH(...){
for (; back != r; ++back){
boost::movelib::iterator_to_raw_pointer(back)->~input_value_type();
}
BOOST_RETHROW;
BOOST_MOVE_RETHROW;
}
BOOST_CATCH_END
BOOST_MOVE_CATCH_END
return r;
}

View File

@@ -16,7 +16,7 @@
#include <boost/move/algo/detail/basic_op.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/detail/destruct_n.hpp>
#include <boost/assert.hpp>
#include <cassert>
namespace boost {
namespace movelib {
@@ -24,19 +24,19 @@ namespace movelib {
template<class Comp>
struct antistable
{
explicit antistable(Comp &comp)
BOOST_MOVE_FORCEINLINE explicit antistable(Comp &comp)
: m_comp(comp)
{}
antistable(const antistable & other)
BOOST_MOVE_FORCEINLINE antistable(const antistable & other)
: m_comp(other.m_comp)
{}
template<class U, class V>
bool operator()(const U &u, const V & v)
BOOST_MOVE_FORCEINLINE bool operator()(const U &u, const V & v)
{ return !m_comp(v, u); }
const Comp &get() const
BOOST_MOVE_FORCEINLINE const Comp &get() const
{ return m_comp; }
private:
@@ -56,15 +56,15 @@ template <class Comp>
class negate
{
public:
negate()
BOOST_MOVE_FORCEINLINE negate()
{}
explicit negate(Comp comp)
BOOST_MOVE_FORCEINLINE explicit negate(Comp comp)
: m_comp(comp)
{}
template <class T1, class T2>
bool operator()(const T1& l, const T2& r)
BOOST_MOVE_FORCEINLINE bool operator()(const T1& l, const T2& r)
{
return !m_comp(l, r);
}
@@ -78,15 +78,15 @@ template <class Comp>
class inverse
{
public:
inverse()
BOOST_MOVE_FORCEINLINE inverse()
{}
explicit inverse(Comp comp)
BOOST_MOVE_FORCEINLINE explicit inverse(Comp comp)
: m_comp(comp)
{}
template <class T1, class T2>
bool operator()(const T1& l, const T2& r)
BOOST_MOVE_FORCEINLINE bool operator()(const T1& l, const T2& r)
{
return m_comp(r, l);
}

View File

@@ -27,7 +27,6 @@
#include <boost/move/utility_core.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/algo/move.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <algorithm> //copy, copy_backward
#include <memory> //uninitialized_copy

View File

@@ -58,6 +58,7 @@
#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)
@@ -218,6 +219,10 @@
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 {
@@ -229,6 +234,11 @@
::boost::move((BASE_TYPE&)(ARG))
//
#define BOOST_MOVE_TO_LV(ARG) \
::boost::move_detail::unrv(ARG)
//
//////////////////////////////////////////////////////////////////////////////
//
// BOOST_MOVABLE_BUT_NOT_COPYABLE
@@ -480,6 +490,17 @@
::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 {

View File

@@ -23,7 +23,6 @@
#include <boost/move/detail/workaround.hpp>
#include <boost/move/detail/unique_ptr_meta_utils.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/static_assert.hpp>
#include <cstddef> //For std::size_t,std::nullptr_t
@@ -112,6 +111,33 @@ 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
@@ -163,7 +189,7 @@ struct default_delete
{
//If T is not an array type, U derives from T
//and T has no virtual destructor, then you have a problem
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
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.
@@ -178,7 +204,7 @@ struct default_delete
{
//If T is not an array type, U derives from T
//and T has no virtual destructor, then you have a problem
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
BOOST_MOVE_STATIC_ASSERT(( !bmupd::missing_virtual_destructor<default_delete, U>::value ));
return *this;
}
@@ -195,10 +221,10 @@ struct default_delete
operator()(U* ptr) const BOOST_NOEXCEPT
{
//U must be a complete type
BOOST_STATIC_ASSERT(sizeof(U) > 0);
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_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
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>());
}
@@ -206,7 +232,7 @@ struct default_delete
//! <b>Effects</b>: Same as <tt>(*this)(static_cast<element_type*>(nullptr))</tt>.
//!
void operator()(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) const BOOST_NOEXCEPT
{ BOOST_STATIC_ASSERT(sizeof(element_type) > 0); }
{ BOOST_MOVE_STATIC_ASSERT(sizeof(element_type) > 0); }
};
} //namespace movelib {

View File

@@ -0,0 +1,61 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_MOVE_DETAIL_ADDRESSOF_HPP
#define BOOST_MOVE_DETAIL_ADDRESSOF_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/move/detail/workaround.hpp>
namespace boost {
namespace move_detail {
#if defined(BOOST_MSVC_FULL_VER) && BOOST_MSVC_FULL_VER >= 190024215
#define BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
#elif defined(BOOST_GCC) && BOOST_GCC >= 70000
#define BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
#elif defined(__has_builtin)
#if __has_builtin(__builtin_addressof)
#define BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
#endif
#endif
#ifdef BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
template<class T>
BOOST_MOVE_FORCEINLINE T *addressof( T & v ) BOOST_NOEXCEPT
{
return __builtin_addressof(v);
}
#else //BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
template <typename T>
BOOST_MOVE_FORCEINLINE T* addressof(T& obj)
{
return static_cast<T*>(
static_cast<void*>(
const_cast<char*>(
&reinterpret_cast<const volatile char&>(obj)
)));
}
#endif //BOOST_MOVE_HAS_BUILTIN_ADDRESSOF
} //namespace move_detail {
} //namespace boost {
#endif //#ifndef BOOST_MOVE_DETAIL_ADDRESSOF_HPP

View File

@@ -13,6 +13,7 @@
#ifdef BOOST_MSVC
# pragma warning (push)
# pragma warning (disable : 4619) // there is no warning number 'XXXX'
# pragma warning (disable : 4324) // structure was padded due to __declspec(align())
# pragma warning (disable : 4675) // "function": resolved overload was found by argument-dependent lookup
# pragma warning (disable : 4996) // "function": was declared deprecated (_CRT_SECURE_NO_DEPRECATE/_SCL_SECURE_NO_WARNINGS)

View File

@@ -0,0 +1,36 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2015. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_MOVE_DETAIL_FORCE_CAST_HPP
#define BOOST_MOVE_DETAIL_FORCE_CAST_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/move/detail/workaround.hpp>
namespace boost {
namespace move_detail {
template <typename T>
BOOST_MOVE_FORCEINLINE T force_ptr(const volatile void *p)
{
return static_cast<T>(const_cast<void*>(p));
}
} //namespace move_detail {
} //namespace boost {
#endif //#ifndef BOOST_MOVE_DETAIL_FORCE_CAST_HPP

View File

@@ -336,6 +336,18 @@ namespace move_detail {
#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

View File

@@ -27,11 +27,11 @@ namespace movelib {
namespace detail {
template <class T>
inline T* iterator_to_pointer(T* i)
BOOST_MOVE_FORCEINLINE T* iterator_to_pointer(T* i)
{ return i; }
template <class Iterator>
inline typename boost::movelib::iterator_traits<Iterator>::pointer
BOOST_MOVE_FORCEINLINE typename boost::movelib::iterator_traits<Iterator>::pointer
iterator_to_pointer(const Iterator &i)
{ return i.operator->(); }
@@ -46,7 +46,7 @@ struct iterator_to_element_ptr
} //namespace detail {
template <class Iterator>
inline typename boost::movelib::detail::iterator_to_element_ptr<Iterator>::type
BOOST_MOVE_FORCEINLINE typename boost::movelib::detail::iterator_to_element_ptr<Iterator>::type
iterator_to_raw_pointer(const Iterator &i)
{
return ::boost::movelib::to_raw_pointer

View File

@@ -22,10 +22,44 @@
# 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;
@@ -34,20 +68,73 @@ 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 Iterator::difference_type difference_type;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename Iterator::iterator_category iterator_category;
typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
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>
@@ -58,7 +145,6 @@ struct iterator_traits<T*>
typedef T* pointer;
typedef T& reference;
typedef std::random_access_iterator_tag iterator_category;
typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
};
template<class T>
@@ -69,9 +155,23 @@ struct iterator_traits<const T*>
typedef const T* pointer;
typedef const T& reference;
typedef std::random_access_iterator_tag iterator_category;
typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
};
}} //namespace boost { namespace movelib{
}} //namespace boost::movelib
#endif //
#include <boost/move/detail/type_traits.hpp>
namespace boost {
namespace movelib {
template<class T>
struct iter_size
: boost::move_detail::
make_unsigned<typename iter_difference<T>::type >
{};
}} //namespace boost move_detail {
#endif //#ifndef BOOST_MOVE_DETAIL_ITERATOR_TRAITS_HPP

View File

@@ -21,6 +21,7 @@
#include <boost/move/detail/workaround.hpp> //forceinline
#include <boost/move/detail/meta_utils_core.hpp>
#include <cstddef> //for std::size_t
#include <boost/move/detail/addressof.hpp>
//Small meta-typetraits to support move
@@ -56,8 +57,8 @@ struct apply
template< bool C_ >
struct bool_ : integral_constant<bool, C_>
{
operator bool() const { return C_; }
bool operator()() const { return C_; }
BOOST_MOVE_FORCEINLINE operator bool() const { return C_; }
BOOST_MOVE_FORCEINLINE bool operator()() const { return C_; }
};
typedef bool_<true> true_;
@@ -70,6 +71,10 @@ struct nat{};
struct nat2{};
struct nat3{};
template <unsigned N>
struct natN
{};
//////////////////////////////////////
// yes_type/no_type
//////////////////////////////////////
@@ -220,7 +225,7 @@ struct identity
{
typedef T type;
typedef typename add_const_lvalue_reference<T>::type reference;
reference operator()(reference t)
BOOST_MOVE_FORCEINLINE reference operator()(reference t) const
{ return t; }
};
@@ -241,36 +246,7 @@ struct is_class_or_union
//////////////////////////////////////
// addressof
//////////////////////////////////////
template<class T>
struct addr_impl_ref
{
T & v_;
BOOST_MOVE_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {}
BOOST_MOVE_FORCEINLINE operator T& () const { return v_; }
private:
addr_impl_ref & operator=(const addr_impl_ref &);
};
template<class T>
struct addressof_impl
{
BOOST_MOVE_FORCEINLINE static T * f( T & v, long )
{
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
BOOST_MOVE_FORCEINLINE static T * f( T * v, int )
{ return v; }
};
template<class T>
BOOST_MOVE_FORCEINLINE T * addressof( T & v )
{
return ::boost::move_detail::addressof_impl<T>::f
( ::boost::move_detail::addr_impl_ref<T>( v ), 0 );
}
//////////////////////////////////////
// has_pointer_type

View 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

View File

@@ -28,6 +28,14 @@
namespace boost {
namespace movelib {
template<class I>
BOOST_MOVE_FORCEINLINE typename iterator_traits<I>::pointer iterator_arrow_result(const I &i)
{ return i.operator->(); }
template<class T>
BOOST_MOVE_FORCEINLINE T * iterator_arrow_result(T *p)
{ return p; }
template<class It>
class reverse_iterator
{
@@ -41,37 +49,38 @@ class reverse_iterator
typedef It iterator_type;
reverse_iterator()
BOOST_MOVE_FORCEINLINE reverse_iterator()
: m_current() //Value initialization to achieve "null iterators" (N3644)
{}
explicit reverse_iterator(It r)
BOOST_MOVE_FORCEINLINE explicit reverse_iterator(It r)
: m_current(r)
{}
reverse_iterator(const reverse_iterator& r)
BOOST_MOVE_FORCEINLINE reverse_iterator(const reverse_iterator& r)
: m_current(r.base())
{}
template<class OtherIt>
reverse_iterator( const reverse_iterator<OtherIt>& r
, typename boost::move_detail::enable_if_convertible<OtherIt, It>::type* =0
BOOST_MOVE_FORCEINLINE
reverse_iterator( const reverse_iterator<OtherIt>& r
, typename boost::move_detail::enable_if_convertible<OtherIt, It>::type* =0
)
: m_current(r.base())
{}
reverse_iterator & operator=( const reverse_iterator& r)
BOOST_MOVE_FORCEINLINE reverse_iterator & operator=( const reverse_iterator& r)
{ m_current = r.base(); return *this; }
template<class OtherIt>
typename boost::move_detail::enable_if_convertible<OtherIt, It, reverse_iterator &>::type
BOOST_MOVE_FORCEINLINE typename boost::move_detail::enable_if_convertible<OtherIt, It, reverse_iterator &>::type
operator=( const reverse_iterator<OtherIt>& r)
{ m_current = r.base(); return *this; }
It base() const
BOOST_MOVE_FORCEINLINE It base() const
{ return m_current; }
reference operator*() const
BOOST_MOVE_FORCEINLINE reference operator*() const
{
It temp(m_current);
--temp;
@@ -79,78 +88,78 @@ class reverse_iterator
return r;
}
pointer operator->() const
BOOST_MOVE_FORCEINLINE pointer operator->() const
{
It temp(m_current);
--temp;
return iterator_arrow_result(temp);
return (iterator_arrow_result)(temp);
}
reference operator[](difference_type off) const
BOOST_MOVE_FORCEINLINE reference operator[](difference_type off) const
{
return this->m_current[-off - 1];
return this->m_current[difference_type(-off - 1)];
}
reverse_iterator& operator++()
BOOST_MOVE_FORCEINLINE reverse_iterator& operator++()
{
--m_current;
return *this;
}
reverse_iterator operator++(int)
BOOST_MOVE_FORCEINLINE reverse_iterator operator++(int)
{
reverse_iterator temp((*this));
--m_current;
return temp;
}
reverse_iterator& operator--()
BOOST_MOVE_FORCEINLINE reverse_iterator& operator--()
{
++m_current;
return *this;
}
reverse_iterator operator--(int)
BOOST_MOVE_FORCEINLINE reverse_iterator operator--(int)
{
reverse_iterator temp((*this));
++m_current;
return temp;
}
friend bool operator==(const reverse_iterator& l, const reverse_iterator& r)
BOOST_MOVE_FORCEINLINE friend bool operator==(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current == r.m_current; }
friend bool operator!=(const reverse_iterator& l, const reverse_iterator& r)
BOOST_MOVE_FORCEINLINE friend bool operator!=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current != r.m_current; }
friend bool operator<(const reverse_iterator& l, const reverse_iterator& r)
BOOST_MOVE_FORCEINLINE friend bool operator<(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current > r.m_current; }
friend bool operator<=(const reverse_iterator& l, const reverse_iterator& r)
BOOST_MOVE_FORCEINLINE friend bool operator<=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current >= r.m_current; }
friend bool operator>(const reverse_iterator& l, const reverse_iterator& r)
BOOST_MOVE_FORCEINLINE friend bool operator>(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current < r.m_current; }
friend bool operator>=(const reverse_iterator& l, const reverse_iterator& r)
BOOST_MOVE_FORCEINLINE friend bool operator>=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current <= r.m_current; }
reverse_iterator& operator+=(difference_type off)
BOOST_MOVE_FORCEINLINE reverse_iterator& operator+=(difference_type off)
{ m_current -= off; return *this; }
reverse_iterator& operator-=(difference_type off)
BOOST_MOVE_FORCEINLINE reverse_iterator& operator-=(difference_type off)
{ m_current += off; return *this; }
friend reverse_iterator operator+(reverse_iterator l, difference_type off)
BOOST_MOVE_FORCEINLINE friend reverse_iterator operator+(reverse_iterator l, difference_type off)
{ return (l += off); }
friend reverse_iterator operator+(difference_type off, reverse_iterator r)
BOOST_MOVE_FORCEINLINE friend reverse_iterator operator+(difference_type off, reverse_iterator r)
{ return (r += off); }
friend reverse_iterator operator-(reverse_iterator l, difference_type off)
BOOST_MOVE_FORCEINLINE friend reverse_iterator operator-(reverse_iterator l, difference_type off)
{ return (l-= off); }
friend difference_type operator-(const reverse_iterator& l, const reverse_iterator& r)
BOOST_MOVE_FORCEINLINE friend difference_type operator-(const reverse_iterator& l, const reverse_iterator& r)
{ return r.m_current - l.m_current; }
private:
@@ -158,10 +167,8 @@ class reverse_iterator
};
template< class Iterator >
reverse_iterator<Iterator> make_reverse_iterator( Iterator i )
{
return reverse_iterator<Iterator>(i);
}
BOOST_MOVE_FORCEINLINE reverse_iterator<Iterator> make_reverse_iterator( Iterator i )
{ return reverse_iterator<Iterator>(i); }
} //namespace movelib {
} //namespace boost {

View File

@@ -24,7 +24,11 @@
#define BOOST_MOVE_STD_NS_BEG _GLIBCXX_BEGIN_NAMESPACE(std)
#define BOOST_MOVE_STD_NS_END _GLIBCXX_END_NAMESPACE
#else
#if defined(_MSC_VER) && (_MSC_VER >= 1915)
#pragma warning (push)
#pragma warning (disable : 4643) // Forward declaring 'X' in namespace std is not permitted by the C++ Standard
#endif
#define BOOST_MOVE_STD_NS_BEG namespace std{
#define BOOST_MOVE_STD_NS_END }
#endif

View File

@@ -11,4 +11,6 @@
#ifdef BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
#pragma GCC diagnostic pop
#undef BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
#elif defined(_MSC_VER) && (_MSC_VER >= 1915)
#pragma warning (pop)
#endif //BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH

View File

@@ -30,8 +30,7 @@
// move/detail
#include <boost/move/detail/meta_utils.hpp>
// other
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <cassert>
// std
#include <cstddef>
@@ -65,6 +64,8 @@
// BOOST_MOVE_HAS_NOTHROW_COPY(T) should evaluate to true if T(t) can not throw
// BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) should evaluate to true if t = u can not throw
// BOOST_MOVE_IS_ENUM(T) should evaluate to true it t is a union type.
// BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) should evaluate to true if T has a non-throwing move constructor.
// BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) should evaluate to true if T has a non-throwing move assignment operator.
//
// The following can also be defined: when detected our implementation is greatly simplified.
//
@@ -102,51 +103,127 @@
# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__has_trivial_move_constructor(T) || ::boost::move_detail::is_pod<T>::value)
# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) (__has_trivial_move_assign(T) || ::boost::move_detail::is_pod<T>::value)
# endif
# if _MSC_FULL_VER >= 180020827
# define BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) (__is_nothrow_assignable(T&, T&&))
# define BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) (__is_nothrow_constructible(T, T&&))
# endif
#endif
#if defined(BOOST_CLANG) && defined(__has_feature)
#if defined(BOOST_CLANG)
// BOOST_MOVE_HAS_TRAIT
# if defined __is_identifier
# define BOOST_MOVE_HAS_TRAIT(T) (__has_extension(T) || !__is_identifier(__##T))
# elif defined(__has_extension)
# define BOOST_MOVE_HAS_TRAIT(T) __has_extension(T)
# else
# define BOOST_MOVE_HAS_TRAIT(T) 0
# endif
# if __has_feature(is_union)
// BOOST_MOVE_IS_UNION
# if BOOST_MOVE_HAS_TRAIT(is_union)
# define BOOST_MOVE_IS_UNION(T) __is_union(T)
# endif
# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_pod)
# define BOOST_MOVE_IS_POD(T) __is_pod(T)
# endif
# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_empty)
# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
# endif
# if __has_feature(has_trivial_constructor)
# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
# endif
# if __has_feature(has_trivial_copy)
# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) __has_trivial_copy(T)
# endif
# if __has_feature(has_trivial_assign)
# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) )
# endif
# if __has_feature(has_trivial_destructor)
# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
# endif
# if __has_feature(has_nothrow_constructor)
# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T)
# endif
# if __has_feature(has_nothrow_copy)
# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T))
# endif
# if __has_feature(is_nothrow_copy_assignable)
# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
# endif
# if __has_feature(is_enum)
// BOOST_MOVE_IS_ENUM
# if BOOST_MOVE_HAS_TRAIT(is_enum)
# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
# endif
# if __has_feature(has_trivial_move_constructor)
// BOOST_MOVE_IS_POD
# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && BOOST_MOVE_HAS_TRAIT(is_pod)
# define BOOST_MOVE_IS_POD(T) __is_pod(T)
# endif
// BOOST_MOVE_IS_EMPTY
# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && BOOST_MOVE_HAS_TRAIT(is_empty)
# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
# endif
// BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR
# if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_trivially_constructible)
# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __is_trivially_constructible(T)
# elif BOOST_MOVE_HAS_TRAIT(has_trivial_constructor)
# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
# endif
// BOOST_MOVE_HAS_TRIVIAL_COPY
# if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_trivially_constructible)
# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__is_constructible(T, const T &) && __is_trivially_constructible(T, const T &))
# elif BOOST_MOVE_HAS_TRAIT(has_trivial_copy)
# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) __has_trivial_copy(T)
# endif
// BOOST_MOVE_HAS_TRIVIAL_ASSIGN
# if BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_trivially_assignable)
# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__is_assignable(T, const T &) && __is_trivially_assignable(T, const T &))
# elif BOOST_MOVE_HAS_TRAIT(has_trivial_copy)
# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) __has_trivial_assign(T)
# endif
// BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR
# if BOOST_MOVE_HAS_TRAIT(is_trivially_destructible)
# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __is_trivially_destructible(T)
# elif BOOST_MOVE_HAS_TRAIT(has_trivial_destructor)
# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
# endif
// BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR
# if BOOST_MOVE_HAS_TRAIT(is_nothrow_constructible)
# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __is_nothrow_constructible(T)
# elif BOOST_MOVE_HAS_TRAIT(has_nothrow_constructor)
# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T)
# endif
// BOOST_MOVE_HAS_NOTHROW_COPY
# if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_nothrow_constructible)
# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__is_constructible(T, const T &) && __is_nothrow_constructible(T, const T &))
# elif BOOST_MOVE_HAS_TRAIT(has_nothrow_copy)
# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T))
# endif
// BOOST_MOVE_HAS_NOTHROW_ASSIGN
# if BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_nothrow_assignable)
# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__is_assignable(T, const T &) && __is_nothrow_assignable(T, const T &))
# elif BOOST_MOVE_HAS_TRAIT(has_nothrow_assign)
# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
# endif
// BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR
# if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
# if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_trivially_constructible)
# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__is_constructible(T, T&&) && __is_trivially_constructible(T, T&&))
# elif BOOST_MOVE_HAS_TRAIT(has_trivial_move_constructor)
# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) __has_trivial_move_constructor(T)
# endif
# if __has_feature(has_trivial_move_assign)
// BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN
# if BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_trivially_assignable)
# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) (__is_assignable(T, T&&) && __is_trivially_assignable(T, T&&))
# elif BOOST_MOVE_HAS_TRAIT(has_trivial_move_assign)
# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) __has_trivial_move_assign(T)
# endif
// BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR
# if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_nothrow_constructible)
# define BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) (__is_constructible(T, T&&) && __is_nothrow_constructible(T, T&&))
# elif BOOST_MOVE_HAS_TRAIT(has_nothrow_move_constructor)
# define BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) __has_nothrow_move_constructor(T)
# endif
// BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN
# if BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_nothrow_assignable)
# define BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) (__is_assignable(T, T&&) && __is_nothrow_assignable(T, T&&))
# elif BOOST_MOVE_HAS_TRAIT(has_nothrow_move_assign)
# define BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) __has_nothrow_move_assign(T)
# endif
# endif //BOOST_NO_CXX11_RVALUE_REFERENCES
// BOOST_MOVE_ALIGNMENT_OF
# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof(T)
#endif
#endif //#if defined(BOOST_CLANG)
#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG)
@@ -160,14 +237,106 @@
# define BOOST_MOVE_IS_POD(T) __is_pod(T)
# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) ((__has_trivial_constructor(T) BOOST_MOVE_INTEL_TT_OPTS))
# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_MOVE_INTEL_TT_OPTS))
# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_MOVE_INTEL_TT_OPTS) )
# if defined(BOOST_GCC) && (BOOST_GCC > 50000)
# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__is_trivially_constructible(T, const T &))
# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__is_trivially_assignable(T, const T &))
# else
# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_MOVE_INTEL_TT_OPTS))
# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_MOVE_INTEL_TT_OPTS) )
# endif
# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_MOVE_INTEL_TT_OPTS)
# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) BOOST_MOVE_INTEL_TT_OPTS)
# define BOOST_MOVE_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) BOOST_MOVE_INTEL_TT_OPTS))
# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_MOVE_INTEL_TT_OPTS))
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_SFINAE_EXPR)
template <typename T>
T && boost_move_tt_declval() BOOST_NOEXCEPT;
# if defined(BOOST_GCC) && (BOOST_GCC >= 80000)
// __is_assignable / __is_constructible implemented
# define BOOST_MOVE_IS_ASSIGNABLE(T, U) __is_assignable(T, U)
# define BOOST_MOVE_IS_CONSTRUCTIBLE(T, U) __is_constructible(T, U)
# else
template<typename Tt, typename Ut>
class boost_move_tt_is_assignable
{
struct twochar { char dummy[2]; };
template < class T
, class U
, class = decltype(boost_move_tt_declval<T>() = boost_move_tt_declval<U>())
> static char test(int);
template<class, class> static twochar test(...);
public:
static const bool value = sizeof(test<Tt, Ut>(0)) == sizeof(char);
};
template<typename Tt, typename Ut>
class boost_move_tt_is_constructible
{
struct twochar { char dummy[2]; };
template < class T
, class U
, class = decltype(T(boost_move_tt_declval<U>()))
> static char test(int);
template<class, class> static twochar test(...);
public:
static const bool value = sizeof(test<Tt, Ut>(0)) == sizeof(char);
};
# define BOOST_MOVE_IS_ASSIGNABLE(T, U) boost_move_tt_is_assignable<T,U>::value
# define BOOST_MOVE_IS_CONSTRUCTIBLE(T, U) boost_move_tt_is_constructible<T, U>::value
# endif
template <typename T, typename U, bool = BOOST_MOVE_IS_ASSIGNABLE(T, U)>
struct boost_move_tt_is_nothrow_assignable
{
static const bool value = false;
};
template <typename T, typename U>
struct boost_move_tt_is_nothrow_assignable<T, U, true>
{
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
static const bool value = noexcept(boost_move_tt_declval<T>() = boost_move_tt_declval<U>());
#else
static const bool value = false;
#endif
};
template <typename T, typename U, bool = BOOST_MOVE_IS_CONSTRUCTIBLE(T, U)>
struct boost_move_tt_is_nothrow_constructible
{
static const bool value = false;
};
template <typename T, typename U>
struct boost_move_tt_is_nothrow_constructible<T, U, true>
{
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
static const bool value = noexcept(T(boost_move_tt_declval<U>()));
#else
static const bool value = false;
#endif
};
# define BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) boost_move_tt_is_nothrow_assignable<T, T&&>::value
# define BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) boost_move_tt_is_nothrow_constructible<T, T&&>::value
# endif
# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
// BOOST_MOVE_ALIGNMENT_OF
# if (!defined(unix) && !defined(__unix__)) || defined(__LP64__)
// GCC sometimes lies about alignment requirements
// of type double on 32-bit unix platforms, use the
@@ -193,7 +362,7 @@
# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof__(T)
#endif
# if defined(__CODEGEARC__)
# if defined(BOOST_CODEGEARC)
# define BOOST_MOVE_IS_UNION(T) __is_union(T)
# define BOOST_MOVE_IS_POD(T) __is_pod(T)
# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
@@ -243,13 +412,13 @@
#endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR
#define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T)
#define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value
#else
#define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR
#define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T)
#define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value
#else
#define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif
@@ -263,45 +432,45 @@
#endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN
#define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T)
#define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) || ::boost::move_detail::is_pod<T>::value
#else
#define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
#endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR
#define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T)
#define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value
#else
#define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif
#ifdef BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR
#define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T)
#define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value
#else
#define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif
#ifdef BOOST_MOVE_HAS_NOTHROW_COPY
#define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_COPY(T)
#define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_COPY(T) || ::boost::move_detail::is_pod<T>::value
#else
#define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif
#ifdef BOOST_MOVE_HAS_NOTHROW_MOVE
#define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE(T)
#else
#define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
#endif
#ifdef BOOST_MOVE_HAS_NOTHROW_ASSIGN
#define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_ASSIGN(T)
#define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) || ::boost::move_detail::is_pod<T>::value
#else
#define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
#define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
#endif
#ifdef BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR
#define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value
#else
#define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T)
#endif
#ifdef BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN
#define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T)
#define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) || ::boost::move_detail::is_pod<T>::value
#else
#define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
#define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T)
#endif
#ifdef BOOST_MOVE_IS_ENUM
@@ -403,6 +572,15 @@ template<typename T> struct remove_cv<const T> { typedef T type; };
template<typename T> struct remove_cv<const volatile T> { typedef T type; };
template<typename T> struct remove_cv<volatile T> { typedef T type; };
//////////////////////////
// remove_cvref
//////////////////////////
template<class T>
struct remove_cvref
: remove_cv<typename remove_reference<T>::type>
{
};
//////////////////////////
// make_unsigned
//////////////////////////
@@ -817,8 +995,6 @@ struct is_trivially_default_constructible
template<class T>
struct is_trivially_copy_constructible
{
//In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
//deleted copy constructors so make sure the type is copy constructible.
static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T);
};
@@ -835,8 +1011,6 @@ struct is_trivially_move_constructible
template<class T>
struct is_trivially_copy_assignable
{
//In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
//deleted copy constructors so make sure the type is copy constructible.
static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T);
};
@@ -852,7 +1026,6 @@ struct is_trivially_move_assignable
//////////////////////////////////////
template<class T>
struct is_nothrow_default_constructible
: is_pod<T>
{ static const bool value = BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T); };
//////////////////////////////////////
@@ -902,6 +1075,7 @@ struct alignment_of_hack
char c;
T t2;
alignment_of_hack();
~alignment_of_hack();
};
template <unsigned A, unsigned S>
@@ -931,7 +1105,7 @@ struct alignment_of
class alignment_dummy;
typedef void (*function_ptr)();
typedef int (alignment_dummy::*member_ptr);
typedef int (alignment_dummy::*member_function_ptr)();
struct alignment_struct
{ long double dummy[4]; };
@@ -954,7 +1128,6 @@ union max_align
long double long_double_[4];
alignment_dummy *unknown_class_ptr_;
function_ptr function_ptr_;
member_function_ptr member_function_ptr_;
alignment_struct alignment_struct_;
};
@@ -964,7 +1137,46 @@ typedef union max_align max_align_t;
// aligned_storage
/////////////////////////////
#if !defined(BOOST_NO_ALIGNMENT)
#if defined(_MSC_VER) && defined(_M_IX86)
// Special version for usual alignments on x86 MSVC because it might crash
// when passsing aligned types by value even for 8 byte alignment.
template<std::size_t Align>
struct aligned_struct;
template <> struct aligned_struct<1> { char data; };
template <> struct aligned_struct<2> { short data; };
template <> struct aligned_struct<4> { int data; };
template <> struct aligned_struct<8> { double data; };
#define BOOST_MOVE_ALIGNED_STRUCT(x) \
template <> struct aligned_struct<x> { \
__declspec(align(x)) char data; \
}
BOOST_MOVE_ALIGNED_STRUCT(16);
BOOST_MOVE_ALIGNED_STRUCT(32);
BOOST_MOVE_ALIGNED_STRUCT(64);
BOOST_MOVE_ALIGNED_STRUCT(128);
BOOST_MOVE_ALIGNED_STRUCT(512);
BOOST_MOVE_ALIGNED_STRUCT(1024);
BOOST_MOVE_ALIGNED_STRUCT(2048);
BOOST_MOVE_ALIGNED_STRUCT(4096);
template<std::size_t Len, std::size_t Align>
union aligned_union
{
typedef aligned_struct<Align> aligner_t;
aligner_t aligner;
unsigned char data[Len > sizeof(aligner_t) ? Len : sizeof(aligner_t)];
};
template<std::size_t Len, std::size_t Align>
struct aligned_storage_impl
{
typedef aligned_union<Len, Align> type;
};
#elif !defined(BOOST_NO_ALIGNMENT)
template<std::size_t Len, std::size_t Align>
struct aligned_struct;
@@ -999,8 +1211,9 @@ BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1000)
template<std::size_t Len, std::size_t Align>
union aligned_struct_wrapper
{
typedef aligned_struct<Len, Align> aligner_t;
aligned_struct<Len, Align> aligner;
unsigned char data[sizeof(aligned_struct<Len, Align>)];
unsigned char data[Len > sizeof(aligner_t) ? Len : sizeof(aligner_t)];
};
template<std::size_t Len, std::size_t Align>
@@ -1015,7 +1228,7 @@ template<class T, std::size_t Len>
union aligned_union
{
T aligner;
unsigned char data[Len];
unsigned char data[Len > sizeof(T) ? Len : sizeof(T)];
};
template<std::size_t Len, std::size_t Align, class T, bool Ok>
@@ -1024,7 +1237,7 @@ struct aligned_next;
template<std::size_t Len, std::size_t Align, class T>
struct aligned_next<Len, Align, T, true>
{
BOOST_STATIC_ASSERT((alignment_of<T>::value == Align));
BOOST_MOVE_STATIC_ASSERT((alignment_of<T>::value == Align));
typedef aligned_union<T, Len> type;
};
@@ -1064,13 +1277,13 @@ template<std::size_t Len, std::size_t Align = alignment_of<max_align_t>::value>
struct aligned_storage
{
//Sanity checks for input parameters
BOOST_STATIC_ASSERT(Align > 0);
BOOST_MOVE_STATIC_ASSERT(Align > 0);
//Sanity checks for output type
typedef typename aligned_storage_impl<Len ? Len : 1, Align>::type type;
static const std::size_t value = alignment_of<type>::value;
BOOST_STATIC_ASSERT(value >= Align);
BOOST_STATIC_ASSERT((value % Align) == 0);
BOOST_MOVE_STATIC_ASSERT(value >= Align);
BOOST_MOVE_STATIC_ASSERT((value % Align) == 0);
//Just in case someone instantiates aligned_storage
//instead of aligned_storage::type (typical error).

View File

@@ -546,7 +546,7 @@ struct is_unary_function
# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600)
# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
#elif defined(__CODEGEARC__)
#elif defined(BOOST_CODEGEARC)
# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
#endif
@@ -559,32 +559,6 @@ struct is_unary_function
struct has_virtual_destructor{ static const bool value = true; };
#endif
//////////////////////////////////////
// missing_virtual_destructor
//////////////////////////////////////
template< class T, class U
, bool enable = is_convertible< U*, T*>::value &&
!is_array<T>::value &&
!is_same<typename remove_cv<T>::type, void>::value &&
!is_same<typename remove_cv<U>::type, typename remove_cv<T>::type>::value
>
struct missing_virtual_destructor_default_delete
{ static const bool value = !has_virtual_destructor<T>::value; };
template<class T, class U>
struct missing_virtual_destructor_default_delete<T, U, false>
{ static const bool value = false; };
template<class Deleter, class U>
struct missing_virtual_destructor
{ static const bool value = false; };
template<class T, class U>
struct missing_virtual_destructor< ::boost::movelib::default_delete<T>, U >
: missing_virtual_destructor_default_delete<T, U>
{};
} //namespace move_upmu {
} //namespace boost {

View File

@@ -52,18 +52,97 @@
#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) && defined(_DEBUG)
//"__forceinline" and MSVC seems to have some bugs in debug mode
#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(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ < 5)))
#elif defined(BOOST_GCC) && (__GNUC__ <= 5)
//Older GCCs have problems with forceinline
#define BOOST_MOVE_FORCEINLINE inline
#else
#define BOOST_MOVE_FORCEINLINE BOOST_FORCEINLINE
#endif
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_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
#endif //#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP

View File

@@ -170,7 +170,7 @@ struct is_move_iterator< ::boost::move_iterator<I> >
//!
//! <b>Returns</b>: move_iterator<It>(i).
template<class It>
inline move_iterator<It> make_move_iterator(const It &it)
BOOST_MOVE_FORCEINLINE move_iterator<It> make_move_iterator(const It &it)
{ return move_iterator<It>(it); }
//////////////////////////////////////////////////////////////////////////////

View File

@@ -38,12 +38,22 @@
#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 {

View File

@@ -25,8 +25,7 @@
#include <boost/move/default_delete.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/move/adl_move_swap.hpp>
#include <boost/static_assert.hpp>
#include <boost/assert.hpp>
#include <cassert>
#include <cstddef> //For std::nullptr_t and std::size_t
@@ -394,8 +393,8 @@ class unique_ptr
{
//If this constructor is instantiated with a pointer type or reference type
//for the template argument D, the program is ill-formed.
BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
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).
@@ -405,8 +404,8 @@ class unique_ptr
{
//If this constructor is instantiated with a pointer type or reference type
//for the template argument D, the program is ill-formed.
BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
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
@@ -430,12 +429,12 @@ class unique_ptr
{
//If T is not an array type, element_type_t<Pointer> derives from T
//it uses the default deleter and T has no virtual destructor, then you have a problem
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
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_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value);
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.
@@ -468,7 +467,7 @@ class unique_ptr
{
//If T is not an array type, element_type_t<Pointer> derives from T
//it uses the default deleter and T has no virtual destructor, then you have a problem
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
BOOST_MOVE_STATIC_ASSERT(( !bmupd::missing_virtual_destructor
<D, typename bmupd::get_element_type<Pointer>::type>::value ));
}
@@ -506,7 +505,7 @@ class unique_ptr
{
//If T is not an array type, element_type_t<Pointer> derives from T
//it uses the default deleter and T has no virtual destructor, then you have a problem
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
BOOST_MOVE_STATIC_ASSERT(( !bmupd::missing_virtual_destructor
<D, typename bmupd::get_element_type<Pointer>::type>::value ));
}
@@ -553,7 +552,7 @@ class unique_ptr
{
//If T is not an array type, U derives from T
//it uses the default deleter and T has no virtual destructor, then you have a problem
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
BOOST_MOVE_STATIC_ASSERT(( !bmupd::missing_virtual_destructor
<D, typename unique_ptr<U, E>::pointer>::value ));
}
@@ -620,7 +619,7 @@ class unique_ptr
BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
operator*() const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value));
BOOST_MOVE_STATIC_ASSERT((!bmupmu::is_array<T>::value));
return *m_data.m_p;
}
@@ -632,8 +631,8 @@ class unique_ptr
BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
operator[](std::size_t i) const BOOST_NOEXCEPT
{
BOOST_ASSERT( bmupmu::extent<T>::value == 0 || i < bmupmu::extent<T>::value );
BOOST_ASSERT(m_data.m_p);
assert( bmupmu::extent<T>::value == 0 || i < bmupmu::extent<T>::value );
assert(m_data.m_p);
return m_data.m_p[i];
}
@@ -646,8 +645,8 @@ class unique_ptr
//! <b>Remarks</b: If T is an array type, the program is ill-formed.
BOOST_MOVE_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value));
BOOST_ASSERT(m_data.m_p);
BOOST_MOVE_STATIC_ASSERT((!bmupmu::is_array<T>::value));
assert(m_data.m_p);
return m_data.m_p;
}
@@ -711,7 +710,7 @@ class unique_ptr
{
//If T is not an array type, element_type_t<Pointer> derives from T
//it uses the default deleter and T has no virtual destructor, then you have a problem
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
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;

View File

@@ -126,13 +126,13 @@
#else //BOOST_MOVE_DOXYGEN_INVOKED
template <class T>
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
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_FORCEINLINE typename ::boost::move_detail::enable_if_c
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; }

View File

@@ -29,7 +29,6 @@
#include <boost/move/detail/workaround.hpp> //forceinline
#include <boost/move/core.hpp>
#include <boost/move/detail/meta_utils.hpp>
#include <boost/static_assert.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
@@ -209,7 +208,8 @@
#else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
template <class T>
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
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
@@ -245,49 +245,16 @@
#else //Old move
template <class T>
BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
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_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
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_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
return static_cast<T&&>(t);
}
#endif //BOOST_MOVE_DOXYGEN_INVOKED
//////////////////////////////////////////////////////////////////////////////
//
// move_if_not_lvalue_reference
//
//////////////////////////////////////////////////////////////////////////////
#if defined(BOOST_MOVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: Calls `boost::move` if `input_reference` is not a lvalue reference.
//! Otherwise returns the reference
template <class T> output_reference move_if_not_lvalue_reference(input_reference) noexcept;
#elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
//Old move approach, lvalues could bind to rvalue references
template <class T>
BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
{ return t; }
#else //Old move
template <class T>
BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
{ return static_cast<T&&>(t); }
template <class T>
BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
{
//"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
BOOST_MOVE_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
return static_cast<T&&>(t);
}
@@ -295,7 +262,45 @@
} //namespace boost {
#endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
#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