mirror of
https://git.suyu.dev/suyu/ext-boost.git
synced 2025-12-24 00:04:41 +01:00
Update to boost 1.66
This commit is contained in:
parent
9ffbf897dc
commit
d80e506e17
203 changed files with 14820 additions and 2478 deletions
67
boost/move/algo/adaptive_merge.hpp
Normal file
67
boost/move/algo/adaptive_merge.hpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_MOVE_ADAPTIVE_MERGE_HPP
|
||||
#define BOOST_MOVE_ADAPTIVE_MERGE_HPP
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
//! <b>Effects</b>: Merges two consecutive sorted ranges [first, middle) and [middle, last)
|
||||
//! into one sorted range [first, last) according to the given comparison function comp.
|
||||
//! The algorithm is stable (if there are equivalent elements in the original two ranges,
|
||||
//! the elements from the first range (preserving their original order) precede the elements
|
||||
//! from the second range (preserving their original order).
|
||||
//!
|
||||
//! <b>Requires</b>:
|
||||
//! - RandIt must meet the requirements of ValueSwappable and RandomAccessIterator.
|
||||
//! - The type of dereferenced RandIt must meet the requirements of MoveAssignable and MoveConstructible.
|
||||
//!
|
||||
//! <b>Parameters</b>:
|
||||
//! - first: the beginning of the first sorted range.
|
||||
//! - middle: the end of the first sorted range and the beginning of the second
|
||||
//! - last: the end of the second sorted range
|
||||
//! - comp: comparison function object which returns true if the first argument is is ordered before the second.
|
||||
//! - uninitialized, uninitialized_len: raw storage starting on "uninitialized", able to hold "uninitialized_len"
|
||||
//! elements of type iterator_traits<RandIt>::value_type. Maximum performance is achieved when uninitialized_len
|
||||
//! is min(std::distance(first, middle), std::distance(middle, last)).
|
||||
//!
|
||||
//! <b>Throws</b>: If comp throws or the move constructor, move assignment or swap of the type
|
||||
//! of dereferenced RandIt throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Always K x O(N) comparisons and move assignments/constructors/swaps.
|
||||
//! Constant factor for comparisons and data movement is minimized when uninitialized_len
|
||||
//! is min(std::distance(first, middle), std::distance(middle, last)).
|
||||
//! Pretty good enough performance is achieved when uninitialized_len is
|
||||
//! ceil(sqrt(std::distance(first, last)))*2.
|
||||
//!
|
||||
//! <b>Caution</b>: Experimental implementation, not production-ready.
|
||||
template<class RandIt, class Compare>
|
||||
void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp
|
||||
, typename iterator_traits<RandIt>::value_type* uninitialized = 0
|
||||
, std::size_t uninitialized_len = 0)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::size_type size_type;
|
||||
typedef typename iterator_traits<RandIt>::value_type value_type;
|
||||
|
||||
::boost::movelib::detail_adaptive::adaptive_xbuf<value_type> xbuf(uninitialized, uninitialized_len);
|
||||
::boost::movelib::detail_adaptive::adaptive_merge_impl(first, size_type(middle - first), size_type(last - middle), comp, xbuf);
|
||||
}
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#define BOOST_MOVE_ADAPTIVE_MERGE_HPP
|
||||
70
boost/move/algo/adaptive_sort.hpp
Normal file
70
boost/move/algo/adaptive_sort.hpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_MOVE_ADAPTIVE_SORT_HPP
|
||||
#define BOOST_MOVE_ADAPTIVE_SORT_HPP
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
//! <b>Effects</b>: Sorts the elements in the range [first, last) in ascending order according
|
||||
//! to comparison functor "comp". The sort is stable (order of equal elements
|
||||
//! is guaranteed to be preserved). Performance is improved if additional raw storage is
|
||||
//! provided.
|
||||
//!
|
||||
//! <b>Requires</b>:
|
||||
//! - RandIt must meet the requirements of ValueSwappable and RandomAccessIterator.
|
||||
//! - The type of dereferenced RandIt must meet the requirements of MoveAssignable and MoveConstructible.
|
||||
//!
|
||||
//! <b>Parameters</b>:
|
||||
//! - first, last: the range of elements to sort
|
||||
//! - comp: comparison function object which returns true if the first argument is is ordered before the second.
|
||||
//! - uninitialized, uninitialized_len: raw storage starting on "uninitialized", able to hold "uninitialized_len"
|
||||
//! elements of type iterator_traits<RandIt>::value_type. Maximum performance is achieved when uninitialized_len
|
||||
//! is ceil(std::distance(first, last)/2).
|
||||
//!
|
||||
//! <b>Throws</b>: If comp throws or the move constructor, move assignment or swap of the type
|
||||
//! of dereferenced RandIt throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Always K x O(Nxlog(N)) comparisons and move assignments/constructors/swaps.
|
||||
//! Comparisons are close to minimum even with no additional memory. Constant factor for data movement is minimized
|
||||
//! when uninitialized_len is ceil(std::distance(first, last)/2). Pretty good enough performance is achieved when
|
||||
//! ceil(sqrt(std::distance(first, last)))*2.
|
||||
//!
|
||||
//! <b>Caution</b>: Experimental implementation, not production-ready.
|
||||
template<class RandIt, class RandRawIt, class Compare>
|
||||
void adaptive_sort( RandIt first, RandIt last, Compare comp
|
||||
, RandRawIt uninitialized
|
||||
, std::size_t uninitialized_len)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::size_type size_type;
|
||||
typedef typename iterator_traits<RandIt>::value_type value_type;
|
||||
|
||||
::boost::movelib::detail_adaptive::adaptive_xbuf<value_type, RandRawIt> xbuf(uninitialized, uninitialized_len);
|
||||
::boost::movelib::detail_adaptive::adaptive_sort_impl(first, size_type(last - first), comp, xbuf);
|
||||
}
|
||||
|
||||
template<class RandIt, class Compare>
|
||||
void adaptive_sort( RandIt first, RandIt last, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::value_type value_type;
|
||||
adaptive_sort(first, last, comp, (value_type*)0, 0u);
|
||||
}
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#define BOOST_MOVE_ADAPTIVE_SORT_HPP
|
||||
2470
boost/move/algo/detail/adaptive_sort_merge.hpp
Normal file
2470
boost/move/algo/detail/adaptive_sort_merge.hpp
Normal file
File diff suppressed because it is too large
Load diff
121
boost/move/algo/detail/basic_op.hpp
Normal file
121
boost/move/algo/detail/basic_op.hpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_MOVE_ALGO_BASIC_OP
|
||||
#define BOOST_MOVE_ALGO_BASIC_OP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
struct forward_t{};
|
||||
struct backward_t{};
|
||||
struct three_way_t{};
|
||||
struct three_way_forward_t{};
|
||||
struct four_way_t{};
|
||||
|
||||
struct move_op
|
||||
{
|
||||
template <class SourceIt, class DestinationIt>
|
||||
BOOST_MOVE_FORCEINLINE void operator()(SourceIt source, DestinationIt dest)
|
||||
{ *dest = ::boost::move(*source); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
BOOST_MOVE_FORCEINLINE DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
|
||||
{ return ::boost::move(first, last, dest_begin); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
BOOST_MOVE_FORCEINLINE DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_last)
|
||||
{ return ::boost::move_backward(first, last, dest_last); }
|
||||
|
||||
template <class SourceIt, class DestinationIt1, class DestinationIt2>
|
||||
BOOST_MOVE_FORCEINLINE void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
|
||||
{
|
||||
*dest2it = boost::move(*dest1it);
|
||||
*dest1it = boost::move(*srcit);
|
||||
}
|
||||
|
||||
template <class SourceIt, class DestinationIt1, class DestinationIt2>
|
||||
DestinationIt2 operator()(three_way_forward_t, SourceIt srcit, SourceIt srcitend, DestinationIt1 dest1it, DestinationIt2 dest2it)
|
||||
{
|
||||
//Destination2 range can overlap SourceIt range so avoid boost::move
|
||||
while(srcit != srcitend){
|
||||
this->operator()(three_way_t(), srcit++, dest1it++, dest2it++);
|
||||
}
|
||||
return dest2it;
|
||||
}
|
||||
|
||||
template <class SourceIt, class DestinationIt1, class DestinationIt2, class DestinationIt3>
|
||||
BOOST_MOVE_FORCEINLINE void operator()(four_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it, DestinationIt3 dest3it)
|
||||
{
|
||||
*dest3it = boost::move(*dest2it);
|
||||
*dest2it = boost::move(*dest1it);
|
||||
*dest1it = boost::move(*srcit);
|
||||
}
|
||||
};
|
||||
|
||||
struct swap_op
|
||||
{
|
||||
template <class SourceIt, class DestinationIt>
|
||||
BOOST_MOVE_FORCEINLINE void operator()(SourceIt source, DestinationIt dest)
|
||||
{ boost::adl_move_swap(*dest, *source); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
BOOST_MOVE_FORCEINLINE DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
|
||||
{ return boost::adl_move_swap_ranges(first, last, dest_begin); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
BOOST_MOVE_FORCEINLINE DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
|
||||
{ return boost::adl_move_swap_ranges_backward(first, last, dest_begin); }
|
||||
|
||||
template <class SourceIt, class DestinationIt1, class DestinationIt2>
|
||||
BOOST_MOVE_FORCEINLINE void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
|
||||
{
|
||||
typename ::boost::movelib::iterator_traits<SourceIt>::value_type tmp(boost::move(*dest2it));
|
||||
*dest2it = boost::move(*dest1it);
|
||||
*dest1it = boost::move(*srcit);
|
||||
*srcit = boost::move(tmp);
|
||||
}
|
||||
|
||||
template <class SourceIt, class DestinationIt1, class DestinationIt2>
|
||||
DestinationIt2 operator()(three_way_forward_t, SourceIt srcit, SourceIt srcitend, DestinationIt1 dest1it, DestinationIt2 dest2it)
|
||||
{
|
||||
while(srcit != srcitend){
|
||||
this->operator()(three_way_t(), srcit++, dest1it++, dest2it++);
|
||||
}
|
||||
return dest2it;
|
||||
}
|
||||
|
||||
template <class SourceIt, class DestinationIt1, class DestinationIt2, class DestinationIt3>
|
||||
BOOST_MOVE_FORCEINLINE void operator()(four_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it, DestinationIt3 dest3it)
|
||||
{
|
||||
typename ::boost::movelib::iterator_traits<SourceIt>::value_type tmp(boost::move(*dest3it));
|
||||
*dest3it = boost::move(*dest2it);
|
||||
*dest2it = boost::move(*dest1it);
|
||||
*dest1it = boost::move(*srcit);
|
||||
*srcit = boost::move(tmp);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} //namespace boost::movelib
|
||||
|
||||
#endif //BOOST_MOVE_ALGO_BASIC_OP
|
||||
128
boost/move/algo/detail/insertion_sort.hpp
Normal file
128
boost/move/algo/detail/insertion_sort.hpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BOOST_MOVE_DETAIL_INSERT_SORT_HPP
|
||||
#define BOOST_MOVE_DETAIL_INSERT_SORT_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/algo/move.hpp>
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/detail/placement_new.hpp>
|
||||
#include <boost/move/detail/destruct_n.hpp>
|
||||
#include <boost/move/algo/detail/basic_op.hpp>
|
||||
#include <boost/move/detail/placement_new.hpp>
|
||||
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
|
||||
|
||||
namespace boost { namespace movelib{
|
||||
|
||||
// @cond
|
||||
|
||||
template <class Compare, class ForwardIterator, class BirdirectionalIterator, class Op>
|
||||
void insertion_sort_op(ForwardIterator first1, ForwardIterator last1, BirdirectionalIterator first2, Compare comp, Op op)
|
||||
{
|
||||
if (first1 != last1){
|
||||
BirdirectionalIterator last2 = first2;
|
||||
op(first1, last2);
|
||||
for (++last2; ++first1 != last1; ++last2){
|
||||
BirdirectionalIterator j2 = last2;
|
||||
BirdirectionalIterator i2 = j2;
|
||||
if (comp(*first1, *--i2)){
|
||||
op(i2, j2);
|
||||
for (--j2; i2 != first2 && comp(*first1, *--i2); --j2) {
|
||||
op(i2, j2);
|
||||
}
|
||||
}
|
||||
op(first1, j2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Compare, class ForwardIterator, class BirdirectionalIterator>
|
||||
void insertion_sort_swap(ForwardIterator first1, ForwardIterator last1, BirdirectionalIterator first2, Compare comp)
|
||||
{
|
||||
insertion_sort_op(first1, last1, first2, comp, swap_op());
|
||||
}
|
||||
|
||||
|
||||
template <class Compare, class ForwardIterator, class BirdirectionalIterator>
|
||||
void insertion_sort_copy(ForwardIterator first1, ForwardIterator last1, BirdirectionalIterator first2, Compare comp)
|
||||
{
|
||||
insertion_sort_op(first1, last1, first2, comp, move_op());
|
||||
}
|
||||
|
||||
// @endcond
|
||||
|
||||
template <class Compare, class BirdirectionalIterator>
|
||||
void insertion_sort(BirdirectionalIterator first, BirdirectionalIterator last, Compare comp)
|
||||
{
|
||||
typedef typename boost::movelib::iterator_traits<BirdirectionalIterator>::value_type value_type;
|
||||
if (first != last){
|
||||
BirdirectionalIterator i = first;
|
||||
for (++i; i != last; ++i){
|
||||
BirdirectionalIterator j = i;
|
||||
if (comp(*i, *--j)) {
|
||||
value_type tmp(::boost::move(*i));
|
||||
*i = ::boost::move(*j);
|
||||
for (BirdirectionalIterator k = j; k != first && comp(tmp, *--k); --j) {
|
||||
*j = ::boost::move(*k);
|
||||
}
|
||||
*j = ::boost::move(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Compare, class BirdirectionalIterator, class BirdirectionalRawIterator>
|
||||
void insertion_sort_uninitialized_copy
|
||||
(BirdirectionalIterator first1, BirdirectionalIterator const last1
|
||||
, BirdirectionalRawIterator const first2
|
||||
, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits<BirdirectionalIterator>::value_type value_type;
|
||||
if (first1 != last1){
|
||||
BirdirectionalRawIterator last2 = first2;
|
||||
::new((iterator_to_raw_pointer)(last2), boost_move_new_t()) value_type(move(*first1));
|
||||
destruct_n<value_type, BirdirectionalRawIterator> d(first2);
|
||||
d.incr();
|
||||
for (++last2; ++first1 != last1; ++last2){
|
||||
BirdirectionalRawIterator j2 = last2;
|
||||
BirdirectionalRawIterator k2 = j2;
|
||||
if (comp(*first1, *--k2)){
|
||||
::new((iterator_to_raw_pointer)(j2), boost_move_new_t()) value_type(move(*k2));
|
||||
d.incr();
|
||||
for (--j2; k2 != first2 && comp(*first1, *--k2); --j2)
|
||||
*j2 = move(*k2);
|
||||
*j2 = move(*first1);
|
||||
}
|
||||
else{
|
||||
::new((iterator_to_raw_pointer)(j2), boost_move_new_t()) value_type(move(*first1));
|
||||
d.incr();
|
||||
}
|
||||
}
|
||||
d.release();
|
||||
}
|
||||
}
|
||||
|
||||
}} //namespace boost { namespace movelib{
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_INSERT_SORT_HPP
|
||||
577
boost/move/algo/detail/merge.hpp
Normal file
577
boost/move/algo/detail/merge.hpp
Normal file
|
|
@ -0,0 +1,577 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_MOVE_MERGE_HPP
|
||||
#define BOOST_MOVE_MERGE_HPP
|
||||
|
||||
#include <boost/move/algo/move.hpp>
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/move/algo/detail/basic_op.hpp>
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/move/detail/destruct_n.hpp>
|
||||
#include <boost/move/algo/predicate.hpp>
|
||||
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
// @cond
|
||||
|
||||
/*
|
||||
template<typename Unsigned>
|
||||
inline Unsigned gcd(Unsigned x, Unsigned y)
|
||||
{
|
||||
if(0 == ((x &(x-1)) | (y & (y-1)))){
|
||||
return x < y ? x : y;
|
||||
}
|
||||
else{
|
||||
do
|
||||
{
|
||||
Unsigned t = x % y;
|
||||
x = y;
|
||||
y = t;
|
||||
} while (y);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//Modified version from "An Optimal In-Place Array Rotation Algorithm", Ching-Kuang Shene
|
||||
template<typename Unsigned>
|
||||
Unsigned gcd(Unsigned x, Unsigned y)
|
||||
{
|
||||
if(0 == ((x &(x-1)) | (y & (y-1)))){
|
||||
return x < y ? x : y;
|
||||
}
|
||||
else{
|
||||
Unsigned z = 1;
|
||||
while((!(x&1)) & (!(y&1))){
|
||||
z <<=1, x>>=1, y>>=1;
|
||||
}
|
||||
while(x && y){
|
||||
if(!(x&1))
|
||||
x >>=1;
|
||||
else if(!(y&1))
|
||||
y >>=1;
|
||||
else if(x >=y)
|
||||
x = (x-y) >> 1;
|
||||
else
|
||||
y = (y-x) >> 1;
|
||||
}
|
||||
return z*(x+y);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RandIt>
|
||||
RandIt rotate_gcd(RandIt first, RandIt middle, RandIt last)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::size_type size_type;
|
||||
typedef typename iterator_traits<RandIt>::value_type value_type;
|
||||
|
||||
if(first == middle)
|
||||
return last;
|
||||
if(middle == last)
|
||||
return first;
|
||||
const size_type middle_pos = size_type(middle - first);
|
||||
RandIt ret = last - middle_pos;
|
||||
if (middle == ret){
|
||||
boost::adl_move_swap_ranges(first, middle, middle);
|
||||
}
|
||||
else{
|
||||
const size_type length = size_type(last - first);
|
||||
for( RandIt it_i(first), it_gcd(it_i + gcd(length, middle_pos))
|
||||
; it_i != it_gcd
|
||||
; ++it_i){
|
||||
value_type temp(boost::move(*it_i));
|
||||
RandIt it_j = it_i;
|
||||
RandIt it_k = it_j+middle_pos;
|
||||
do{
|
||||
*it_j = boost::move(*it_k);
|
||||
it_j = it_k;
|
||||
size_type const left = size_type(last - it_j);
|
||||
it_k = left > middle_pos ? it_j + middle_pos : first + (middle_pos - left);
|
||||
} while(it_k != it_i);
|
||||
*it_j = boost::move(temp);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class RandIt, class T, class Compare>
|
||||
RandIt lower_bound
|
||||
(RandIt first, const RandIt last, const T& key, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits
|
||||
<RandIt>::size_type size_type;
|
||||
size_type len = size_type(last - first);
|
||||
RandIt middle;
|
||||
|
||||
while (len) {
|
||||
size_type step = len >> 1;
|
||||
middle = first;
|
||||
middle += step;
|
||||
|
||||
if (comp(*middle, key)) {
|
||||
first = ++middle;
|
||||
len -= step + 1;
|
||||
}
|
||||
else{
|
||||
len = step;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class RandIt, class T, class Compare>
|
||||
RandIt upper_bound
|
||||
(RandIt first, const RandIt last, const T& key, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits
|
||||
<RandIt>::size_type size_type;
|
||||
size_type len = size_type(last - first);
|
||||
RandIt middle;
|
||||
|
||||
while (len) {
|
||||
size_type step = len >> 1;
|
||||
middle = first;
|
||||
middle += step;
|
||||
|
||||
if (!comp(key, *middle)) {
|
||||
first = ++middle;
|
||||
len -= step + 1;
|
||||
}
|
||||
else{
|
||||
len = step;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
|
||||
template<class RandIt, class Compare, class Op>
|
||||
void op_merge_left( RandIt buf_first
|
||||
, RandIt first1
|
||||
, RandIt const last1
|
||||
, RandIt const last2
|
||||
, Compare comp
|
||||
, Op op)
|
||||
{
|
||||
for(RandIt first2=last1; first2 != last2; ++buf_first){
|
||||
if(first1 == last1){
|
||||
op(forward_t(), first2, last2, buf_first);
|
||||
return;
|
||||
}
|
||||
else if(comp(*first2, *first1)){
|
||||
op(first2, buf_first);
|
||||
++first2;
|
||||
}
|
||||
else{
|
||||
op(first1, buf_first);
|
||||
++first1;
|
||||
}
|
||||
}
|
||||
if(buf_first != first1){//In case all remaining elements are in the same place
|
||||
//(e.g. buffer is exactly the size of the second half
|
||||
//and all elements from the second half are less)
|
||||
op(forward_t(), first1, last1, buf_first);
|
||||
}
|
||||
}
|
||||
|
||||
// [buf_first, first1) -> buffer
|
||||
// [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
|
||||
// Elements from buffer are moved to [last2 - (first1-buf_first), last2)
|
||||
// Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
|
||||
template<class RandIt, class Compare>
|
||||
void merge_left
|
||||
(RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
|
||||
{
|
||||
op_merge_left(buf_first, first1, last1, last2, comp, move_op());
|
||||
}
|
||||
|
||||
// [buf_first, first1) -> buffer
|
||||
// [first1, last1) merge [last1,last2) -> [buf_first,buf_first+(last2-first1))
|
||||
// Elements from buffer are swapped to [last2 - (first1-buf_first), last2)
|
||||
// Note: distance(buf_first, first1) >= distance(last1, last2), so no overlapping occurs
|
||||
template<class RandIt, class Compare>
|
||||
void swap_merge_left
|
||||
(RandIt buf_first, RandIt first1, RandIt const last1, RandIt const last2, Compare comp)
|
||||
{
|
||||
op_merge_left(buf_first, first1, last1, last2, comp, swap_op());
|
||||
}
|
||||
|
||||
template<class RandIt, class Compare, class Op>
|
||||
void op_merge_right
|
||||
(RandIt const first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp, Op op)
|
||||
{
|
||||
RandIt const first2 = last1;
|
||||
while(first1 != last1){
|
||||
if(last2 == first2){
|
||||
op(backward_t(), first1, last1, buf_last);
|
||||
return;
|
||||
}
|
||||
--last2;
|
||||
--last1;
|
||||
--buf_last;
|
||||
if(comp(*last2, *last1)){
|
||||
op(last1, buf_last);
|
||||
++last2;
|
||||
}
|
||||
else{
|
||||
op(last2, buf_last);
|
||||
++last1;
|
||||
}
|
||||
}
|
||||
if(last2 != buf_last){ //In case all remaining elements are in the same place
|
||||
//(e.g. buffer is exactly the size of the first half
|
||||
//and all elements from the second half are less)
|
||||
op(backward_t(), first2, last2, buf_last);
|
||||
}
|
||||
}
|
||||
|
||||
// [last2, buf_last) - buffer
|
||||
// [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
|
||||
// Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
|
||||
template<class RandIt, class Compare>
|
||||
void merge_right
|
||||
(RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
|
||||
{
|
||||
op_merge_right(first1, last1, last2, buf_last, comp, move_op());
|
||||
}
|
||||
|
||||
// [last2, buf_last) - buffer
|
||||
// [first1, last1) merge [last1,last2) -> [first1+(buf_last-last2), buf_last)
|
||||
// Note: distance[last2, buf_last) >= distance[first1, last1), so no overlapping occurs
|
||||
template<class RandIt, class Compare>
|
||||
void swap_merge_right
|
||||
(RandIt first1, RandIt last1, RandIt last2, RandIt buf_last, Compare comp)
|
||||
{
|
||||
op_merge_right(first1, last1, last2, buf_last, comp, swap_op());
|
||||
}
|
||||
|
||||
template <class BidirIt, class Distance, class Compare>
|
||||
void merge_bufferless_ONlogN_recursive
|
||||
(BidirIt first, BidirIt middle, BidirIt last, Distance len1, Distance len2, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits<BidirIt>::size_type size_type;
|
||||
while(1) {
|
||||
//#define MERGE_BUFFERLESS_RECURSIVE_OPT
|
||||
#ifndef MERGE_BUFFERLESS_RECURSIVE_OPT
|
||||
if (len2 == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!len1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((len1 | len2) == 1) {
|
||||
if (comp(*middle, *first))
|
||||
adl_move_swap(*first, *middle);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (len2 == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!len1) {
|
||||
return;
|
||||
}
|
||||
BidirIt middle_prev = middle; --middle_prev;
|
||||
if(!comp(*middle, *middle_prev))
|
||||
return;
|
||||
|
||||
while(true) {
|
||||
if (comp(*middle, *first))
|
||||
break;
|
||||
++first;
|
||||
if(--len1 == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (len1 == 1 && len2 == 1) {
|
||||
//comp(*middle, *first) == true already tested in the loop
|
||||
adl_move_swap(*first, *middle);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
BidirIt first_cut = first;
|
||||
BidirIt second_cut = middle;
|
||||
Distance len11 = 0;
|
||||
Distance len22 = 0;
|
||||
if (len1 > len2) {
|
||||
len11 = len1 / 2;
|
||||
first_cut += len11;
|
||||
second_cut = boost::movelib::lower_bound(middle, last, *first_cut, comp);
|
||||
len22 = size_type(second_cut - middle);
|
||||
}
|
||||
else {
|
||||
len22 = len2 / 2;
|
||||
second_cut += len22;
|
||||
first_cut = boost::movelib::upper_bound(first, middle, *second_cut, comp);
|
||||
len11 = size_type(first_cut - first);
|
||||
}
|
||||
BidirIt new_middle = rotate_gcd(first_cut, middle, second_cut);
|
||||
|
||||
//Avoid one recursive call doing a manual tail call elimination on the biggest range
|
||||
const Distance len_internal = len11+len22;
|
||||
if( len_internal < (len1 + len2 - len_internal) ) {
|
||||
merge_bufferless_ONlogN_recursive(first, first_cut, new_middle, len11, len22, comp);
|
||||
//merge_bufferless_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
|
||||
first = new_middle;
|
||||
middle = second_cut;
|
||||
len1 -= len11;
|
||||
len2 -= len22;
|
||||
}
|
||||
else {
|
||||
//merge_bufferless_recursive(first, first_cut, new_middle, len11, len22, comp);
|
||||
merge_bufferless_ONlogN_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
|
||||
middle = first_cut;
|
||||
last = new_middle;
|
||||
len1 = len11;
|
||||
len2 = len22;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Complexity: NlogN
|
||||
template<class BidirIt, class Compare>
|
||||
void merge_bufferless_ONlogN(BidirIt first, BidirIt middle, BidirIt last, Compare comp)
|
||||
{
|
||||
merge_bufferless_ONlogN_recursive
|
||||
(first, middle, last, middle - first, last - middle, comp);
|
||||
}
|
||||
|
||||
//Complexity: min(len1,len2)^2 + max(len1,len2)
|
||||
template<class RandIt, class Compare>
|
||||
void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp)
|
||||
{
|
||||
if((middle - first) < (last - middle)){
|
||||
while(first != middle){
|
||||
RandIt const old_last1 = middle;
|
||||
middle = boost::movelib::lower_bound(middle, last, *first, comp);
|
||||
first = rotate_gcd(first, old_last1, middle);
|
||||
if(middle == last){
|
||||
break;
|
||||
}
|
||||
do{
|
||||
++first;
|
||||
} while(first != middle && !comp(*middle, *first));
|
||||
}
|
||||
}
|
||||
else{
|
||||
while(middle != last){
|
||||
RandIt p = boost::movelib::upper_bound(first, middle, last[-1], comp);
|
||||
last = rotate_gcd(p, middle, last);
|
||||
middle = p;
|
||||
if(middle == first){
|
||||
break;
|
||||
}
|
||||
--p;
|
||||
do{
|
||||
--last;
|
||||
} while(middle != last && !comp(last[-1], *p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class RandIt, class Compare>
|
||||
void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
|
||||
{
|
||||
//#define BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
|
||||
#ifdef BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
|
||||
merge_bufferless_ONlogN(first, middle, last, comp);
|
||||
#else
|
||||
merge_bufferless_ON2(first, middle, last, comp);
|
||||
#endif //BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
|
||||
}
|
||||
|
||||
// [r_first, r_last) are already in the right part of the destination range.
|
||||
template <class Compare, class InputIterator, class InputOutIterator, class Op>
|
||||
void op_merge_with_right_placed
|
||||
( InputIterator first, InputIterator last
|
||||
, InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
|
||||
, Compare comp, Op op)
|
||||
{
|
||||
BOOST_ASSERT((last - first) == (r_first - dest_first));
|
||||
while ( first != last ) {
|
||||
if (r_first == r_last) {
|
||||
InputOutIterator end = op(forward_t(), first, last, dest_first);
|
||||
BOOST_ASSERT(end == r_last);
|
||||
(void)end;
|
||||
return;
|
||||
}
|
||||
else if (comp(*r_first, *first)) {
|
||||
op(r_first, dest_first);
|
||||
++r_first;
|
||||
}
|
||||
else {
|
||||
op(first, dest_first);
|
||||
++first;
|
||||
}
|
||||
++dest_first;
|
||||
}
|
||||
// Remaining [r_first, r_last) already in the correct place
|
||||
}
|
||||
|
||||
template <class Compare, class InputIterator, class InputOutIterator>
|
||||
void swap_merge_with_right_placed
|
||||
( InputIterator first, InputIterator last
|
||||
, InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
|
||||
, Compare comp)
|
||||
{
|
||||
op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, swap_op());
|
||||
}
|
||||
|
||||
// [first, last) are already in the right part of the destination range.
|
||||
template <class Compare, class Op, class BidirIterator, class BidirOutIterator>
|
||||
void op_merge_with_left_placed
|
||||
( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
|
||||
, BidirIterator const r_first, BidirIterator r_last
|
||||
, Compare comp, Op op)
|
||||
{
|
||||
BOOST_ASSERT((dest_last - last) == (r_last - r_first));
|
||||
while( r_first != r_last ) {
|
||||
if(first == last) {
|
||||
BidirOutIterator res = op(backward_t(), r_first, r_last, dest_last);
|
||||
BOOST_ASSERT(last == res);
|
||||
(void)res;
|
||||
return;
|
||||
}
|
||||
--r_last;
|
||||
--last;
|
||||
if(comp(*r_last, *last)){
|
||||
++r_last;
|
||||
--dest_last;
|
||||
op(last, dest_last);
|
||||
}
|
||||
else{
|
||||
++last;
|
||||
--dest_last;
|
||||
op(r_last, dest_last);
|
||||
}
|
||||
}
|
||||
// Remaining [first, last) already in the correct place
|
||||
}
|
||||
|
||||
// @endcond
|
||||
|
||||
// [irst, last) are already in the right part of the destination range.
|
||||
template <class Compare, class BidirIterator, class BidirOutIterator>
|
||||
void merge_with_left_placed
|
||||
( BidirOutIterator const first, BidirOutIterator last, BidirOutIterator dest_last
|
||||
, BidirIterator const r_first, BidirIterator r_last
|
||||
, Compare comp)
|
||||
{
|
||||
op_merge_with_left_placed(first, last, dest_last, r_first, r_last, comp, move_op());
|
||||
}
|
||||
|
||||
// [r_first, r_last) are already in the right part of the destination range.
|
||||
template <class Compare, class InputIterator, class InputOutIterator>
|
||||
void merge_with_right_placed
|
||||
( InputIterator first, InputIterator last
|
||||
, InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
|
||||
, Compare comp)
|
||||
{
|
||||
op_merge_with_right_placed(first, last, dest_first, r_first, r_last, comp, move_op());
|
||||
}
|
||||
|
||||
// [r_first, r_last) are already in the right part of the destination range.
|
||||
// [dest_first, r_first) is uninitialized memory
|
||||
template <class Compare, class InputIterator, class InputOutIterator>
|
||||
void uninitialized_merge_with_right_placed
|
||||
( InputIterator first, InputIterator last
|
||||
, InputOutIterator dest_first, InputOutIterator r_first, InputOutIterator r_last
|
||||
, Compare comp)
|
||||
{
|
||||
BOOST_ASSERT((last - first) == (r_first - dest_first));
|
||||
typedef typename iterator_traits<InputOutIterator>::value_type value_type;
|
||||
InputOutIterator const original_r_first = r_first;
|
||||
|
||||
destruct_n<value_type, InputOutIterator> d(dest_first);
|
||||
|
||||
while ( first != last && dest_first != original_r_first ) {
|
||||
if (r_first == r_last) {
|
||||
for(; dest_first != original_r_first; ++dest_first, ++first){
|
||||
::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
|
||||
d.incr();
|
||||
}
|
||||
d.release();
|
||||
InputOutIterator end = ::boost::move(first, last, original_r_first);
|
||||
BOOST_ASSERT(end == r_last);
|
||||
(void)end;
|
||||
return;
|
||||
}
|
||||
else if (comp(*r_first, *first)) {
|
||||
::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*r_first));
|
||||
d.incr();
|
||||
++r_first;
|
||||
}
|
||||
else {
|
||||
::new((iterator_to_raw_pointer)(dest_first)) value_type(::boost::move(*first));
|
||||
d.incr();
|
||||
++first;
|
||||
}
|
||||
++dest_first;
|
||||
}
|
||||
d.release();
|
||||
merge_with_right_placed(first, last, original_r_first, r_first, r_last, comp);
|
||||
}
|
||||
|
||||
/*
|
||||
// [r_first, r_last) are already in the right part of the destination range.
|
||||
// [dest_first, r_first) is uninitialized memory
|
||||
template <class Compare, class BidirOutIterator, class BidirIterator>
|
||||
void uninitialized_merge_with_left_placed
|
||||
( BidirOutIterator dest_first, BidirOutIterator r_first, BidirOutIterator r_last
|
||||
, BidirIterator first, BidirIterator last
|
||||
, Compare comp)
|
||||
{
|
||||
BOOST_ASSERT((last - first) == (r_last - r_first));
|
||||
typedef typename iterator_traits<BidirOutIterator>::value_type value_type;
|
||||
BidirOutIterator const original_r_last = r_last;
|
||||
|
||||
destruct_n<value_type> d(&*dest_last);
|
||||
|
||||
while ( first != last && dest_first != original_r_first ) {
|
||||
if (r_first == r_last) {
|
||||
for(; dest_first != original_r_first; ++dest_first, ++first){
|
||||
::new(&*dest_first) value_type(::boost::move(*first));
|
||||
d.incr();
|
||||
}
|
||||
d.release();
|
||||
BidirOutIterator end = ::boost::move(first, last, original_r_first);
|
||||
BOOST_ASSERT(end == r_last);
|
||||
(void)end;
|
||||
return;
|
||||
}
|
||||
else if (comp(*r_first, *first)) {
|
||||
::new(&*dest_first) value_type(::boost::move(*r_first));
|
||||
d.incr();
|
||||
++r_first;
|
||||
}
|
||||
else {
|
||||
::new(&*dest_first) value_type(::boost::move(*first));
|
||||
d.incr();
|
||||
++first;
|
||||
}
|
||||
++dest_first;
|
||||
}
|
||||
d.release();
|
||||
merge_with_right_placed(first, last, original_r_first, r_first, r_last, comp);
|
||||
}
|
||||
*/
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#define BOOST_MOVE_MERGE_HPP
|
||||
139
boost/move/algo/detail/merge_sort.hpp
Normal file
139
boost/move/algo/detail/merge_sort.hpp
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP
|
||||
#define BOOST_MOVE_DETAIL_MERGE_SORT_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/detail/workaround.hpp>
|
||||
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/algo/move.hpp>
|
||||
#include <boost/move/algo/detail/merge.hpp>
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/move/detail/destruct_n.hpp>
|
||||
#include <boost/move/algo/detail/insertion_sort.hpp>
|
||||
#include <cassert>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
// @cond
|
||||
|
||||
static const unsigned MergeSortInsertionSortThreshold = 16;
|
||||
|
||||
template <class RandIt, class Compare>
|
||||
void inplace_stable_sort(RandIt first, RandIt last, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::size_type size_type;
|
||||
if (size_type(last - first) <= size_type(MergeSortInsertionSortThreshold)) {
|
||||
insertion_sort(first, last, comp);
|
||||
return;
|
||||
}
|
||||
RandIt middle = first + (last - first) / 2;
|
||||
inplace_stable_sort(first, middle, comp);
|
||||
inplace_stable_sort(middle, last, comp);
|
||||
merge_bufferless_ONlogN_recursive
|
||||
(first, middle, last, size_type(middle - first), size_type(last - middle), comp);
|
||||
}
|
||||
|
||||
// @endcond
|
||||
|
||||
template<class RandIt, class RandIt2, class Compare>
|
||||
void merge_sort_copy( RandIt first, RandIt last
|
||||
, RandIt2 dest, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::size_type size_type;
|
||||
|
||||
size_type const count = size_type(last - first);
|
||||
if(count <= MergeSortInsertionSortThreshold){
|
||||
insertion_sort_copy(first, last, dest, comp);
|
||||
}
|
||||
else{
|
||||
size_type const half = count/2;
|
||||
merge_sort_copy(first + half, last , dest+half , comp);
|
||||
merge_sort_copy(first , first + half, first + half, comp);
|
||||
merge_with_right_placed
|
||||
( first + half, first + half + half
|
||||
, dest, dest+half, dest + count
|
||||
, comp);
|
||||
}
|
||||
}
|
||||
|
||||
template<class RandIt, class RandItRaw, class Compare>
|
||||
void merge_sort_uninitialized_copy( RandIt first, RandIt last
|
||||
, RandItRaw uninitialized
|
||||
, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::size_type size_type;
|
||||
typedef typename iterator_traits<RandIt>::value_type value_type;
|
||||
|
||||
size_type const count = size_type(last - first);
|
||||
if(count <= MergeSortInsertionSortThreshold){
|
||||
insertion_sort_uninitialized_copy(first, last, uninitialized, comp);
|
||||
}
|
||||
else{
|
||||
size_type const half = count/2;
|
||||
merge_sort_uninitialized_copy(first + half, last, uninitialized + half, comp);
|
||||
destruct_n<value_type, RandItRaw> d(uninitialized+half);
|
||||
d.incr(count-half);
|
||||
merge_sort_copy(first, first + half, first + half, comp);
|
||||
uninitialized_merge_with_right_placed
|
||||
( first + half, first + half + half
|
||||
, uninitialized, uninitialized+half, uninitialized+count
|
||||
, comp);
|
||||
d.release();
|
||||
}
|
||||
}
|
||||
|
||||
template<class RandIt, class RandItRaw, class Compare>
|
||||
void merge_sort( RandIt first, RandIt last, Compare comp
|
||||
, RandItRaw uninitialized)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::size_type size_type;
|
||||
typedef typename iterator_traits<RandIt>::value_type value_type;
|
||||
|
||||
size_type const count = size_type(last - first);
|
||||
if(count <= MergeSortInsertionSortThreshold){
|
||||
insertion_sort(first, last, comp);
|
||||
}
|
||||
else{
|
||||
size_type const half = count/2;
|
||||
size_type const rest = count - half;
|
||||
RandIt const half_it = first + half;
|
||||
RandIt const rest_it = first + rest;
|
||||
|
||||
merge_sort_uninitialized_copy(half_it, last, uninitialized, comp);
|
||||
destruct_n<value_type, RandItRaw> d(uninitialized);
|
||||
d.incr(rest);
|
||||
merge_sort_copy(first, half_it, rest_it, comp);
|
||||
merge_with_right_placed
|
||||
( uninitialized, uninitialized + rest
|
||||
, first, rest_it, last, antistable<Compare>(comp));
|
||||
}
|
||||
}
|
||||
|
||||
}} //namespace boost { namespace movelib{
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
|
@ -126,7 +127,7 @@ F uninitialized_move(I f, I l, F r
|
|||
}
|
||||
BOOST_CATCH(...){
|
||||
for (; back != r; ++back){
|
||||
back->~input_value_type();
|
||||
boost::movelib::iterator_to_raw_pointer(back)->~input_value_type();
|
||||
}
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
|
|
|
|||
86
boost/move/algo/predicate.hpp
Normal file
86
boost/move/algo/predicate.hpp
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_MOVE_ALGO_PREDICATE_HPP
|
||||
#define BOOST_MOVE_ALGO_PREDICATE_HPP
|
||||
|
||||
#include <boost/move/algo/move.hpp>
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
#include <boost/move/algo/detail/basic_op.hpp>
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/move/detail/destruct_n.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
template<class Comp>
|
||||
struct antistable
|
||||
{
|
||||
explicit antistable(Comp &comp)
|
||||
: m_comp(comp)
|
||||
{}
|
||||
|
||||
template<class U, class V>
|
||||
bool operator()(const U &u, const V & v)
|
||||
{ return !m_comp(v, u); }
|
||||
|
||||
private:
|
||||
antistable & operator=(const antistable &);
|
||||
Comp &m_comp;
|
||||
};
|
||||
|
||||
template <class Comp>
|
||||
class negate
|
||||
{
|
||||
public:
|
||||
negate()
|
||||
{}
|
||||
|
||||
explicit negate(Comp comp)
|
||||
: m_comp(comp)
|
||||
{}
|
||||
|
||||
template <class T1, class T2>
|
||||
bool operator()(const T1& l, const T2& r)
|
||||
{
|
||||
return !m_comp(l, r);
|
||||
}
|
||||
|
||||
private:
|
||||
Comp m_comp;
|
||||
};
|
||||
|
||||
|
||||
template <class Comp>
|
||||
class inverse
|
||||
{
|
||||
public:
|
||||
inverse()
|
||||
{}
|
||||
|
||||
explicit inverse(Comp comp)
|
||||
: m_comp(comp)
|
||||
{}
|
||||
|
||||
template <class T1, class T2>
|
||||
bool operator()(const T1& l, const T2& r)
|
||||
{
|
||||
return m_comp(r, l);
|
||||
}
|
||||
|
||||
private:
|
||||
Comp m_comp;
|
||||
};
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#define BOOST_MOVE_ALGO_PREDICATE_HPP
|
||||
55
boost/move/algo/unique.hpp
Normal file
55
boost/move/algo/unique.hpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2017-2017.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_MOVE_ALGO_UNIQUE_HPP
|
||||
#define BOOST_MOVE_ALGO_UNIQUE_HPP
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
//! <b>Requires</b>: The comparison function shall be an equivalence relation. The type of *first shall satisfy
|
||||
//! the MoveAssignable requirements
|
||||
//!
|
||||
//! <b>Effects</b>: For a nonempty range, eliminates all but the first element from every consecutive group
|
||||
//! of equivalent elements referred to by the iterator i in the range [first + 1, last) for which the
|
||||
//! following conditions hold: pred(*(i - 1), *i) != false.
|
||||
//!
|
||||
//! <b>Returns</b>: The end of the resulting range.
|
||||
//!
|
||||
//! <b>Complexity</b>: For nonempty ranges, exactly (last - first) - 1 applications of the corresponding predicate.
|
||||
template<class ForwardIterator, class BinaryPredicate>
|
||||
ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred)
|
||||
{
|
||||
if (first != last) {
|
||||
ForwardIterator next(first);
|
||||
++next;
|
||||
for (; next != last; ++next, ++first) {
|
||||
if (pred(*first, *next)) { //Find first equal element
|
||||
while (++next != last)
|
||||
if (!pred(*first, *next))
|
||||
*++first = ::boost::move(*next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
++first;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#define BOOST_MOVE_ALGO_UNIQUE_HPP
|
||||
|
|
@ -64,15 +64,7 @@
|
|||
#endif
|
||||
|
||||
//Move emulation rv breaks standard aliasing rules so add workarounds for some compilers
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4) && \
|
||||
(\
|
||||
defined(BOOST_GCC) || \
|
||||
(defined(BOOST_INTEL) && (BOOST_INTEL_CXX_VERSION >= 1300)) \
|
||||
)
|
||||
#define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
|
||||
#else
|
||||
#define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS
|
||||
#endif
|
||||
#define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
|
||||
|
||||
namespace boost {
|
||||
|
||||
|
|
|
|||
66
boost/move/detail/destruct_n.hpp
Normal file
66
boost/move/detail/destruct_n.hpp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2015-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
|
||||
#define BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib{
|
||||
|
||||
template<class T, class RandItUninit>
|
||||
class destruct_n
|
||||
{
|
||||
public:
|
||||
explicit destruct_n(RandItUninit raw)
|
||||
: m_ptr(raw), m_size()
|
||||
{}
|
||||
|
||||
void incr()
|
||||
{
|
||||
++m_size;
|
||||
}
|
||||
|
||||
void incr(std::size_t n)
|
||||
{
|
||||
m_size += n;
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
m_size = 0u;
|
||||
}
|
||||
|
||||
~destruct_n()
|
||||
{
|
||||
while(m_size--){
|
||||
m_ptr[m_size].~T();
|
||||
}
|
||||
}
|
||||
private:
|
||||
RandItUninit m_ptr;
|
||||
std::size_t m_size;
|
||||
};
|
||||
|
||||
}} //namespace boost { namespace movelib{
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
|
||||
|
|
@ -458,6 +458,31 @@ namespace move_detail {
|
|||
#define BOOST_MOVE_CLASSDFLTQ8 BOOST_MOVE_CLASSDFLTQ7, class Q7 = void
|
||||
#define BOOST_MOVE_CLASSDFLTQ9 BOOST_MOVE_CLASSDFLTQ8, class Q8 = void
|
||||
|
||||
//BOOST_MOVE_LAST_TARGN
|
||||
#define BOOST_MOVE_LAST_TARG0 void
|
||||
#define BOOST_MOVE_LAST_TARG1 P0
|
||||
#define BOOST_MOVE_LAST_TARG2 P1
|
||||
#define BOOST_MOVE_LAST_TARG3 P2
|
||||
#define BOOST_MOVE_LAST_TARG4 P3
|
||||
#define BOOST_MOVE_LAST_TARG5 P4
|
||||
#define BOOST_MOVE_LAST_TARG6 P5
|
||||
#define BOOST_MOVE_LAST_TARG7 P6
|
||||
#define BOOST_MOVE_LAST_TARG8 P7
|
||||
#define BOOST_MOVE_LAST_TARG9 P8
|
||||
|
||||
//BOOST_MOVE_LAST_TARGQN
|
||||
#define BOOST_MOVE_LAST_TARGQ0 void
|
||||
#define BOOST_MOVE_LAST_TARGQ1 Q0
|
||||
#define BOOST_MOVE_LAST_TARGQ2 Q1
|
||||
#define BOOST_MOVE_LAST_TARGQ3 Q2
|
||||
#define BOOST_MOVE_LAST_TARGQ4 Q3
|
||||
#define BOOST_MOVE_LAST_TARGQ5 Q4
|
||||
#define BOOST_MOVE_LAST_TARGQ6 Q5
|
||||
#define BOOST_MOVE_LAST_TARGQ7 Q6
|
||||
#define BOOST_MOVE_LAST_TARGQ8 Q7
|
||||
#define BOOST_MOVE_LAST_TARGQ9 Q8
|
||||
|
||||
|
||||
//BOOST_MOVE_TARGN
|
||||
#define BOOST_MOVE_TARG0
|
||||
#define BOOST_MOVE_TARG1 P0
|
||||
|
|
|
|||
59
boost/move/detail/iterator_to_raw_pointer.hpp
Normal file
59
boost/move/detail/iterator_to_raw_pointer.hpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/container for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
|
||||
#define BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/move/detail/to_raw_pointer.hpp>
|
||||
#include <boost/move/detail/pointer_element.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
inline T* iterator_to_pointer(T* i)
|
||||
{ return i; }
|
||||
|
||||
template <class Iterator>
|
||||
inline typename boost::movelib::iterator_traits<Iterator>::pointer
|
||||
iterator_to_pointer(const Iterator &i)
|
||||
{ return i.operator->(); }
|
||||
|
||||
template <class Iterator>
|
||||
struct iterator_to_element_ptr
|
||||
{
|
||||
typedef typename boost::movelib::iterator_traits<Iterator>::pointer pointer;
|
||||
typedef typename boost::movelib::pointer_element<pointer>::type element_type;
|
||||
typedef element_type* type;
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
template <class Iterator>
|
||||
inline typename boost::movelib::detail::iterator_to_element_ptr<Iterator>::type
|
||||
iterator_to_raw_pointer(const Iterator &i)
|
||||
{
|
||||
return ::boost::movelib::to_raw_pointer
|
||||
( ::boost::movelib::detail::iterator_to_pointer(i) );
|
||||
}
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
|
||||
30
boost/move/detail/placement_new.hpp
Normal file
30
boost/move/detail/placement_new.hpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef BOOST_MOVE_DETAIL_PLACEMENT_NEW_HPP
|
||||
#define BOOST_MOVE_DETAIL_PLACEMENT_NEW_HPP
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2015. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/container for documentation.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
struct boost_move_new_t{};
|
||||
|
||||
//avoid including <new>
|
||||
inline void *operator new(std::size_t, void *p, boost_move_new_t)
|
||||
{ return p; }
|
||||
|
||||
inline void operator delete(void *, void *, boost_move_new_t)
|
||||
{}
|
||||
|
||||
#endif //BOOST_MOVE_DETAIL_PLACEMENT_NEW_HPP
|
||||
168
boost/move/detail/pointer_element.hpp
Normal file
168
boost/move/detail/pointer_element.hpp
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2017. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_MOVE_DETAIL_POINTER_ELEMENT_HPP
|
||||
#define BOOST_MOVE_DETAIL_POINTER_ELEMENT_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
|
||||
#include <boost/move/detail/workaround.hpp>
|
||||
#endif //BOOST_MOVE_DETAIL_WORKAROUND_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
namespace detail{
|
||||
|
||||
//////////////////////
|
||||
//struct first_param
|
||||
//////////////////////
|
||||
|
||||
template <typename T> struct first_param
|
||||
{ typedef void type; };
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <template <typename, typename...> class TemplateClass, typename T, typename... Args>
|
||||
struct first_param< TemplateClass<T, Args...> >
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
#else //C++03 compilers
|
||||
|
||||
template < template //0arg
|
||||
<class
|
||||
> class TemplateClass, class T
|
||||
>
|
||||
struct first_param
|
||||
< TemplateClass<T> >
|
||||
{ typedef T type; };
|
||||
|
||||
template < template //1arg
|
||||
<class,class
|
||||
> class TemplateClass, class T
|
||||
, class P0>
|
||||
struct first_param
|
||||
< TemplateClass<T, P0> >
|
||||
{ typedef T type; };
|
||||
|
||||
template < template //2arg
|
||||
<class,class,class
|
||||
> class TemplateClass, class T
|
||||
, class P0, class P1>
|
||||
struct first_param
|
||||
< TemplateClass<T, P0, P1> >
|
||||
{ typedef T type; };
|
||||
|
||||
template < template //3arg
|
||||
<class,class,class,class
|
||||
> class TemplateClass, class T
|
||||
, class P0, class P1, class P2>
|
||||
struct first_param
|
||||
< TemplateClass<T, P0, P1, P2> >
|
||||
{ typedef T type; };
|
||||
|
||||
template < template //4arg
|
||||
<class,class,class,class,class
|
||||
> class TemplateClass, class T
|
||||
, class P0, class P1, class P2, class P3>
|
||||
struct first_param
|
||||
< TemplateClass<T, P0, P1, P2, P3> >
|
||||
{ typedef T type; };
|
||||
|
||||
template < template //5arg
|
||||
<class,class,class,class,class,class
|
||||
> class TemplateClass, class T
|
||||
, class P0, class P1, class P2, class P3, class P4>
|
||||
struct first_param
|
||||
< TemplateClass<T, P0, P1, P2, P3, P4> >
|
||||
{ typedef T type; };
|
||||
|
||||
template < template //6arg
|
||||
<class,class,class,class,class,class,class
|
||||
> class TemplateClass, class T
|
||||
, class P0, class P1, class P2, class P3, class P4, class P5>
|
||||
struct first_param
|
||||
< TemplateClass<T, P0, P1, P2, P3, P4, P5> >
|
||||
{ typedef T type; };
|
||||
|
||||
template < template //7arg
|
||||
<class,class,class,class,class,class,class,class
|
||||
> class TemplateClass, class T
|
||||
, class P0, class P1, class P2, class P3, class P4, class P5, class P6>
|
||||
struct first_param
|
||||
< TemplateClass<T, P0, P1, P2, P3, P4, P5, P6> >
|
||||
{ typedef T type; };
|
||||
|
||||
template < template //8arg
|
||||
<class,class,class,class,class,class,class,class,class
|
||||
> class TemplateClass, class T
|
||||
, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
|
||||
struct first_param
|
||||
< TemplateClass<T, P0, P1, P2, P3, P4, P5, P6, P7> >
|
||||
{ typedef T type; };
|
||||
|
||||
template < template //9arg
|
||||
<class,class,class,class,class,class,class,class,class,class
|
||||
> class TemplateClass, class T
|
||||
, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
|
||||
struct first_param
|
||||
< TemplateClass<T, P0, P1, P2, P3, P4, P5, P6, P7, P8> >
|
||||
{ typedef T type; };
|
||||
|
||||
#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename T>
|
||||
struct has_internal_pointer_element
|
||||
{
|
||||
template <typename X>
|
||||
static char test(int, typename X::element_type*);
|
||||
|
||||
template <typename X>
|
||||
static int test(...);
|
||||
|
||||
static const bool value = (1 == sizeof(test<T>(0, 0)));
|
||||
};
|
||||
|
||||
template<class Ptr, bool = has_internal_pointer_element<Ptr>::value>
|
||||
struct pointer_element_impl
|
||||
{
|
||||
typedef typename Ptr::element_type type;
|
||||
};
|
||||
|
||||
template<class Ptr>
|
||||
struct pointer_element_impl<Ptr, false>
|
||||
{
|
||||
typedef typename boost::movelib::detail::first_param<Ptr>::type type;
|
||||
};
|
||||
|
||||
} //namespace detail{
|
||||
|
||||
template <typename Ptr>
|
||||
struct pointer_element
|
||||
{
|
||||
typedef typename ::boost::movelib::detail::pointer_element_impl<Ptr>::type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct pointer_element<T*>
|
||||
{ typedef T type; };
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#endif // defined(BOOST_MOVE_DETAIL_POINTER_ELEMENT_HPP)
|
||||
171
boost/move/detail/reverse_iterator.hpp
Normal file
171
boost/move/detail/reverse_iterator.hpp
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2014-2014
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP
|
||||
#define BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/move/detail/meta_utils.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
template<class It>
|
||||
class reverse_iterator
|
||||
{
|
||||
public:
|
||||
typedef typename boost::movelib::iterator_traits<It>::pointer pointer;
|
||||
typedef typename boost::movelib::iterator_traits<It>::reference reference;
|
||||
typedef typename boost::movelib::iterator_traits<It>::difference_type difference_type;
|
||||
typedef typename boost::movelib::iterator_traits<It>::iterator_category iterator_category;
|
||||
typedef typename boost::movelib::iterator_traits<It>::value_type value_type;
|
||||
|
||||
|
||||
typedef It iterator_type;
|
||||
|
||||
reverse_iterator()
|
||||
: m_current() //Value initialization to achieve "null iterators" (N3644)
|
||||
{}
|
||||
|
||||
explicit reverse_iterator(It r)
|
||||
: m_current(r)
|
||||
{}
|
||||
|
||||
reverse_iterator(const reverse_iterator& r)
|
||||
: m_current(r.base())
|
||||
{}
|
||||
|
||||
template<class OtherIt>
|
||||
reverse_iterator( const reverse_iterator<OtherIt>& r
|
||||
, typename boost::move_detail::enable_if_convertible<OtherIt, It>::type* =0
|
||||
)
|
||||
: m_current(r.base())
|
||||
{}
|
||||
|
||||
reverse_iterator & operator=( const reverse_iterator& r)
|
||||
{ m_current = r.base(); return *this; }
|
||||
|
||||
template<class OtherIt>
|
||||
typename boost::move_detail::enable_if_convertible<OtherIt, It, reverse_iterator &>::type
|
||||
operator=( const reverse_iterator<OtherIt>& r)
|
||||
{ m_current = r.base(); return *this; }
|
||||
|
||||
It base() const
|
||||
{ return m_current; }
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
It temp(m_current);
|
||||
--temp;
|
||||
reference r = *temp;
|
||||
return r;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{
|
||||
It temp(m_current);
|
||||
--temp;
|
||||
return iterator_arrow_result(temp);
|
||||
}
|
||||
|
||||
reference operator[](difference_type off) const
|
||||
{
|
||||
return this->m_current[-off - 1];
|
||||
}
|
||||
|
||||
reverse_iterator& operator++()
|
||||
{
|
||||
--m_current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reverse_iterator operator++(int)
|
||||
{
|
||||
reverse_iterator temp((*this));
|
||||
--m_current;
|
||||
return temp;
|
||||
}
|
||||
|
||||
reverse_iterator& operator--()
|
||||
{
|
||||
++m_current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reverse_iterator operator--(int)
|
||||
{
|
||||
reverse_iterator temp((*this));
|
||||
++m_current;
|
||||
return temp;
|
||||
}
|
||||
|
||||
friend bool operator==(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current == r.m_current; }
|
||||
|
||||
friend bool operator!=(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current != r.m_current; }
|
||||
|
||||
friend bool operator<(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current > r.m_current; }
|
||||
|
||||
friend bool operator<=(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current >= r.m_current; }
|
||||
|
||||
friend bool operator>(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current < r.m_current; }
|
||||
|
||||
friend bool operator>=(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return l.m_current <= r.m_current; }
|
||||
|
||||
reverse_iterator& operator+=(difference_type off)
|
||||
{ m_current -= off; return *this; }
|
||||
|
||||
reverse_iterator& operator-=(difference_type off)
|
||||
{ m_current += off; return *this; }
|
||||
|
||||
friend reverse_iterator operator+(reverse_iterator l, difference_type off)
|
||||
{ return (l += off); }
|
||||
|
||||
friend reverse_iterator operator+(difference_type off, reverse_iterator r)
|
||||
{ return (r += off); }
|
||||
|
||||
friend reverse_iterator operator-(reverse_iterator l, difference_type off)
|
||||
{ return (l-= off); }
|
||||
|
||||
friend difference_type operator-(const reverse_iterator& l, const reverse_iterator& r)
|
||||
{ return r.m_current - l.m_current; }
|
||||
|
||||
private:
|
||||
It m_current; // the wrapped iterator
|
||||
};
|
||||
|
||||
template< class Iterator >
|
||||
reverse_iterator<Iterator> make_reverse_iterator( Iterator i )
|
||||
{
|
||||
return reverse_iterator<Iterator>(i);
|
||||
}
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP
|
||||
45
boost/move/detail/to_raw_pointer.hpp
Normal file
45
boost/move/detail/to_raw_pointer.hpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2017-2017
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_MOVE_DETAIL_TO_RAW_POINTER_HPP
|
||||
#define BOOST_MOVE_DETAIL_TO_RAW_POINTER_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/detail/workaround.hpp>
|
||||
#include <boost/move/detail/pointer_element.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
template <class T>
|
||||
BOOST_MOVE_FORCEINLINE T* to_raw_pointer(T* p)
|
||||
{ return p; }
|
||||
|
||||
template <class Pointer>
|
||||
BOOST_MOVE_FORCEINLINE typename boost::movelib::pointer_element<Pointer>::type*
|
||||
to_raw_pointer(const Pointer &p)
|
||||
{ return ::boost::movelib::to_raw_pointer(p.operator->()); }
|
||||
|
||||
} //namespace movelib
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_MOVE_DETAIL_TO_RAW_POINTER_HPP
|
||||
|
|
@ -967,14 +967,13 @@ typedef union max_align max_align_t;
|
|||
#if !defined(BOOST_NO_ALIGNMENT)
|
||||
|
||||
template<std::size_t Len, std::size_t Align>
|
||||
struct aligned_storage_impl;
|
||||
struct aligned_struct;
|
||||
|
||||
#define BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(A)\
|
||||
template<std::size_t Len>\
|
||||
struct BOOST_ALIGNMENT(A) aligned_storage_impl<Len, A>\
|
||||
struct BOOST_ALIGNMENT(A) aligned_struct<Len, A>\
|
||||
{\
|
||||
char dummy[Len];\
|
||||
typedef aligned_storage_impl<Len, A> type;\
|
||||
};\
|
||||
//
|
||||
|
||||
|
|
@ -995,6 +994,20 @@ BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1000)
|
|||
|
||||
#undef BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT
|
||||
|
||||
// Workaround for bogus [-Wignored-attributes] warning on GCC 6.x/7.x: don't use a type that "directly" carries the alignment attribute.
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82270
|
||||
template<std::size_t Len, std::size_t Align>
|
||||
struct aligned_struct_wrapper
|
||||
{
|
||||
aligned_struct<Len, Align> dummy;
|
||||
};
|
||||
|
||||
template<std::size_t Len, std::size_t Align>
|
||||
struct aligned_storage_impl
|
||||
{
|
||||
typedef aligned_struct_wrapper<Len, Align> type;
|
||||
};
|
||||
|
||||
#else //BOOST_NO_ALIGNMENT
|
||||
|
||||
template<class T, std::size_t Len>
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ class is_convertible
|
|||
#define BOOST_MOVE_TT_DECL
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(UNDER_CE)
|
||||
#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(_M_ARM64) && !defined(UNDER_CE)
|
||||
#define BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue