mirror of
https://github.com/boostorg/move.git
synced 2025-07-31 12:57:14 +02:00
Merge branch 'develop'
This commit is contained in:
@ -14,6 +14,7 @@ import quickbook ;
|
||||
doxygen autodoc
|
||||
:
|
||||
[ glob ../../../boost/move/*.hpp ]
|
||||
[ glob ../../../boost/move/algo/*.hpp ]
|
||||
:
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
@ -30,6 +31,7 @@ doxygen autodoc
|
||||
\"BOOST_MOVE_DOC0PTR(T)=std::nullptr_t\" \\
|
||||
\"BOOST_MOVE_DOC1ST(T1, T2)=T1\" \\
|
||||
\"BOOST_MOVE_DOCIGN(T1) \"\\
|
||||
\"BOOST_MOVE_FORCEINLINE=inline\" \\
|
||||
"
|
||||
;
|
||||
|
||||
|
20
doc/move.qbk
20
doc/move.qbk
@ -762,6 +762,16 @@ Many thanks to all boosters that have tested, reviewed and improved the library.
|
||||
|
||||
[section:release_notes Release Notes]
|
||||
|
||||
[section:release_notes_boost_1_61 Boost 1.61 Release]
|
||||
|
||||
* Experimental: asymptotically optimal bufferless merge and sort algorithms: [funcref boost::movelib::adaptive_merge adaptive_merge]
|
||||
and [funcref boost::movelib::adaptive_sort adaptive_sort].
|
||||
|
||||
* Fixed bug:
|
||||
* [@https://svn.boost.org/trac/boost/ticket/11758 Trac #11758: ['"BOOST_MOVABLE_BUT_NOT_COPYABLE doesn't reset private access with rvalue ref version"]],
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:release_notes_boost_1_60 Boost 1.60 Release]
|
||||
|
||||
* Fixed bug:
|
||||
@ -771,11 +781,11 @@ Many thanks to all boosters that have tested, reviewed and improved the library.
|
||||
|
||||
[section:release_notes_boost_1_59 Boost 1.59 Release]
|
||||
|
||||
* Changed `unique_ptr`'s converting constructor taking the source by value in C++03 compilers to allow simple conversions
|
||||
from convertible types returned by value.
|
||||
* Fixed bug:
|
||||
* [@https://svn.boost.org/trac/boost/ticket/11229 Trac #11229: ['"vector incorrectly copies move-only objects using memcpy"]],
|
||||
* [@https://svn.boost.org/trac/boost/ticket/11510 Trac #11510: ['"unique_ptr: -Wshadow warning issued"]],
|
||||
* Changed `unique_ptr`'s converting constructor taking the source by value in C++03 compilers to allow simple conversions
|
||||
from convertible types returned by value.
|
||||
* Fixed bug:
|
||||
* [@https://svn.boost.org/trac/boost/ticket/11229 Trac #11229: ['"vector incorrectly copies move-only objects using memcpy"]],
|
||||
* [@https://svn.boost.org/trac/boost/ticket/11510 Trac #11510: ['"unique_ptr: -Wshadow warning issued"]],
|
||||
|
||||
[endsect]
|
||||
|
||||
|
@ -22,9 +22,8 @@
|
||||
|
||||
//Based on Boost.Core's swap.
|
||||
//Many thanks to Steven Watanabe, Joseph Gauterin and Niels Dekker.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef> //for std::size_t
|
||||
#include <boost/move/detail/workaround.hpp> //forceinline
|
||||
|
||||
//Try to avoid including <algorithm>, as it's quite big
|
||||
#if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB)
|
||||
@ -156,7 +155,7 @@ struct and_op_not
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
|
||||
BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
|
||||
{
|
||||
//use std::swap if argument dependent lookup fails
|
||||
//Use using directive ("using namespace xxx;") instead as some older compilers
|
||||
@ -166,14 +165,14 @@ void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::mov
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void swap_proxy(T& x, T& y
|
||||
BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
|
||||
, typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>
|
||||
, boost_move_member_swap::has_member_swap<T> >
|
||||
>::type* = 0)
|
||||
{ T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t); }
|
||||
|
||||
template<class T>
|
||||
void swap_proxy(T& x, T& y
|
||||
BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
|
||||
, typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T>
|
||||
, boost_move_member_swap::has_member_swap<T> >
|
||||
>::type* = 0)
|
||||
@ -186,7 +185,7 @@ void swap_proxy(T& x, T& y
|
||||
namespace boost_move_adl_swap{
|
||||
|
||||
template<class T>
|
||||
void swap_proxy(T& x, T& y)
|
||||
BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(x, y);
|
||||
@ -223,11 +222,45 @@ namespace boost{
|
||||
//! - Otherwise a move-based swap is called, equivalent to:
|
||||
//! <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>.
|
||||
template<class T>
|
||||
void adl_move_swap(T& x, T& y)
|
||||
BOOST_MOVE_FORCEINLINE void adl_move_swap(T& x, T& y)
|
||||
{
|
||||
::boost_move_adl_swap::swap_proxy(x, y);
|
||||
}
|
||||
|
||||
//! Exchanges elements between range [first1, last1) and another range starting at first2
|
||||
//! using boost::adl_move_swap.
|
||||
//!
|
||||
//! Parameters:
|
||||
//! first1, last1 - the first range of elements to swap
|
||||
//! first2 - beginning of the second range of elements to swap
|
||||
//!
|
||||
//! Type requirements:
|
||||
//! - ForwardIt1, ForwardIt2 must meet the requirements of ForwardIterator.
|
||||
//! - The types of dereferenced ForwardIt1 and ForwardIt2 must meet the
|
||||
//! requirements of Swappable
|
||||
//!
|
||||
//! Return value: Iterator to the element past the last element exchanged in the range
|
||||
//! beginning with first2.
|
||||
template<class ForwardIt1, class ForwardIt2>
|
||||
ForwardIt2 adl_move_swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
|
||||
{
|
||||
while (first1 != last1) {
|
||||
::boost::adl_move_swap(*first1, *first2);
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
return first2;
|
||||
}
|
||||
|
||||
template<class BidirIt1, class BidirIt2>
|
||||
BidirIt2 adl_move_swap_ranges_backward(BidirIt1 first1, BidirIt1 last1, BidirIt2 last2)
|
||||
{
|
||||
while (first1 != last1) {
|
||||
::boost::adl_move_swap(*(--last1), *(--last2));
|
||||
}
|
||||
return last2;
|
||||
}
|
||||
|
||||
} //namespace boost{
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
|
||||
|
67
include/boost/move/algo/adaptive_merge.hpp
Normal file
67
include/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
|
63
include/boost/move/algo/adaptive_sort.hpp
Normal file
63
include/boost/move/algo/adaptive_sort.hpp
Normal file
@ -0,0 +1,63 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 Compare>
|
||||
void adaptive_sort( RandIt first, 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_sort_impl(first, size_type(last - first), comp, xbuf);
|
||||
}
|
||||
|
||||
} //namespace movelib {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#define BOOST_MOVE_ADAPTIVE_SORT_HPP
|
2284
include/boost/move/algo/detail/adaptive_sort_merge.hpp
Normal file
2284
include/boost/move/algo/detail/adaptive_sort_merge.hpp
Normal file
File diff suppressed because it is too large
Load Diff
63
include/boost/move/algo/detail/basic_op.hpp
Normal file
63
include/boost/move/algo/detail/basic_op.hpp
Normal file
@ -0,0 +1,63 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
|
||||
struct forward_t{};
|
||||
struct backward_t{};
|
||||
|
||||
struct move_op
|
||||
{
|
||||
template <class SourceIt, class DestinationIt>
|
||||
void operator()(SourceIt source, DestinationIt dest)
|
||||
{ *dest = ::boost::move(*source); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
DestinationIt operator()(forward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
|
||||
{ return ::boost::move(first, last, dest_begin); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_last)
|
||||
{ return ::boost::move_backward(first, last, dest_last); }
|
||||
};
|
||||
|
||||
struct swap_op
|
||||
{
|
||||
template <class SourceIt, class DestinationIt>
|
||||
void operator()(SourceIt source, DestinationIt dest)
|
||||
{ boost::adl_move_swap(*dest, *source); }
|
||||
|
||||
template <class SourceIt, class DestinationIt>
|
||||
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>
|
||||
DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_begin)
|
||||
{ return boost::adl_move_swap_ranges_backward(first, last, dest_begin); }
|
||||
};
|
||||
|
||||
}} //namespace boost::movelib
|
||||
|
||||
#endif //BOOST_MOVE_ALGO_BASIC_OP
|
120
include/boost/move/algo/detail/bufferless_merge_sort.hpp
Normal file
120
include/boost/move/algo/detail/bufferless_merge_sort.hpp
Normal file
@ -0,0 +1,120 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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_ALGO_BUFFERLESS_MERGE_SORT_HPP
|
||||
#define BOOST_MOVE_ALGO_BUFFERLESS_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/adl_move_swap.hpp>
|
||||
|
||||
#include <boost/move/algo/move.hpp>
|
||||
#include <boost/move/algo/detail/merge.hpp>
|
||||
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/move/algo/detail/insertion_sort.hpp>
|
||||
#include <cassert>
|
||||
|
||||
namespace boost {
|
||||
namespace movelib {
|
||||
// @cond
|
||||
namespace detail_bufferless_mergesort {
|
||||
|
||||
static const std::size_t UnbufferedMergeSortInsertionSortThreshold = 16;
|
||||
|
||||
//A in-placed version based on:
|
||||
//Jyrki Katajainen, Tomi Pasanen, Jukka Teuhola.
|
||||
//``Practical in-place mergesort''. Nordic Journal of Computing, 1996.
|
||||
|
||||
template<class RandIt, class Compare>
|
||||
void bufferless_merge_sort(RandIt first, RandIt last, Compare comp);
|
||||
|
||||
template<class RandIt, class Compare>
|
||||
void swap_sort(RandIt const first, RandIt const last, RandIt const buffer_first, RandIt const buffer_last, Compare comp, bool buffer_at_right)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::size_type size_type;
|
||||
if (size_type(last - first) > UnbufferedMergeSortInsertionSortThreshold) {
|
||||
RandIt m = first + (last - first) / 2;
|
||||
bufferless_merge_sort(first, m, comp);
|
||||
bufferless_merge_sort(m, last, comp);
|
||||
if(buffer_at_right){
|
||||
//Use antistable to minimize movements (if equal, move first half elements
|
||||
//to maximize the chance last half elements are already in place.
|
||||
boost::movelib::swap_merge_right(first, m, last, buffer_last, boost::movelib::antistable<Compare>(comp));
|
||||
}
|
||||
else{
|
||||
boost::movelib::swap_merge_left(buffer_first, first, m, last, comp);
|
||||
}
|
||||
}
|
||||
else
|
||||
boost::movelib::insertion_sort_swap(first, last, buffer_first, comp);
|
||||
}
|
||||
|
||||
template<class RandIt, class Compare>
|
||||
void bufferless_merge_sort(RandIt const first, RandIt const last, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits<RandIt>::size_type size_type;
|
||||
size_type len = size_type(last - first);
|
||||
if (len > size_type(UnbufferedMergeSortInsertionSortThreshold)) {
|
||||
len /= 2;
|
||||
RandIt h = last - len; //ceil(half)
|
||||
RandIt f = h - len; //ceil(first)
|
||||
swap_sort(f, h, h, last, comp, true); //[h, last) contains sorted elements
|
||||
|
||||
//Divide unsorted first half in two
|
||||
len = size_type(h - first);
|
||||
while (len > size_type(UnbufferedMergeSortInsertionSortThreshold)) {
|
||||
len /= 2;
|
||||
RandIt n = h; //new end
|
||||
h = n - len; //ceil(half')
|
||||
f = h - len; //ceil(first')
|
||||
swap_sort(h, n, f, h, comp, false); // the first half of the previous working area [f, h)
|
||||
//contains sorted elements: working area in the middle [h, n)
|
||||
//Now merge small (left) sorted with big (right) sorted (buffer is between them)
|
||||
swap_merge_with_right_placed(f, h, h, n, last, comp);
|
||||
}
|
||||
|
||||
boost::movelib::insertion_sort(first, h, comp);
|
||||
boost::movelib::merge_bufferless(first, h, last, comp);
|
||||
}
|
||||
else{
|
||||
boost::movelib::insertion_sort(first, last, comp);
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace detail_bufferless_mergesort {
|
||||
|
||||
// @endcond
|
||||
|
||||
//Unstable bufferless merge sort
|
||||
template<class RandIt, class Compare>
|
||||
void bufferless_merge_sort(RandIt first, RandIt last, Compare comp)
|
||||
{
|
||||
detail_bufferless_mergesort::bufferless_merge_sort(first, last, comp);
|
||||
}
|
||||
|
||||
}} //namespace boost::movelib
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_ALGO_BUFFERLESS_MERGE_SORT_HPP
|
127
include/boost/move/algo/detail/insertion_sort.hpp
Normal file
127
include/boost/move/algo/detail/insertion_sort.hpp
Normal file
@ -0,0 +1,127 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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>
|
||||
|
||||
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>
|
||||
void insertion_sort_uninitialized_copy
|
||||
(BirdirectionalIterator first1, BirdirectionalIterator const last1
|
||||
, typename iterator_traits<BirdirectionalIterator>::value_type* const first2
|
||||
, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits<BirdirectionalIterator>::value_type value_type;
|
||||
if (first1 != last1){
|
||||
value_type* last2 = first2;
|
||||
::new(last2, boost_move_new_t()) value_type(move(*first1));
|
||||
destruct_n<value_type> d(first2);
|
||||
d.incr();
|
||||
for (++last2; ++first1 != last1; ++last2){
|
||||
value_type* j2 = last2;
|
||||
value_type* k2 = j2;
|
||||
if (comp(*first1, *--k2)){
|
||||
::new(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(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
|
444
include/boost/move/algo/detail/merge.hpp
Normal file
444
include/boost/move/algo/detail/merge.hpp
Normal file
@ -0,0 +1,444 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/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);
|
||||
}
|
||||
else{
|
||||
buf_first = 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());
|
||||
}
|
||||
|
||||
// cost: min(L1,L2)^2+max(L1,L2)
|
||||
template<class RandIt, class Compare>
|
||||
void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
|
||||
{
|
||||
if((middle - first) < (last - middle)){
|
||||
while(first != middle){
|
||||
RandIt const old_last1 = middle;
|
||||
middle = 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 = 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 Comp>
|
||||
struct antistable
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
// [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());
|
||||
}
|
||||
|
||||
// [r_first, r_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
|
||||
|
||||
// [r_first, r_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> 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(&*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(&*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
|
124
include/boost/move/algo/detail/merge_sort.hpp
Normal file
124
include/boost/move/algo/detail/merge_sort.hpp
Normal file
@ -0,0 +1,124 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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;
|
||||
|
||||
// @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 Compare>
|
||||
void merge_sort_uninitialized_copy( RandIt first, RandIt last
|
||||
, typename iterator_traits<RandIt>::value_type* 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> 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 Compare>
|
||||
void merge_sort( RandIt first, RandIt last, Compare comp
|
||||
, typename iterator_traits<RandIt>::value_type* 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> 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
|
155
include/boost/move/algo/move.hpp
Normal file
155
include/boost/move/algo/move.hpp
Normal file
@ -0,0 +1,155 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2012-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BOOST_MOVE_ALGO_MOVE_HPP
|
||||
#define BOOST_MOVE_ALGO_MOVE_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
|
||||
|
||||
//! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last -
|
||||
//! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first),
|
||||
//! performs *(result + n) = ::boost::move (*(first + n)).
|
||||
//!
|
||||
//! <b>Effects</b>: result + (last - first).
|
||||
//!
|
||||
//! <b>Requires</b>: result shall not be in the range [first,last).
|
||||
//!
|
||||
//! <b>Complexity</b>: Exactly last - first move assignments.
|
||||
template <typename I, // I models InputIterator
|
||||
typename O> // O models OutputIterator
|
||||
O move(I f, I l, O result)
|
||||
{
|
||||
while (f != l) {
|
||||
*result = ::boost::move(*f);
|
||||
++f; ++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move_backward
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! <b>Effects</b>: Moves elements in the range [first,last) into the range
|
||||
//! [result - (last-first),result) starting from last - 1 and proceeding to
|
||||
//! first. For each positive integer n <= (last - first),
|
||||
//! performs *(result - n) = ::boost::move(*(last - n)).
|
||||
//!
|
||||
//! <b>Requires</b>: result shall not be in the range [first,last).
|
||||
//!
|
||||
//! <b>Returns</b>: result - (last - first).
|
||||
//!
|
||||
//! <b>Complexity</b>: Exactly last - first assignments.
|
||||
template <typename I, // I models BidirectionalIterator
|
||||
typename O> // O models BidirectionalIterator
|
||||
O move_backward(I f, I l, O result)
|
||||
{
|
||||
while (f != l) {
|
||||
--l; --result;
|
||||
*result = ::boost::move(*l);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
using ::std::move_backward;
|
||||
|
||||
#endif //!defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uninitialized_move
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! <b>Effects</b>:
|
||||
//! \code
|
||||
//! for (; first != last; ++result, ++first)
|
||||
//! new (static_cast<void*>(&*result))
|
||||
//! typename iterator_traits<ForwardIterator>::value_type(boost::move(*first));
|
||||
//! \endcode
|
||||
//!
|
||||
//! <b>Returns</b>: result
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_move(I f, I l, F r
|
||||
/// @cond
|
||||
// ,typename ::boost::move_detail::enable_if<has_move_emulation_enabled<typename boost::movelib::iterator_traits<I>::value_type> >::type* = 0
|
||||
/// @endcond
|
||||
)
|
||||
{
|
||||
typedef typename boost::movelib::iterator_traits<I>::value_type input_value_type;
|
||||
|
||||
F back = r;
|
||||
BOOST_TRY{
|
||||
while (f != l) {
|
||||
void * const addr = static_cast<void*>(::boost::move_detail::addressof(*r));
|
||||
::new(addr) input_value_type(::boost::move(*f));
|
||||
++f; ++r;
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
for (; back != r; ++back){
|
||||
back->~input_value_type();
|
||||
}
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
return r;
|
||||
}
|
||||
|
||||
/// @cond
|
||||
/*
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_move(I f, I l, F r,
|
||||
typename ::boost::move_detail::disable_if<has_move_emulation_enabled<typename boost::movelib::iterator_traits<I>::value_type> >::type* = 0)
|
||||
{
|
||||
return std::uninitialized_copy(f, l, r);
|
||||
}
|
||||
*/
|
||||
|
||||
/// @endcond
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_ALGO_MOVE_HPP
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/iterator.hpp>
|
||||
#include <boost/move/algo/move.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
|
||||
#include <algorithm> //copy, copy_backward
|
||||
@ -33,122 +34,6 @@
|
||||
|
||||
namespace boost {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
|
||||
|
||||
//! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last -
|
||||
//! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first),
|
||||
//! performs *(result + n) = ::boost::move (*(first + n)).
|
||||
//!
|
||||
//! <b>Effects</b>: result + (last - first).
|
||||
//!
|
||||
//! <b>Requires</b>: result shall not be in the range [first,last).
|
||||
//!
|
||||
//! <b>Complexity</b>: Exactly last - first move assignments.
|
||||
template <typename I, // I models InputIterator
|
||||
typename O> // O models OutputIterator
|
||||
O move(I f, I l, O result)
|
||||
{
|
||||
while (f != l) {
|
||||
*result = ::boost::move(*f);
|
||||
++f; ++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// move_backward
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! <b>Effects</b>: Moves elements in the range [first,last) into the range
|
||||
//! [result - (last-first),result) starting from last - 1 and proceeding to
|
||||
//! first. For each positive integer n <= (last - first),
|
||||
//! performs *(result - n) = ::boost::move(*(last - n)).
|
||||
//!
|
||||
//! <b>Requires</b>: result shall not be in the range [first,last).
|
||||
//!
|
||||
//! <b>Returns</b>: result - (last - first).
|
||||
//!
|
||||
//! <b>Complexity</b>: Exactly last - first assignments.
|
||||
template <typename I, // I models BidirectionalIterator
|
||||
typename O> // O models BidirectionalIterator
|
||||
O move_backward(I f, I l, O result)
|
||||
{
|
||||
while (f != l) {
|
||||
--l; --result;
|
||||
*result = ::boost::move(*l);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
using ::std::move_backward;
|
||||
|
||||
#endif //!defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uninitialized_move
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! <b>Effects</b>:
|
||||
//! \code
|
||||
//! for (; first != last; ++result, ++first)
|
||||
//! new (static_cast<void*>(&*result))
|
||||
//! typename iterator_traits<ForwardIterator>::value_type(boost::move(*first));
|
||||
//! \endcode
|
||||
//!
|
||||
//! <b>Returns</b>: result
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_move(I f, I l, F r
|
||||
/// @cond
|
||||
// ,typename ::boost::move_detail::enable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0
|
||||
/// @endcond
|
||||
)
|
||||
{
|
||||
typedef typename std::iterator_traits<I>::value_type input_value_type;
|
||||
|
||||
F back = r;
|
||||
BOOST_TRY{
|
||||
while (f != l) {
|
||||
void * const addr = static_cast<void*>(::boost::move_detail::addressof(*r));
|
||||
::new(addr) input_value_type(::boost::move(*f));
|
||||
++f; ++r;
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
for (; back != r; ++back){
|
||||
back->~input_value_type();
|
||||
}
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
return r;
|
||||
}
|
||||
|
||||
/// @cond
|
||||
/*
|
||||
template
|
||||
<typename I, // I models InputIterator
|
||||
typename F> // F models ForwardIterator
|
||||
F uninitialized_move(I f, I l, F r,
|
||||
typename ::boost::move_detail::disable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0)
|
||||
{
|
||||
return std::uninitialized_copy(f, l, r);
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uninitialized_copy_or_move
|
||||
|
@ -197,7 +197,7 @@
|
||||
namespace move_detail {
|
||||
|
||||
template <class Ret, class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< ::boost::move_detail::is_lvalue_reference<Ret>::value ||
|
||||
!::boost::has_move_emulation_enabled<T>::value
|
||||
, T&>::type
|
||||
@ -207,7 +207,7 @@
|
||||
}
|
||||
|
||||
template <class Ret, class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< !::boost::move_detail::is_lvalue_reference<Ret>::value &&
|
||||
::boost::has_move_emulation_enabled<T>::value
|
||||
, ::boost::rv<T>&>::type
|
||||
@ -217,7 +217,7 @@
|
||||
}
|
||||
|
||||
template <class Ret, class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< !::boost::move_detail::is_lvalue_reference<Ret>::value &&
|
||||
::boost::has_move_emulation_enabled<T>::value
|
||||
, ::boost::rv<T>&>::type
|
||||
@ -245,9 +245,9 @@
|
||||
#define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
|
||||
BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
|
||||
public:\
|
||||
operator ::boost::rv<TYPE>&() \
|
||||
BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
|
||||
{ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
|
||||
operator const ::boost::rv<TYPE>&() const \
|
||||
BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
|
||||
{ return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
|
||||
private:\
|
||||
//
|
||||
@ -263,18 +263,18 @@
|
||||
TYPE& operator=(TYPE &t)\
|
||||
{ this->operator=(const_cast<const TYPE &>(t)); return *this;}\
|
||||
public:\
|
||||
operator ::boost::rv<TYPE>&() \
|
||||
BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
|
||||
{ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
|
||||
operator const ::boost::rv<TYPE>&() const \
|
||||
BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
|
||||
{ return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
|
||||
private:\
|
||||
//
|
||||
|
||||
#define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
|
||||
public:\
|
||||
operator ::boost::rv<TYPE>&() \
|
||||
BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
|
||||
{ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
|
||||
operator const ::boost::rv<TYPE>&() const \
|
||||
BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
|
||||
{ return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
|
||||
private:\
|
||||
//
|
||||
@ -301,6 +301,7 @@
|
||||
BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
|
||||
public:\
|
||||
typedef int boost_move_emulation_t;\
|
||||
private:\
|
||||
//
|
||||
|
||||
//! This macro marks a type as copyable and movable.
|
||||
@ -450,7 +451,7 @@
|
||||
namespace move_detail {
|
||||
|
||||
template <class Ret, class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< ::boost::move_detail::is_lvalue_reference<Ret>::value
|
||||
, T&>::type
|
||||
move_return(T& x) BOOST_NOEXCEPT
|
||||
@ -459,7 +460,7 @@
|
||||
}
|
||||
|
||||
template <class Ret, class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< !::boost::move_detail::is_lvalue_reference<Ret>::value
|
||||
, Ret && >::type
|
||||
move_return(T&& t) BOOST_NOEXCEPT
|
||||
|
@ -16,4 +16,6 @@
|
||||
# pragma warning (disable : 4324) // structure was padded due to __declspec(align())
|
||||
# pragma warning (disable : 4675) // "function": resolved overload was found by argument-dependent lookup
|
||||
# pragma warning (disable : 4996) // "function": was declared deprecated (_CRT_SECURE_NO_DEPRECATE/_SCL_SECURE_NO_WARNINGS)
|
||||
# pragma warning (disable : 4714) // "function": marked as __forceinline not inlined
|
||||
# pragma warning (disable : 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
67
include/boost/move/detail/destruct_n.hpp
Normal file
67
include/boost/move/detail/destruct_n.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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! \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 destruct_n
|
||||
{
|
||||
public:
|
||||
explicit destruct_n(T *raw)
|
||||
: m_ptr(raw), m_size()
|
||||
{}
|
||||
|
||||
void incr()
|
||||
{
|
||||
++m_size;
|
||||
}
|
||||
|
||||
void incr(std::size_t n)
|
||||
{
|
||||
m_size += n;
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
m_size = 0u;
|
||||
m_ptr = 0;
|
||||
}
|
||||
|
||||
~destruct_n()
|
||||
{
|
||||
while(m_size--){
|
||||
m_ptr[m_size].~T();
|
||||
}
|
||||
}
|
||||
private:
|
||||
T *m_ptr;
|
||||
std::size_t m_size;
|
||||
};
|
||||
|
||||
}} //namespace boost { namespace movelib{
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_DESTRUCT_N_HPP
|
@ -23,6 +23,7 @@
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
|
||||
#include <boost/move/detail/std_ns_begin.hpp>
|
||||
BOOST_MOVE_STD_NS_BEG
|
||||
@ -46,6 +47,7 @@ struct iterator_traits
|
||||
typedef typename Iterator::pointer pointer;
|
||||
typedef typename Iterator::reference reference;
|
||||
typedef typename Iterator::iterator_category iterator_category;
|
||||
typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
@ -56,6 +58,7 @@ 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>
|
||||
@ -66,6 +69,7 @@ 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{
|
||||
|
@ -14,13 +14,11 @@
|
||||
#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
|
||||
#define BOOST_MOVE_DETAIL_META_UTILS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/detail/workaround.hpp> //forceinline
|
||||
#include <boost/move/detail/meta_utils_core.hpp>
|
||||
#include <cstddef> //for std::size_t
|
||||
|
||||
@ -245,8 +243,8 @@ template<class T>
|
||||
struct addr_impl_ref
|
||||
{
|
||||
T & v_;
|
||||
inline addr_impl_ref( T & v ): v_( v ) {}
|
||||
inline operator T& () const { return 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 &);
|
||||
@ -255,18 +253,18 @@ struct addr_impl_ref
|
||||
template<class T>
|
||||
struct addressof_impl
|
||||
{
|
||||
static inline T * f( T & v, long )
|
||||
BOOST_MOVE_FORCEINLINE static T * f( T & v, long )
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
|
||||
}
|
||||
|
||||
static inline T * f( T * v, int )
|
||||
BOOST_MOVE_FORCEINLINE static T * f( T * v, int )
|
||||
{ return v; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline T * addressof( T & v )
|
||||
BOOST_MOVE_FORCEINLINE T * addressof( T & v )
|
||||
{
|
||||
return ::boost::move_detail::addressof_impl<T>::f
|
||||
( ::boost::move_detail::addr_impl_ref<T>( v ), 0 );
|
||||
@ -314,6 +312,17 @@ class is_convertible
|
||||
|
||||
#endif
|
||||
|
||||
template <class T, class U, bool IsSame = is_same<T, U>::value>
|
||||
struct is_same_or_convertible
|
||||
: is_convertible<T, U>
|
||||
{};
|
||||
|
||||
template <class T, class U>
|
||||
struct is_same_or_convertible<T, U, true>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<
|
||||
bool C
|
||||
, typename F1
|
||||
@ -347,6 +356,16 @@ struct disable_if_convertible
|
||||
: disable_if< is_convertible<T, U>, R>
|
||||
{};
|
||||
|
||||
template<class T, class U, class R = void>
|
||||
struct enable_if_same_or_convertible
|
||||
: enable_if< is_same_or_convertible<T, U>, R>
|
||||
{};
|
||||
|
||||
template<class T, class U, class R = void>
|
||||
struct disable_if_same_or_convertible
|
||||
: disable_if< is_same_or_convertible<T, U>, R>
|
||||
{};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// and_
|
||||
@ -561,4 +580,6 @@ template< class T > struct remove_rvalue_reference { typedef T type; };
|
||||
} //namespace move_detail {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/move/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
|
||||
|
@ -1,6 +1,6 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2010-2012.
|
||||
// (C) Copyright Ion Gaztanaga 2010-2016.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -20,8 +20,9 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/move/core.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/detail/meta_utils.hpp>
|
||||
#include <boost/move/detail/type_traits.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
@ -43,6 +44,30 @@
|
||||
////////////////////////////////////////
|
||||
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class TYPE>
|
||||
struct boost_move_conversion_aware_catch_1
|
||||
: public ::boost::move_detail::enable_if_and
|
||||
< RETURN_VALUE
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
|
||||
, ::boost::move_detail::is_class<TYPE>
|
||||
, ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>
|
||||
>
|
||||
{};
|
||||
|
||||
template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class TYPE>
|
||||
struct boost_move_conversion_aware_catch_2
|
||||
: public ::boost::move_detail::disable_if_or
|
||||
< RETURN_VALUE
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
|
||||
, ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
|
||||
, ::boost::move_detail::and_
|
||||
< ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
|
||||
, ::boost::move_detail::is_class<BOOST_MOVE_TEMPL_PARAM>
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
#define BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
|
||||
RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
|
||||
{ return FWD_FUNCTION(static_cast<const TYPE&>(x)); }\
|
||||
@ -59,26 +84,14 @@
|
||||
\
|
||||
template<class BOOST_MOVE_TEMPL_PARAM>\
|
||||
RETURN_VALUE PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u,\
|
||||
typename ::boost::move_detail::enable_if_and\
|
||||
< ::boost::move_detail::nat \
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
|
||||
, ::boost::move_detail::is_class<TYPE>\
|
||||
, ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>\
|
||||
>::type* = 0)\
|
||||
typename boost_move_conversion_aware_catch_1< ::boost::move_detail::nat, BOOST_MOVE_TEMPL_PARAM, TYPE>::type* = 0)\
|
||||
{ return FWD_FUNCTION(u); }\
|
||||
\
|
||||
template<class BOOST_MOVE_TEMPL_PARAM>\
|
||||
RETURN_VALUE PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u,\
|
||||
typename ::boost::move_detail::disable_if_or\
|
||||
< ::boost::move_detail::nat \
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM> \
|
||||
, ::boost::move_detail::and_ \
|
||||
< ::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM> \
|
||||
, ::boost::move_detail::is_class<BOOST_MOVE_TEMPL_PARAM> \
|
||||
> \
|
||||
>::type* = 0)\
|
||||
typename boost_move_conversion_aware_catch_2< ::boost::move_detail::nat, BOOST_MOVE_TEMPL_PARAM, TYPE>::type* = 0)\
|
||||
{\
|
||||
TYPE t(u);\
|
||||
TYPE t((u));\
|
||||
return FWD_FUNCTION(::boost::move(t));\
|
||||
}\
|
||||
//
|
||||
@ -87,27 +100,15 @@
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
|
||||
\
|
||||
template<class BOOST_MOVE_TEMPL_PARAM>\
|
||||
typename ::boost::move_detail::enable_if_and\
|
||||
< RETURN_VALUE \
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
|
||||
, ::boost::move_detail::is_class<TYPE>\
|
||||
, ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>\
|
||||
>::type\
|
||||
typename boost_move_conversion_aware_catch_1<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, TYPE>::type\
|
||||
PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
|
||||
{ return FWD_FUNCTION(u); }\
|
||||
\
|
||||
template<class BOOST_MOVE_TEMPL_PARAM>\
|
||||
typename ::boost::move_detail::disable_if_or\
|
||||
< RETURN_VALUE \
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM> \
|
||||
, ::boost::move_detail::and_ \
|
||||
< ::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM> \
|
||||
, ::boost::move_detail::is_class<BOOST_MOVE_TEMPL_PARAM> \
|
||||
> \
|
||||
>::type\
|
||||
typename boost_move_conversion_aware_catch_2<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, TYPE>::type\
|
||||
PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
|
||||
{\
|
||||
TYPE t(u);\
|
||||
TYPE t((u));\
|
||||
return FWD_FUNCTION(::boost::move(t));\
|
||||
}\
|
||||
//
|
||||
@ -127,7 +128,7 @@
|
||||
, RETURN_VALUE >::type\
|
||||
PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
|
||||
{\
|
||||
TYPE t(u);\
|
||||
TYPE t((u));\
|
||||
return FWD_FUNCTION(::boost::move(t));\
|
||||
}\
|
||||
//
|
||||
@ -151,6 +152,27 @@
|
||||
////////////////////////////////////////
|
||||
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class UNLESS_CONVERTIBLE_TO, class TYPE>
|
||||
struct boost_move_conversion_aware_catch_1arg_1
|
||||
: public ::boost::move_detail::enable_if_and
|
||||
< RETURN_VALUE
|
||||
, ::boost::move_detail::not_< ::boost::move_detail::is_same_or_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> >
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
|
||||
, ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>
|
||||
>
|
||||
{};
|
||||
|
||||
template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class UNLESS_CONVERTIBLE_TO, class TYPE>
|
||||
struct boost_move_conversion_aware_catch_1arg_2
|
||||
: public ::boost::move_detail::disable_if_or
|
||||
< RETURN_VALUE
|
||||
, ::boost::move_detail::is_same_or_convertible< BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>
|
||||
, ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
|
||||
>
|
||||
{};
|
||||
|
||||
#define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
|
||||
RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
|
||||
{ return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
|
||||
@ -167,23 +189,14 @@
|
||||
\
|
||||
template<class BOOST_MOVE_TEMPL_PARAM>\
|
||||
RETURN_VALUE PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u,\
|
||||
typename ::boost::move_detail::enable_if_and\
|
||||
< ::boost::move_detail::nat \
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
|
||||
, ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>\
|
||||
>::type* = 0)\
|
||||
typename boost_move_conversion_aware_catch_1arg_1<void, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type* = 0)\
|
||||
{ return FWD_FUNCTION(arg1, u); }\
|
||||
\
|
||||
template<class BOOST_MOVE_TEMPL_PARAM>\
|
||||
RETURN_VALUE PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u,\
|
||||
typename ::boost::move_detail::disable_if_or\
|
||||
< void \
|
||||
, ::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>\
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
|
||||
, ::boost::move_detail::is_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>\
|
||||
>::type* = 0)\
|
||||
typename boost_move_conversion_aware_catch_1arg_2<void, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type* = 0)\
|
||||
{\
|
||||
TYPE t(u);\
|
||||
TYPE t((u));\
|
||||
return FWD_FUNCTION(arg1, ::boost::move(t));\
|
||||
}\
|
||||
//
|
||||
@ -192,24 +205,15 @@
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
|
||||
\
|
||||
template<class BOOST_MOVE_TEMPL_PARAM>\
|
||||
typename ::boost::move_detail::enable_if_and\
|
||||
< RETURN_VALUE \
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
|
||||
, ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>\
|
||||
>::type\
|
||||
typename boost_move_conversion_aware_catch_1arg_1<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type\
|
||||
PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
|
||||
{ return FWD_FUNCTION(arg1, u); }\
|
||||
\
|
||||
template<class BOOST_MOVE_TEMPL_PARAM>\
|
||||
typename ::boost::move_detail::disable_if_or\
|
||||
< RETURN_VALUE \
|
||||
, ::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>\
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>\
|
||||
, ::boost::move_detail::is_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>\
|
||||
>::type\
|
||||
typename boost_move_conversion_aware_catch_1arg_2<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type\
|
||||
PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
|
||||
{\
|
||||
TYPE t(u);\
|
||||
TYPE t((u));\
|
||||
return FWD_FUNCTION(arg1, ::boost::move(t));\
|
||||
}\
|
||||
//
|
||||
@ -228,11 +232,11 @@
|
||||
typename ::boost::move_detail::disable_if_or\
|
||||
< RETURN_VALUE \
|
||||
, ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM> \
|
||||
, ::boost::move_detail::is_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> \
|
||||
, ::boost::move_detail::is_same_or_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> \
|
||||
>::type\
|
||||
PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
|
||||
{\
|
||||
TYPE t(u);\
|
||||
TYPE t((u));\
|
||||
return FWD_FUNCTION(arg1, ::boost::move(t));\
|
||||
}\
|
||||
//
|
||||
|
30
include/boost/move/detail/placement_new.hpp
Normal file
30
include/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
|
@ -52,4 +52,17 @@
|
||||
#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
|
||||
#define BOOST_MOVE_FORCEINLINE inline
|
||||
#else
|
||||
#define BOOST_MOVE_FORCEINLINE BOOST_FORCEINLINE
|
||||
#endif
|
||||
|
||||
#endif //#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
|
||||
|
@ -23,6 +23,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/detail/workaround.hpp> //forceinline
|
||||
#include <boost/move/detail/iterator_traits.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
@ -57,22 +58,20 @@ class move_iterator
|
||||
typedef typename boost::movelib::iterator_traits<iterator_type>::difference_type difference_type;
|
||||
typedef typename boost::movelib::iterator_traits<iterator_type>::iterator_category iterator_category;
|
||||
|
||||
move_iterator()
|
||||
BOOST_MOVE_FORCEINLINE move_iterator()
|
||||
: m_it()
|
||||
{}
|
||||
|
||||
explicit move_iterator(It i)
|
||||
BOOST_MOVE_FORCEINLINE explicit move_iterator(const It &i)
|
||||
: m_it(i)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
move_iterator(const move_iterator<U>& u)
|
||||
: m_it(u.base())
|
||||
BOOST_MOVE_FORCEINLINE move_iterator(const move_iterator<U>& u)
|
||||
: m_it(u.m_it)
|
||||
{}
|
||||
|
||||
iterator_type base() const
|
||||
{ return m_it; }
|
||||
|
||||
reference operator*() const
|
||||
BOOST_MOVE_FORCEINLINE reference operator*() const
|
||||
{
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
|
||||
return *m_it;
|
||||
@ -81,34 +80,34 @@ class move_iterator
|
||||
#endif
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
BOOST_MOVE_FORCEINLINE pointer operator->() const
|
||||
{ return m_it; }
|
||||
|
||||
move_iterator& operator++()
|
||||
BOOST_MOVE_FORCEINLINE move_iterator& operator++()
|
||||
{ ++m_it; return *this; }
|
||||
|
||||
move_iterator<iterator_type> operator++(int)
|
||||
BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator++(int)
|
||||
{ move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; }
|
||||
|
||||
move_iterator& operator--()
|
||||
BOOST_MOVE_FORCEINLINE move_iterator& operator--()
|
||||
{ --m_it; return *this; }
|
||||
|
||||
move_iterator<iterator_type> operator--(int)
|
||||
BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator--(int)
|
||||
{ move_iterator<iterator_type> tmp(*this); --(*this); return tmp; }
|
||||
|
||||
move_iterator<iterator_type> operator+ (difference_type n) const
|
||||
{ return move_iterator<iterator_type>(m_it + n); }
|
||||
|
||||
move_iterator& operator+=(difference_type n)
|
||||
BOOST_MOVE_FORCEINLINE move_iterator& operator+=(difference_type n)
|
||||
{ m_it += n; return *this; }
|
||||
|
||||
move_iterator<iterator_type> operator- (difference_type n) const
|
||||
BOOST_MOVE_FORCEINLINE move_iterator<iterator_type> operator- (difference_type n) const
|
||||
{ return move_iterator<iterator_type>(m_it - n); }
|
||||
|
||||
move_iterator& operator-=(difference_type n)
|
||||
BOOST_MOVE_FORCEINLINE move_iterator& operator-=(difference_type n)
|
||||
{ m_it -= n; return *this; }
|
||||
|
||||
reference operator[](difference_type n) const
|
||||
BOOST_MOVE_FORCEINLINE reference operator[](difference_type n) const
|
||||
{
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
|
||||
return m_it[n];
|
||||
@ -117,29 +116,29 @@ class move_iterator
|
||||
#endif
|
||||
}
|
||||
|
||||
friend bool operator==(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() == y.base(); }
|
||||
BOOST_MOVE_FORCEINLINE friend bool operator==(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it == y.m_it; }
|
||||
|
||||
friend bool operator!=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() != y.base(); }
|
||||
BOOST_MOVE_FORCEINLINE friend bool operator!=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it != y.m_it; }
|
||||
|
||||
friend bool operator< (const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() < y.base(); }
|
||||
BOOST_MOVE_FORCEINLINE friend bool operator< (const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it < y.m_it; }
|
||||
|
||||
friend bool operator<=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() <= y.base(); }
|
||||
BOOST_MOVE_FORCEINLINE friend bool operator<=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it <= y.m_it; }
|
||||
|
||||
friend bool operator> (const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() > y.base(); }
|
||||
BOOST_MOVE_FORCEINLINE friend bool operator> (const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it > y.m_it; }
|
||||
|
||||
friend bool operator>=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() >= y.base(); }
|
||||
BOOST_MOVE_FORCEINLINE friend bool operator>=(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it >= y.m_it; }
|
||||
|
||||
friend difference_type operator-(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.base() - y.base(); }
|
||||
BOOST_MOVE_FORCEINLINE friend difference_type operator-(const move_iterator& x, const move_iterator& y)
|
||||
{ return x.m_it - y.m_it; }
|
||||
|
||||
friend move_iterator operator+(difference_type n, const move_iterator& x)
|
||||
{ return move_iterator(x.base() + n); }
|
||||
BOOST_MOVE_FORCEINLINE friend move_iterator operator+(difference_type n, const move_iterator& x)
|
||||
{ return move_iterator(x.m_it + n); }
|
||||
|
||||
private:
|
||||
It m_it;
|
||||
|
@ -20,7 +20,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/detail/workaround.hpp>
|
||||
#include <boost/move/detail/workaround.hpp> //forceinline
|
||||
#include <boost/move/detail/unique_ptr_meta_utils.hpp>
|
||||
#include <boost/move/default_delete.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
@ -93,25 +93,25 @@ struct unique_ptr_data
|
||||
typedef typename deleter_types<D>::del_ref del_ref;
|
||||
typedef typename deleter_types<D>::del_cref del_cref;
|
||||
|
||||
unique_ptr_data() BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
|
||||
: m_p(), d()
|
||||
{}
|
||||
|
||||
explicit unique_ptr_data(P p) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
|
||||
: m_p(p), d()
|
||||
{}
|
||||
|
||||
unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
|
||||
: m_p(p), d(d1)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
unique_ptr_data(P p, BOOST_FWD_REF(U) d1) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d1) BOOST_NOEXCEPT
|
||||
: m_p(p), d(::boost::forward<U>(d1))
|
||||
{}
|
||||
|
||||
del_ref deleter() { return d; }
|
||||
del_cref deleter() const{ return d; }
|
||||
BOOST_MOVE_FORCEINLINE del_ref deleter() { return d; }
|
||||
BOOST_MOVE_FORCEINLINE del_cref deleter() const{ return d; }
|
||||
|
||||
P m_p;
|
||||
D d;
|
||||
@ -129,25 +129,25 @@ struct unique_ptr_data<P, D, false>
|
||||
typedef typename deleter_types<D>::del_ref del_ref;
|
||||
typedef typename deleter_types<D>::del_cref del_cref;
|
||||
|
||||
unique_ptr_data() BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr_data() BOOST_NOEXCEPT
|
||||
: D(), m_p()
|
||||
{}
|
||||
|
||||
explicit unique_ptr_data(P p) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE explicit unique_ptr_data(P p) BOOST_NOEXCEPT
|
||||
: D(), m_p(p)
|
||||
{}
|
||||
|
||||
unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT
|
||||
: D(d1), m_p(p)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
|
||||
: D(::boost::forward<U>(d)), m_p(p)
|
||||
{}
|
||||
|
||||
del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); }
|
||||
del_cref deleter() const BOOST_NOEXCEPT { return static_cast<del_cref>(*this); }
|
||||
BOOST_MOVE_FORCEINLINE del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); }
|
||||
BOOST_MOVE_FORCEINLINE del_cref deleter() const BOOST_NOEXCEPT { return static_cast<del_cref>(*this); }
|
||||
|
||||
P m_p;
|
||||
|
||||
@ -389,7 +389,7 @@ class unique_ptr
|
||||
//!
|
||||
//! <b>Remarks</b>: If this constructor is instantiated with a pointer type or reference type
|
||||
//! for the template argument D, the program is ill-formed.
|
||||
BOOST_CONSTEXPR unique_ptr() BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE BOOST_CONSTEXPR unique_ptr() BOOST_NOEXCEPT
|
||||
: m_data()
|
||||
{
|
||||
//If this constructor is instantiated with a pointer type or reference type
|
||||
@ -400,7 +400,7 @@ class unique_ptr
|
||||
|
||||
//! <b>Effects</b>: Same as <tt>unique_ptr()</tt> (default constructor).
|
||||
//!
|
||||
BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
|
||||
: m_data()
|
||||
{
|
||||
//If this constructor is instantiated with a pointer type or reference type
|
||||
@ -423,7 +423,7 @@ class unique_ptr
|
||||
//! - If T is not an array type and Pointer is implicitly convertible to pointer.
|
||||
//! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
|
||||
template<class Pointer>
|
||||
explicit unique_ptr(Pointer p
|
||||
BOOST_MOVE_FORCEINLINE explicit unique_ptr(Pointer p
|
||||
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
|
||||
) BOOST_NOEXCEPT
|
||||
: m_data(p)
|
||||
@ -461,7 +461,7 @@ class unique_ptr
|
||||
//! - If T is not an array type and Pointer is implicitly convertible to pointer.
|
||||
//! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
|
||||
template<class Pointer>
|
||||
unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1
|
||||
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
|
||||
) BOOST_NOEXCEPT
|
||||
: m_data(p, d1)
|
||||
@ -474,7 +474,7 @@ class unique_ptr
|
||||
|
||||
//! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type1 d1)</tt>
|
||||
//! and additionally <tt>get() == nullptr</tt>
|
||||
unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT
|
||||
: m_data(pointer(), d1)
|
||||
{}
|
||||
|
||||
@ -499,7 +499,7 @@ class unique_ptr
|
||||
//! - If T is not an array type and Pointer is implicitly convertible to pointer.
|
||||
//! - If T is an array type and Pointer is a more CV qualified pointer to element_type.
|
||||
template<class Pointer>
|
||||
unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2
|
||||
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
|
||||
) BOOST_NOEXCEPT
|
||||
: m_data(p, ::boost::move(d2))
|
||||
@ -512,7 +512,7 @@ class unique_ptr
|
||||
|
||||
//! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type2 d2)</tt>
|
||||
//! and additionally <tt>get() == nullptr</tt>
|
||||
unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT
|
||||
: m_data(pointer(), ::boost::move(d2))
|
||||
{}
|
||||
|
||||
@ -526,7 +526,7 @@ class unique_ptr
|
||||
//! <b>Postconditions</b>: <tt>get()</tt> yields the value u.get() yielded before the construction. <tt>get_deleter()</tt>
|
||||
//! returns a reference to the stored deleter that was constructed from u.get_deleter(). If D is a
|
||||
//! reference type then <tt>get_deleter()</tt> and <tt>u.get_deleter()</tt> both reference the same lvalue deleter.
|
||||
unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT
|
||||
: m_data(u.release(), ::boost::move_if_not_lvalue_reference<D>(u.get_deleter()))
|
||||
{}
|
||||
|
||||
@ -546,7 +546,7 @@ class unique_ptr
|
||||
//! <b>Postconditions</b>: <tt>get()</tt> yields the value <tt>u.get()</tt> yielded before the construction. <tt>get_deleter()</tt>
|
||||
//! returns a reference to the stored deleter that was constructed from <tt>u.get_deleter()</tt>.
|
||||
template <class U, class E>
|
||||
unique_ptr( BOOST_RV_REF_BEG_IF_CXX11 unique_ptr<U, E> BOOST_RV_REF_END_IF_CXX11 u
|
||||
BOOST_MOVE_FORCEINLINE unique_ptr( BOOST_RV_REF_BEG_IF_CXX11 unique_ptr<U, E> BOOST_RV_REF_END_IF_CXX11 u
|
||||
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr<T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E>::type* =0)
|
||||
) BOOST_NOEXCEPT
|
||||
: m_data(u.release(), ::boost::move_if_not_lvalue_reference<E>(u.get_deleter()))
|
||||
@ -629,7 +629,7 @@ class unique_ptr
|
||||
//! <b>Returns</b>: <tt>get()[i]</tt>.
|
||||
//!
|
||||
//! <b>Remarks</b: If T is not an array type, the program is ill-formed.
|
||||
BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type)
|
||||
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 );
|
||||
@ -644,7 +644,7 @@ class unique_ptr
|
||||
//! <b>Note</b>: use typically requires that T be a complete type.
|
||||
//!
|
||||
//! <b>Remarks</b: If T is an array type, the program is ill-formed.
|
||||
pointer operator->() const BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value));
|
||||
BOOST_ASSERT(m_data.m_p);
|
||||
@ -653,27 +653,27 @@ class unique_ptr
|
||||
|
||||
//! <b>Returns</b>: The stored pointer.
|
||||
//!
|
||||
pointer get() const BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE pointer get() const BOOST_NOEXCEPT
|
||||
{ return m_data.m_p; }
|
||||
|
||||
//! <b>Returns</b>: A reference to the stored deleter.
|
||||
//!
|
||||
BOOST_MOVE_DOC1ST(D&, typename bmupmu::add_lvalue_reference<D>::type)
|
||||
BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(D&, typename bmupmu::add_lvalue_reference<D>::type)
|
||||
get_deleter() BOOST_NOEXCEPT
|
||||
{ return m_data.deleter(); }
|
||||
|
||||
//! <b>Returns</b>: A reference to the stored deleter.
|
||||
//!
|
||||
BOOST_MOVE_DOC1ST(const D&, typename bmupmu::add_const_lvalue_reference<D>::type)
|
||||
BOOST_MOVE_FORCEINLINE BOOST_MOVE_DOC1ST(const D&, typename bmupmu::add_const_lvalue_reference<D>::type)
|
||||
get_deleter() const BOOST_NOEXCEPT
|
||||
{ return m_data.deleter(); }
|
||||
|
||||
#ifdef BOOST_MOVE_DOXYGEN_INVOKED
|
||||
//! <b>Returns</b>: Returns: get() != nullptr.
|
||||
//!
|
||||
explicit operator bool
|
||||
BOOST_MOVE_FORCEINLINE explicit operator bool
|
||||
#else
|
||||
operator bmupd::explicit_bool_arg
|
||||
BOOST_MOVE_FORCEINLINE operator bmupd::explicit_bool_arg
|
||||
#endif
|
||||
()const BOOST_NOEXCEPT
|
||||
{
|
||||
@ -685,7 +685,7 @@ class unique_ptr
|
||||
//! <b>Postcondition</b>: <tt>get() == nullptr</tt>.
|
||||
//!
|
||||
//! <b>Returns</b>: The value <tt>get()</tt> had at the start of the call to release.
|
||||
pointer release() BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE pointer release() BOOST_NOEXCEPT
|
||||
{
|
||||
const pointer tmp = m_data.m_p;
|
||||
m_data.m_p = pointer();
|
||||
@ -748,19 +748,19 @@ class unique_ptr
|
||||
//! <b>Effects</b>: Calls <tt>x.swap(y)</tt>.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline void swap(unique_ptr<T, D> &x, unique_ptr<T, D> &y) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE void swap(unique_ptr<T, D> &x, unique_ptr<T, D> &y) BOOST_NOEXCEPT
|
||||
{ x.swap(y); }
|
||||
|
||||
//! <b>Returns</b>: <tt>x.get() == y.get()</tt>.
|
||||
//!
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
BOOST_MOVE_FORCEINLINE bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{ return x.get() == y.get(); }
|
||||
|
||||
//! <b>Returns</b>: <tt>x.get() != y.get()</tt>.
|
||||
//!
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
BOOST_MOVE_FORCEINLINE bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{ return x.get() != y.get(); }
|
||||
|
||||
//! <b>Returns</b>: x.get() < y.get().
|
||||
@ -768,99 +768,99 @@ inline bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
//! <b>Remarks</b>: This comparison shall induce a
|
||||
//! strict weak ordering betwen pointers.
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
BOOST_MOVE_FORCEINLINE bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{ return x.get() < y.get(); }
|
||||
|
||||
//! <b>Returns</b>: !(y < x).
|
||||
//!
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
BOOST_MOVE_FORCEINLINE bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{ return !(y < x); }
|
||||
|
||||
//! <b>Returns</b>: y < x.
|
||||
//!
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
BOOST_MOVE_FORCEINLINE bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{ return y < x; }
|
||||
|
||||
//! <b>Returns</b>:!(x < y).
|
||||
//!
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
BOOST_MOVE_FORCEINLINE bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{ return !(x < y); }
|
||||
|
||||
//! <b>Returns</b>:!x.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator==(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE bool operator==(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
|
||||
{ return !x; }
|
||||
|
||||
//! <b>Returns</b>:!x.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator==(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE bool operator==(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
|
||||
{ return !x; }
|
||||
|
||||
//! <b>Returns</b>: (bool)x.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator!=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE bool operator!=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT
|
||||
{ return !!x; }
|
||||
|
||||
//! <b>Returns</b>: (bool)x.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator!=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE bool operator!=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
|
||||
{ return !!x; }
|
||||
|
||||
//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
|
||||
//!
|
||||
//! <b>Returns</b>: Returns <tt>x.get() < pointer()</tt>.
|
||||
template <class T, class D>
|
||||
inline bool operator<(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
|
||||
BOOST_MOVE_FORCEINLINE bool operator<(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
|
||||
{ return x.get() < typename unique_ptr<T, D>::pointer(); }
|
||||
|
||||
//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
|
||||
//!
|
||||
//! <b>Returns</b>: Returns <tt>pointer() < x.get()</tt>.
|
||||
template <class T, class D>
|
||||
inline bool operator<(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
|
||||
BOOST_MOVE_FORCEINLINE bool operator<(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
|
||||
{ return typename unique_ptr<T, D>::pointer() < x.get(); }
|
||||
|
||||
//! <b>Returns</b>: <tt>nullptr < x</tt>.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator>(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
|
||||
BOOST_MOVE_FORCEINLINE bool operator>(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
|
||||
{ return x.get() > typename unique_ptr<T, D>::pointer(); }
|
||||
|
||||
//! <b>Returns</b>: <tt>x < nullptr</tt>.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator>(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
|
||||
BOOST_MOVE_FORCEINLINE bool operator>(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
|
||||
{ return typename unique_ptr<T, D>::pointer() > x.get(); }
|
||||
|
||||
//! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator<=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
|
||||
BOOST_MOVE_FORCEINLINE bool operator<=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
|
||||
{ return !(bmupd::nullptr_type() < x); }
|
||||
|
||||
//! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator<=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
|
||||
BOOST_MOVE_FORCEINLINE bool operator<=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
|
||||
{ return !(x < bmupd::nullptr_type()); }
|
||||
|
||||
//! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator>=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
|
||||
BOOST_MOVE_FORCEINLINE bool operator>=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type))
|
||||
{ return !(x < bmupd::nullptr_type()); }
|
||||
|
||||
//! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
|
||||
//!
|
||||
template <class T, class D>
|
||||
inline bool operator>=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
|
||||
BOOST_MOVE_FORCEINLINE bool operator>=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x)
|
||||
{ return !(bmupd::nullptr_type() < x); }
|
||||
|
||||
} //namespace movelib {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/detail/workaround.hpp> //forceinline
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/move/traits.hpp>
|
||||
|
||||
@ -39,7 +40,7 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< enable_move_utility_emulation<T>::value && !has_move_emulation_enabled<T>::value
|
||||
, typename ::boost::move_detail::add_const<T>::type &
|
||||
>::type
|
||||
@ -49,7 +50,7 @@
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
|
||||
&& ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, rv<T>&>::type
|
||||
move_if_noexcept(T& x) BOOST_NOEXCEPT
|
||||
@ -58,7 +59,7 @@
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
|
||||
&& ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
|
||||
, rv<T>&
|
||||
@ -69,7 +70,7 @@
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
|
||||
&& !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
|
||||
, typename ::boost::move_detail::add_const<T>::type &
|
||||
@ -80,7 +81,7 @@
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
|
||||
&& !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
|
||||
, typename ::boost::move_detail::add_const<T>::type &
|
||||
@ -125,13 +126,13 @@
|
||||
#else //BOOST_MOVE_DOXYGEN_INVOKED
|
||||
|
||||
template <class T>
|
||||
typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, T&&>::type
|
||||
move_if_noexcept(T& x) BOOST_NOEXCEPT
|
||||
{ return ::boost::move(x); }
|
||||
|
||||
template <class T>
|
||||
typename ::boost::move_detail::enable_if_c
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
|
||||
< !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, const T&>::type
|
||||
move_if_noexcept(T& x) BOOST_NOEXCEPT
|
||||
{ return x; }
|
||||
|
@ -26,6 +26,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/move/detail/config_begin.hpp>
|
||||
#include <boost/move/detail/workaround.hpp> //forceinline
|
||||
#include <boost/move/core.hpp>
|
||||
#include <boost/move/detail/meta_utils.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
@ -47,7 +48,7 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_and
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
|
||||
< T &
|
||||
, enable_move_utility_emulation<T>
|
||||
, has_move_emulation_disabled<T>
|
||||
@ -58,7 +59,7 @@
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_and
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
|
||||
< rv<T>&
|
||||
, enable_move_utility_emulation<T>
|
||||
, has_move_emulation_enabled<T>
|
||||
@ -69,7 +70,7 @@
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_and
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
|
||||
< rv<T>&
|
||||
, enable_move_utility_emulation<T>
|
||||
, has_move_emulation_enabled<T>
|
||||
@ -86,7 +87,7 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_and
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
|
||||
< T &
|
||||
, enable_move_utility_emulation<T>
|
||||
, ::boost::move_detail::is_rv<T>
|
||||
@ -97,7 +98,7 @@
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_and
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
|
||||
< const T &
|
||||
, enable_move_utility_emulation<T>
|
||||
, ::boost::move_detail::is_not_rv<T>
|
||||
@ -114,7 +115,7 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_and
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
|
||||
< T &
|
||||
, enable_move_utility_emulation<T>
|
||||
, ::boost::move_detail::is_rv<T>
|
||||
@ -125,7 +126,7 @@
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_and
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
|
||||
< typename ::boost::move_detail::add_lvalue_reference<T>::type
|
||||
, enable_move_utility_emulation<T>
|
||||
, ::boost::move_detail::is_not_rv<T>
|
||||
@ -140,7 +141,7 @@
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::enable_if_and
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
|
||||
< rv<T>&
|
||||
, enable_move_utility_emulation<T>
|
||||
, ::boost::move_detail::is_not_rv<T>
|
||||
@ -202,13 +203,13 @@
|
||||
|
||||
//Old move approach, lvalues could bind to rvalue references
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
|
||||
{ return t; }
|
||||
|
||||
#else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
|
||||
|
||||
template <class T>
|
||||
inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
|
||||
{ return static_cast<typename ::boost::move_detail::remove_reference<T>::type &&>(t); }
|
||||
|
||||
#endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
|
||||
@ -238,17 +239,17 @@
|
||||
//Old move approach, lvalues could bind to rvalue references
|
||||
|
||||
template <class T>
|
||||
inline T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
|
||||
{ return t; }
|
||||
|
||||
#else //Old move
|
||||
|
||||
template <class T>
|
||||
inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
|
||||
{ return static_cast<T&&>(t); }
|
||||
|
||||
template <class T>
|
||||
inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
|
||||
BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
|
||||
{
|
||||
//"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
|
||||
BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
|
||||
@ -273,17 +274,17 @@
|
||||
//Old move approach, lvalues could bind to rvalue references
|
||||
|
||||
template <class T>
|
||||
inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
|
||||
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>
|
||||
inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
|
||||
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>
|
||||
inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
|
||||
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);
|
||||
|
@ -111,6 +111,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "type_traits", "type_traits.
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_sort", "bench_sort.vcproj", "{CD2617A8-6217-9EB7-24CE-6C9AA035376A}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_merge", "bench_merge.vcproj", "{CD2617A8-6217-9EB7-24CE-6C9AA035376A}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
@ -231,25 +239,45 @@ Global
|
||||
{D7C28A23-8621-FE05-BF87-3C7B6176BD02}.Debug.Build.0 = Debug|Win32
|
||||
{D7C28A23-8621-FE05-BF87-3C7B6176BD02}.Release.ActiveCfg = Release|Win32
|
||||
{D7C28A23-8621-FE05-BF87-3C7B6176BD02}.Release.Build.0 = Release|Win32
|
||||
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Debug.ActiveCfg = Debug|Win32
|
||||
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Debug.Build.0 = Debug|Win32
|
||||
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.ActiveCfg = Release|Win32
|
||||
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.Build.0 = Release|Win32
|
||||
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Debug.ActiveCfg = Debug|Win32
|
||||
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Debug.Build.0 = Debug|Win32
|
||||
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.ActiveCfg = Release|Win32
|
||||
{CD2617A8-6217-9EB7-24CE-6C9AA035376A}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionItems) = postSolution
|
||||
..\..\..\..\boost\move\algo\adaptive_merge.hpp = ..\..\..\..\boost\move\algo\adaptive_merge.hpp
|
||||
..\..\..\..\boost\move\algo\adaptive_sort.hpp = ..\..\..\..\boost\move\algo\adaptive_sort.hpp
|
||||
..\..\..\..\boost\move\algo\detail\adaptive_sort_merge.hpp = ..\..\..\..\boost\move\algo\detail\adaptive_sort_merge.hpp
|
||||
..\..\..\..\boost\move\adl_move_swap.hpp = ..\..\..\..\boost\move\adl_move_swap.hpp
|
||||
..\..\..\..\boost\move\algorithm.hpp = ..\..\..\..\boost\move\algorithm.hpp
|
||||
..\..\..\..\boost\move\algo\basic_op.hpp = ..\..\..\..\boost\move\algo\basic_op.hpp
|
||||
..\..\..\..\boost\move\algo\bufferless_merge_sort.hpp = ..\..\..\..\boost\move\algo\bufferless_merge_sort.hpp
|
||||
..\..\..\..\boost\move\detail\config_begin.hpp = ..\..\..\..\boost\move\detail\config_begin.hpp
|
||||
..\..\..\..\boost\move\detail\config_end.hpp = ..\..\..\..\boost\move\detail\config_end.hpp
|
||||
..\..\..\..\boost\move\core.hpp = ..\..\..\..\boost\move\core.hpp
|
||||
..\..\..\..\boost\move\default_delete.hpp = ..\..\..\..\boost\move\default_delete.hpp
|
||||
..\..\..\..\boost\move\detail\destruct_n.hpp = ..\..\..\..\boost\move\detail\destruct_n.hpp
|
||||
..\..\..\..\boost\move\detail\fwd_macros.hpp = ..\..\..\..\boost\move\detail\fwd_macros.hpp
|
||||
..\..\..\..\boost\move\algo\insertion_sort.hpp = ..\..\..\..\boost\move\algo\insertion_sort.hpp
|
||||
..\..\..\..\boost\move\iterator.hpp = ..\..\..\..\boost\move\iterator.hpp
|
||||
..\..\..\..\boost\move\detail\iterator_traits.hpp = ..\..\..\..\boost\move\detail\iterator_traits.hpp
|
||||
..\..\doc\Jamfile.v2 = ..\..\doc\Jamfile.v2
|
||||
..\..\..\..\boost\move\make_unique.hpp = ..\..\..\..\boost\move\make_unique.hpp
|
||||
..\..\..\..\boost\move\algo\merge.hpp = ..\..\..\..\boost\move\algo\merge.hpp
|
||||
..\..\..\..\boost\move\algo\merge_sort.hpp = ..\..\..\..\boost\move\algo\merge_sort.hpp
|
||||
..\..\..\..\boost\move\detail\meta_utils.hpp = ..\..\..\..\boost\move\detail\meta_utils.hpp
|
||||
..\..\..\..\boost\move\detail\meta_utils_core.hpp = ..\..\..\..\boost\move\detail\meta_utils_core.hpp
|
||||
..\..\..\..\boost\move\move.hpp = ..\..\..\..\boost\move\move.hpp
|
||||
..\..\..\..\boost\move\algo\move.hpp = ..\..\..\..\boost\move\algo\move.hpp
|
||||
..\..\doc\move.qbk = ..\..\doc\move.qbk
|
||||
..\..\..\..\boost\move\detail\move_helpers.hpp = ..\..\..\..\boost\move\detail\move_helpers.hpp
|
||||
..\..\..\..\boost\move\detail\placement_new.hpp = ..\..\..\..\boost\move\detail\placement_new.hpp
|
||||
..\..\..\..\boost\move\detail\std_ns_begin.hpp = ..\..\..\..\boost\move\detail\std_ns_begin.hpp
|
||||
..\..\..\..\boost\move\detail\std_ns_end.hpp = ..\..\..\..\boost\move\detail\std_ns_end.hpp
|
||||
..\..\..\..\boost\move\traits.hpp = ..\..\..\..\boost\move\traits.hpp
|
||||
..\..\..\..\boost\move\detail\type_traits.hpp = ..\..\..\..\boost\move\detail\type_traits.hpp
|
||||
..\..\..\..\boost\move\unique_ptr.hpp = ..\..\..\..\boost\move\unique_ptr.hpp
|
||||
|
134
proj/vc7ide/bench_merge.vcproj
Normal file
134
proj/vc7ide/bench_merge.vcproj
Normal file
@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="bench_merge"
|
||||
ProjectGUID="{CD2617A8-6217-9EB7-24CE-6C9AA035376A}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="../../Bin/Win32/Debug"
|
||||
IntermediateDirectory="Debug/bench_merge"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../../.."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
TreatWChar_tAsBuiltInType="TRUE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="winmm.lib"
|
||||
OutputFile="$(OutDir)/bench_merge_d.exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../../../../stage/lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/bench_merge.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="../../Bin/Win32/Release"
|
||||
IntermediateDirectory="Release/bench_merge"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../.."
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
|
||||
RuntimeLibrary="2"
|
||||
TreatWChar_tAsBuiltInType="TRUE"
|
||||
ForceConformanceInForLoopScope="FALSE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="winmm.lib"
|
||||
OutputFile="$(OutDir)/bench_merge.exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../../../../stage/lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{1D875633-A605-0546-5C56-3A5FEAD72B0A}">
|
||||
<File
|
||||
RelativePath="..\..\test\bench_merge.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
134
proj/vc7ide/bench_sort.vcproj
Normal file
134
proj/vc7ide/bench_sort.vcproj
Normal file
@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="bench_sort"
|
||||
ProjectGUID="{CD2617A8-6217-9EB7-24CE-6C9AA035376A}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="../../Bin/Win32/Debug"
|
||||
IntermediateDirectory="Debug/bench_sort"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../../.."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
DisableLanguageExtensions="FALSE"
|
||||
TreatWChar_tAsBuiltInType="TRUE"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="winmm.lib"
|
||||
OutputFile="$(OutDir)/bench_sort_d.exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../../../../stage/lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/bench_sort.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
FixedBaseAddress="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="../../Bin/Win32/Release"
|
||||
IntermediateDirectory="Release/bench_sort"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../.."
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;BOOST_DATE_TIME_NO_LIB"
|
||||
RuntimeLibrary="2"
|
||||
TreatWChar_tAsBuiltInType="TRUE"
|
||||
ForceConformanceInForLoopScope="FALSE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="winmm.lib"
|
||||
OutputFile="$(OutDir)/bench_sort.exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="../../../../stage/lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{1D875633-A605-0546-5C56-3A5FEAD72B0A}">
|
||||
<File
|
||||
RelativePath="..\..\test\bench_sort.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
@ -128,11 +128,6 @@
|
||||
RelativePath="..\..\example\doc_clone_ptr.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93A78280-B78D-4B31-7E8B-6255ACE1E5FB}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@ -128,11 +128,6 @@
|
||||
RelativePath="..\..\example\doc_construct_forward.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93A78280-B78D-4B31-7E8B-6255ACE1E5FB}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@ -128,11 +128,6 @@
|
||||
RelativePath="..\..\example\doc_file_descriptor.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93A78280-B78D-4B31-7E8B-6255ACE1E5FB}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@ -128,11 +128,6 @@
|
||||
RelativePath="..\..\example\doc_how_works.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93A78280-B78D-4B31-7E8B-6255ACE1E5FB}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@ -128,11 +128,6 @@
|
||||
RelativePath="..\..\example\doc_move_algorithms.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93A78280-B78D-4B31-7E8B-6255ACE1E5FB}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@ -128,11 +128,6 @@
|
||||
RelativePath="..\..\example\doc_move_inserter.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93A78280-B78D-4B31-7E8B-6255ACE1E5FB}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@ -128,11 +128,6 @@
|
||||
RelativePath="..\..\example\doc_move_iterator.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93A78280-B78D-4B31-7E8B-6255ACE1E5FB}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@ -128,11 +128,6 @@
|
||||
RelativePath="..\..\test\move.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93A78280-B78D-4B31-7E8B-6255ACE1E5FB}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@ -12,7 +12,7 @@ rule test_all
|
||||
|
||||
for local fileb in [ glob *.cpp ]
|
||||
{
|
||||
all_rules += [ run $(fileb)
|
||||
all_rules += [ run $(fileb) /boost/timer//boost_timer
|
||||
: # additional args
|
||||
: # test-files
|
||||
: # requirements
|
||||
|
328
test/bench_merge.cpp
Normal file
328
test/bench_merge.cpp
Normal file
@ -0,0 +1,328 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <algorithm> //std::inplace_merge
|
||||
#include <cstdio> //std::printf
|
||||
#include <iostream> //std::cout
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/move/unique_ptr.hpp>
|
||||
#include <boost/timer/timer.hpp>
|
||||
|
||||
using boost::timer::cpu_timer;
|
||||
using boost::timer::cpu_times;
|
||||
using boost::timer::nanosecond_type;
|
||||
|
||||
|
||||
boost::ulong_long_type num_copy;
|
||||
boost::ulong_long_type num_elements;
|
||||
|
||||
struct merged_type
|
||||
{
|
||||
public:
|
||||
std::size_t key;
|
||||
std::size_t val;
|
||||
|
||||
merged_type()
|
||||
{
|
||||
++num_elements;
|
||||
}
|
||||
|
||||
merged_type(const merged_type& other)
|
||||
: key(other.key), val(other.val)
|
||||
{
|
||||
++num_elements;
|
||||
++num_copy;
|
||||
}
|
||||
|
||||
merged_type & operator=(const merged_type& other)
|
||||
{
|
||||
++num_copy;
|
||||
key = other.key;
|
||||
val = other.val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~merged_type ()
|
||||
{
|
||||
--num_elements;
|
||||
}
|
||||
};
|
||||
|
||||
boost::ulong_long_type num_compare;
|
||||
|
||||
//#define BOOST_MOVE_ADAPTIVE_SORT_STATS
|
||||
void print_stats(const char *str, boost::ulong_long_type element_count)
|
||||
{
|
||||
std::printf("%sCmp:%8.04f Cpy:%9.04f\n", str, double(num_compare)/element_count, double(num_copy)/element_count );
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
struct counted_less
|
||||
{
|
||||
bool operator()(const T &a,T const &b) const
|
||||
{ ++num_compare; return a.key < b.key; }
|
||||
};
|
||||
|
||||
#include <boost/move/algo/adaptive_merge.hpp>
|
||||
#include <boost/move/algo/detail/merge.hpp>
|
||||
#include <boost/move/core.hpp>
|
||||
|
||||
template<class T, class Compare>
|
||||
std::size_t generate_elements(T elements[], std::size_t element_count, std::size_t key_reps[], std::size_t key_len, Compare comp)
|
||||
{
|
||||
std::srand(0);
|
||||
for(std::size_t i = 0; i < (key_len ? key_len : element_count); ++i){
|
||||
key_reps[i]=0;
|
||||
}
|
||||
for(std::size_t i=0; i < element_count; ++i){
|
||||
std::size_t key = key_len ? (i % key_len) : i;
|
||||
elements[i].key=key;
|
||||
}
|
||||
std::random_shuffle(elements, elements + element_count);
|
||||
std::random_shuffle(elements, elements + element_count);
|
||||
std::random_shuffle(elements, elements + element_count);
|
||||
for(std::size_t i = 0; i < element_count; ++i){
|
||||
elements[i].val = key_reps[elements[i].key]++;
|
||||
}
|
||||
std::size_t split_count = element_count/2;
|
||||
std::stable_sort(elements, elements+split_count, comp);
|
||||
std::stable_sort(elements+split_count, elements+element_count, comp);
|
||||
return split_count;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool test_order(T *elements, std::size_t element_count, bool stable = true)
|
||||
{
|
||||
for(std::size_t i = 1; i < element_count; ++i){
|
||||
if(counted_less<T>()(elements[i], elements[i-1])){
|
||||
std::printf("\n Ord KO !!!!");
|
||||
return false;
|
||||
}
|
||||
if( stable && !(counted_less<T>()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
|
||||
std::printf("\n Stb KO !!!! ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T, class Compare>
|
||||
void adaptive_merge_buffered(T *elements, T *mid, T *last, Compare comp, std::size_t BufLen)
|
||||
{
|
||||
boost::movelib::unique_ptr<char[]> mem(new char[sizeof(T)*BufLen]);
|
||||
boost::movelib::adaptive_merge(elements, mid, last, comp, reinterpret_cast<T*>(mem.get()), BufLen);
|
||||
}
|
||||
|
||||
enum AlgoType
|
||||
{
|
||||
InplaceMerge,
|
||||
AdaptiveMerge,
|
||||
SqrtHAdaptiveMerge,
|
||||
SqrtAdaptiveMerge,
|
||||
Sqrt2AdaptiveMerge,
|
||||
QuartAdaptiveMerge,
|
||||
BuflessMerge,
|
||||
MaxMerge
|
||||
};
|
||||
|
||||
const char *AlgoNames [] = { "InplaceMerge "
|
||||
, "AdaptMerge "
|
||||
, "SqrtHAdaptMerge "
|
||||
, "SqrtAdaptMerge "
|
||||
, "Sqrt2AdaptMerge "
|
||||
, "QuartAdaptMerge "
|
||||
, "BuflessMerge "
|
||||
};
|
||||
|
||||
BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxMerge);
|
||||
|
||||
template<class T>
|
||||
bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count, std::size_t key_len, unsigned alg, nanosecond_type &prev_clock)
|
||||
{
|
||||
std::size_t const split_pos = generate_elements(elements, element_count, key_reps, key_len, counted_less<T>());
|
||||
|
||||
std::printf("%s ", AlgoNames[alg]);
|
||||
num_compare=0;
|
||||
num_copy=0;
|
||||
num_elements = element_count;
|
||||
cpu_timer timer;
|
||||
timer.resume();
|
||||
switch(alg)
|
||||
{
|
||||
case InplaceMerge:
|
||||
std::inplace_merge(elements, elements+split_pos, elements+element_count, counted_less<T>());
|
||||
break;
|
||||
case AdaptiveMerge:
|
||||
boost::movelib::adaptive_merge(elements, elements+split_pos, elements+element_count, counted_less<T>());
|
||||
break;
|
||||
case SqrtHAdaptiveMerge:
|
||||
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>()
|
||||
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
|
||||
break;
|
||||
case SqrtAdaptiveMerge:
|
||||
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>()
|
||||
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
|
||||
break;
|
||||
case Sqrt2AdaptiveMerge:
|
||||
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>()
|
||||
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
|
||||
break;
|
||||
case QuartAdaptiveMerge:
|
||||
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>()
|
||||
, (element_count-1)/4+1);
|
||||
break;
|
||||
case BuflessMerge:
|
||||
boost::movelib::merge_bufferless(elements, elements+split_pos, elements+element_count, counted_less<T>());
|
||||
break;
|
||||
}
|
||||
timer.stop();
|
||||
|
||||
if(num_elements == element_count){
|
||||
std::printf(" Tmp Ok ");
|
||||
} else{
|
||||
std::printf(" Tmp KO ");
|
||||
}
|
||||
nanosecond_type new_clock = timer.elapsed().wall;
|
||||
|
||||
//std::cout << "Cmp:" << num_compare << " Cpy:" << num_copy; //for old compilers without ll size argument
|
||||
std::printf("Cmp:%8.04f Cpy:%9.04f", double(num_compare)/element_count, double(num_copy)/element_count );
|
||||
|
||||
double time = double(new_clock);
|
||||
|
||||
const char *units = "ns";
|
||||
if(time >= 1000000000.0){
|
||||
time /= 1000000000.0;
|
||||
units = " s";
|
||||
}
|
||||
else if(time >= 1000000.0){
|
||||
time /= 1000000.0;
|
||||
units = "ms";
|
||||
}
|
||||
else if(time >= 1000.0){
|
||||
time /= 1000.0;
|
||||
units = "us";
|
||||
}
|
||||
|
||||
std::printf(" %6.02f%s (%6.02f)\n"
|
||||
, time
|
||||
, units
|
||||
, prev_clock ? double(new_clock)/double(prev_clock): 1.0);
|
||||
prev_clock = new_clock;
|
||||
bool res = test_order(elements, element_count, true);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool measure_all(std::size_t L, std::size_t NK)
|
||||
{
|
||||
boost::movelib::unique_ptr<T[]> pdata(new T[L]);
|
||||
boost::movelib::unique_ptr<std::size_t[]> pkeys(new std::size_t[NK ? NK : L]);
|
||||
T *A = pdata.get();
|
||||
std::size_t *Keys = pkeys.get();
|
||||
std::printf("\n - - N: %u, NK: %u - -\n", (unsigned)L, (unsigned)NK);
|
||||
|
||||
nanosecond_type prev_clock = 0;
|
||||
nanosecond_type back_clock;
|
||||
bool res = true;
|
||||
res = res && measure_algo(A,Keys,L,NK,InplaceMerge, prev_clock);
|
||||
back_clock = prev_clock;/*
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,QuartAdaptiveMerge, prev_clock);*/
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,Sqrt2AdaptiveMerge, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,SqrtAdaptiveMerge, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,SqrtHAdaptiveMerge, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,AdaptiveMerge, prev_clock);
|
||||
//
|
||||
//prev_clock = back_clock;
|
||||
//res = res && measure_algo(A,Keys,L,NK,BuflessMerge, prev_clock);
|
||||
//
|
||||
if(!res)
|
||||
throw int(0);
|
||||
return res;
|
||||
}
|
||||
|
||||
struct less
|
||||
{
|
||||
template<class T, class U>
|
||||
bool operator()(const T &t, const U &u)
|
||||
{ return t < u; }
|
||||
};
|
||||
|
||||
//Undef it to run the long test
|
||||
#define BENCH_MERGE_SHORT
|
||||
|
||||
int main()
|
||||
{
|
||||
try{
|
||||
measure_all<merged_type>(101,1);
|
||||
measure_all<merged_type>(101,7);
|
||||
measure_all<merged_type>(101,31);
|
||||
measure_all<merged_type>(101,0);
|
||||
|
||||
//
|
||||
measure_all<merged_type>(1101,1);
|
||||
measure_all<merged_type>(1001,7);
|
||||
measure_all<merged_type>(1001,31);
|
||||
measure_all<merged_type>(1001,127);
|
||||
measure_all<merged_type>(1001,511);
|
||||
measure_all<merged_type>(1001,0);
|
||||
//
|
||||
#ifndef BENCH_MERGE_SHORT
|
||||
measure_all<merged_type>(10001,65);
|
||||
measure_all<merged_type>(10001,255);
|
||||
measure_all<merged_type>(10001,1023);
|
||||
measure_all<merged_type>(10001,4095);
|
||||
measure_all<merged_type>(10001,0);
|
||||
|
||||
//
|
||||
measure_all<merged_type>(100001,511);
|
||||
measure_all<merged_type>(100001,2047);
|
||||
measure_all<merged_type>(100001,8191);
|
||||
measure_all<merged_type>(100001,32767);
|
||||
measure_all<merged_type>(100001,0);
|
||||
|
||||
//
|
||||
#ifdef NDEBUG
|
||||
measure_all<merged_type>(1000001,1);
|
||||
measure_all<merged_type>(1000001,1024);
|
||||
measure_all<merged_type>(1000001,32768);
|
||||
measure_all<merged_type>(1000001,524287);
|
||||
measure_all<merged_type>(1000001,0);
|
||||
measure_all<merged_type>(1500001,0);
|
||||
//measure_all<merged_type>(10000001,0);
|
||||
//measure_all<merged_type>(15000001,0);
|
||||
//measure_all<merged_type>(100000001,0);
|
||||
#endif //NDEBUG
|
||||
|
||||
#endif //#ifndef BENCH_MERGE_SHORT
|
||||
|
||||
//measure_all<merged_type>(100000001,0);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
351
test/bench_sort.cpp
Normal file
351
test/bench_sort.cpp
Normal file
@ -0,0 +1,351 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cstdlib> //std::srand
|
||||
#include <algorithm> //std::stable_sort, std::make|sort_heap, std::random_shuffle
|
||||
#include <cstdio> //std::printf
|
||||
#include <iostream> //std::cout
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/move/unique_ptr.hpp>
|
||||
#include <boost/timer/timer.hpp>
|
||||
|
||||
using boost::timer::cpu_timer;
|
||||
using boost::timer::cpu_times;
|
||||
using boost::timer::nanosecond_type;
|
||||
|
||||
|
||||
boost::ulong_long_type num_copy;
|
||||
boost::ulong_long_type num_elements;
|
||||
|
||||
struct sorted_type
|
||||
{
|
||||
public:
|
||||
std::size_t key;
|
||||
std::size_t val;
|
||||
|
||||
sorted_type()
|
||||
{
|
||||
++num_elements;
|
||||
}
|
||||
|
||||
sorted_type(const sorted_type& other)
|
||||
: key(other.key), val(other.val)
|
||||
{
|
||||
++num_elements;
|
||||
++num_copy;
|
||||
}
|
||||
|
||||
sorted_type & operator=(const sorted_type& other)
|
||||
{
|
||||
++num_copy;
|
||||
key = other.key;
|
||||
val = other.val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~sorted_type ()
|
||||
{
|
||||
--num_elements;
|
||||
}
|
||||
};
|
||||
|
||||
boost::ulong_long_type num_compare;
|
||||
|
||||
//#define BOOST_MOVE_ADAPTIVE_SORT_STATS
|
||||
void print_stats(const char *str, boost::ulong_long_type element_count)
|
||||
{
|
||||
std::printf("%sCmp:%7.03f Cpy:%8.03f\n", str, double(num_compare)/element_count, double(num_copy)/element_count );
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
struct counted_less
|
||||
{
|
||||
bool operator()(const T &a,T const &b) const
|
||||
{ ++num_compare; return a.key < b.key; }
|
||||
};
|
||||
|
||||
#include <boost/move/algo/adaptive_sort.hpp>
|
||||
#include <boost/move/algo/detail/merge_sort.hpp>
|
||||
#include <boost/move/algo/detail/bufferless_merge_sort.hpp>
|
||||
#include <boost/move/core.hpp>
|
||||
|
||||
template<class T>
|
||||
void generate_elements(T elements[], std::size_t element_count, std::size_t key_reps[], std::size_t key_len)
|
||||
{
|
||||
std::srand(0);
|
||||
for(std::size_t i = 0; i < (key_len ? key_len : element_count); ++i){
|
||||
key_reps[i]=0;
|
||||
}
|
||||
for(std::size_t i=0; i < element_count; ++i){
|
||||
std::size_t key = key_len ? (i % key_len) : i;
|
||||
elements[i].key=key;
|
||||
}
|
||||
std::random_shuffle(elements, elements + element_count);
|
||||
std::random_shuffle(elements, elements + element_count);
|
||||
std::random_shuffle(elements, elements + element_count);
|
||||
for(std::size_t i = 0; i < element_count; ++i){
|
||||
elements[i].val = key_reps[elements[i].key]++;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool test_order(T *elements, std::size_t element_count, bool stable = true)
|
||||
{
|
||||
for(std::size_t i = 1; i < element_count; ++i){
|
||||
if(counted_less<T>()(elements[i], elements[i-1])){
|
||||
std::printf("\n Ord KO !!!!");
|
||||
return false;
|
||||
}
|
||||
if( stable && !(counted_less<T>()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
|
||||
std::printf("\n Stb KO !!!! ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T, class Compare>
|
||||
void adaptive_sort_buffered(T *elements, std::size_t element_count, Compare comp, std::size_t BufLen)
|
||||
{
|
||||
boost::movelib::unique_ptr<char[]> mem(new char[sizeof(T)*BufLen]);
|
||||
boost::movelib::adaptive_sort(elements, elements + element_count, comp, reinterpret_cast<T*>(mem.get()), BufLen);
|
||||
}
|
||||
|
||||
template<class T, class Compare>
|
||||
void merge_sort_buffered(T *elements, std::size_t element_count, Compare comp)
|
||||
{
|
||||
boost::movelib::unique_ptr<char[]> mem(new char[sizeof(T)*((element_count+1)/2)]);
|
||||
boost::movelib::merge_sort(elements, elements + element_count, comp, reinterpret_cast<T*>(mem.get()));
|
||||
}
|
||||
|
||||
enum AlgoType
|
||||
{
|
||||
MergeSort,
|
||||
StableSort,
|
||||
AdaptiveSort,
|
||||
SqrtHAdaptiveSort,
|
||||
SqrtAdaptiveSort,
|
||||
Sqrt2AdaptiveSort,
|
||||
QuartAdaptiveSort,
|
||||
NoBufMergeSort,
|
||||
SlowStableSort,
|
||||
HeapSort,
|
||||
MaxSort
|
||||
};
|
||||
|
||||
const char *AlgoNames [] = { "MergeSort "
|
||||
, "StableSort "
|
||||
, "AdaptSort "
|
||||
, "SqrtHAdaptSort "
|
||||
, "SqrtAdaptSort "
|
||||
, "Sqrt2AdaptSort "
|
||||
, "QuartAdaptSort "
|
||||
, "NoBufMergeSort "
|
||||
, "SlowSort "
|
||||
, "HeapSort "
|
||||
};
|
||||
|
||||
BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxSort);
|
||||
|
||||
template<class T>
|
||||
bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count, std::size_t key_len, unsigned alg, nanosecond_type &prev_clock)
|
||||
{
|
||||
generate_elements(elements, element_count, key_reps, key_len);
|
||||
|
||||
std::printf("%s ", AlgoNames[alg]);
|
||||
num_compare=0;
|
||||
num_copy=0;
|
||||
num_elements = element_count;
|
||||
cpu_timer timer;
|
||||
timer.resume();
|
||||
switch(alg)
|
||||
{
|
||||
case MergeSort:
|
||||
merge_sort_buffered(elements, element_count, counted_less<T>());
|
||||
break;
|
||||
case StableSort:
|
||||
std::stable_sort(elements,elements+element_count,counted_less<T>());
|
||||
break;
|
||||
case AdaptiveSort:
|
||||
boost::movelib::adaptive_sort(elements, elements+element_count, counted_less<T>());
|
||||
break;
|
||||
case SqrtHAdaptiveSort:
|
||||
adaptive_sort_buffered( elements, element_count, counted_less<T>()
|
||||
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
|
||||
break;
|
||||
case SqrtAdaptiveSort:
|
||||
adaptive_sort_buffered( elements, element_count, counted_less<T>()
|
||||
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
|
||||
break;
|
||||
case Sqrt2AdaptiveSort:
|
||||
adaptive_sort_buffered( elements, element_count, counted_less<T>()
|
||||
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
|
||||
break;
|
||||
case QuartAdaptiveSort:
|
||||
adaptive_sort_buffered( elements, element_count, counted_less<T>()
|
||||
, (element_count-1)/4+1);
|
||||
break;
|
||||
case NoBufMergeSort:
|
||||
boost::movelib::bufferless_merge_sort(elements, elements+element_count, counted_less<T>());
|
||||
break;
|
||||
case SlowStableSort:
|
||||
boost::movelib::detail_adaptive::slow_stable_sort(elements, elements+element_count, counted_less<T>());
|
||||
break;
|
||||
case HeapSort:
|
||||
std::make_heap(elements, elements+element_count, counted_less<T>());
|
||||
std::sort_heap(elements, elements+element_count, counted_less<T>());
|
||||
break;
|
||||
}
|
||||
timer.stop();
|
||||
|
||||
if(num_elements == element_count){
|
||||
std::printf(" Tmp Ok ");
|
||||
} else{
|
||||
std::printf(" Tmp KO ");
|
||||
}
|
||||
nanosecond_type new_clock = timer.elapsed().wall;
|
||||
|
||||
//std::cout << "Cmp:" << num_compare << " Cpy:" << num_copy; //for old compilers without ll size argument
|
||||
std::printf("Cmp:%7.03f Cpy:%8.03f", double(num_compare)/element_count, double(num_copy)/element_count );
|
||||
|
||||
double time = double(new_clock);
|
||||
|
||||
const char *units = "ns";
|
||||
if(time >= 1000000000.0){
|
||||
time /= 1000000000.0;
|
||||
units = " s";
|
||||
}
|
||||
else if(time >= 1000000.0){
|
||||
time /= 1000000.0;
|
||||
units = "ms";
|
||||
}
|
||||
else if(time >= 1000.0){
|
||||
time /= 1000.0;
|
||||
units = "us";
|
||||
}
|
||||
|
||||
std::printf(" %6.02f%s (%6.02f)\n"
|
||||
, time
|
||||
, units
|
||||
, prev_clock ? double(new_clock)/double(prev_clock): 1.0);
|
||||
prev_clock = new_clock;
|
||||
bool res = test_order(elements, element_count, alg != HeapSort && alg != NoBufMergeSort);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool measure_all(std::size_t L, std::size_t NK)
|
||||
{
|
||||
boost::movelib::unique_ptr<T[]> pdata(new T[L]);
|
||||
boost::movelib::unique_ptr<std::size_t[]> pkeys(new std::size_t[NK ? NK : L]);
|
||||
T *A = pdata.get();
|
||||
std::size_t *Keys = pkeys.get();
|
||||
std::printf("\n - - N: %u, NK: %u - -\n", (unsigned)L, (unsigned)NK);
|
||||
|
||||
nanosecond_type prev_clock = 0;
|
||||
nanosecond_type back_clock;
|
||||
bool res = true;
|
||||
res = res && measure_algo(A,Keys,L,NK,MergeSort, prev_clock);
|
||||
back_clock = prev_clock;
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,StableSort, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,HeapSort, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,QuartAdaptiveSort, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,Sqrt2AdaptiveSort, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,SqrtAdaptiveSort, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,SqrtHAdaptiveSort, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,AdaptiveSort, prev_clock);
|
||||
//
|
||||
prev_clock = back_clock;
|
||||
res = res && measure_algo(A,Keys,L,NK,NoBufMergeSort, prev_clock);
|
||||
//
|
||||
//prev_clock = back_clock;
|
||||
//res = res && measure_algo(A,Keys,L,NK,SlowStableSort, prev_clock);
|
||||
//
|
||||
if(!res)
|
||||
throw int(0);
|
||||
return res;
|
||||
}
|
||||
|
||||
//Undef it to run the long test
|
||||
#define BENCH_SORT_SHORT
|
||||
|
||||
struct less
|
||||
{
|
||||
template<class T, class U>
|
||||
bool operator()(const T &t, const U &u)
|
||||
{ return t < u; }
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
measure_all<sorted_type>(101,1);
|
||||
measure_all<sorted_type>(101,7);
|
||||
measure_all<sorted_type>(101,31);
|
||||
measure_all<sorted_type>(101,0);
|
||||
|
||||
//
|
||||
measure_all<sorted_type>(1101,1);
|
||||
measure_all<sorted_type>(1001,7);
|
||||
measure_all<sorted_type>(1001,31);
|
||||
measure_all<sorted_type>(1001,127);
|
||||
measure_all<sorted_type>(1001,511);
|
||||
measure_all<sorted_type>(1001,0);
|
||||
//
|
||||
#ifndef BENCH_SORT_SHORT
|
||||
measure_all<sorted_type>(10001,65);
|
||||
measure_all<sorted_type>(10001,255);
|
||||
measure_all<sorted_type>(10001,1023);
|
||||
measure_all<sorted_type>(10001,4095);
|
||||
measure_all<sorted_type>(10001,0);
|
||||
|
||||
//
|
||||
measure_all<sorted_type>(100001,511);
|
||||
measure_all<sorted_type>(100001,2047);
|
||||
measure_all<sorted_type>(100001,8191);
|
||||
measure_all<sorted_type>(100001,32767);
|
||||
measure_all<sorted_type>(100001,0);
|
||||
|
||||
//
|
||||
#ifdef NDEBUG
|
||||
measure_all<sorted_type>(1000001,1);
|
||||
measure_all<sorted_type>(1000001,1024);
|
||||
measure_all<sorted_type>(1000001,32768);
|
||||
measure_all<sorted_type>(1000001,524287);
|
||||
measure_all<sorted_type>(1000001,0);
|
||||
measure_all<sorted_type>(1500001,0);
|
||||
//measure_all<sorted_type>(10000001,0);
|
||||
#endif //NDEBUG
|
||||
|
||||
#endif //#ifndef BENCH_SORT_SHORT
|
||||
|
||||
//measure_all<sorted_type>(100000001,0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -47,33 +47,79 @@ static const unsigned char ee_patternbuf[PatternSize] = { 0xEE, 0xEE, 0xEE, 0xEE
|
||||
static const unsigned char dd_patternbuf[PatternSize] = { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD };
|
||||
static const unsigned char cc_patternbuf[PatternSize] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC };
|
||||
|
||||
void volatile_memset(volatile void *p, int ch, std::size_t len)
|
||||
{
|
||||
volatile unsigned char *puch = static_cast<volatile unsigned char *>(p);
|
||||
for(std::size_t i = 0; i != len; ++i){
|
||||
*puch = (unsigned char)ch;
|
||||
++puch;
|
||||
}
|
||||
}
|
||||
|
||||
int volatile_memcmp(const volatile void *p1, const volatile void *p2, std::size_t len)
|
||||
{
|
||||
const volatile unsigned char *s1 = static_cast<const volatile unsigned char *>(p1);
|
||||
const volatile unsigned char *s2 = static_cast<const volatile unsigned char *>(p2);
|
||||
unsigned char u1, u2;
|
||||
|
||||
for ( ; len-- ; s1++, s2++) {
|
||||
u1 = *s1;
|
||||
u2 = *s2;
|
||||
if (u1 != u2) {
|
||||
return (u1-u2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void volatile_memcmp(volatile void *p, int ch, std::size_t len)
|
||||
{
|
||||
volatile unsigned char *puch = static_cast<volatile unsigned char *>(p);
|
||||
for(std::size_t i = 0; i != len; ++i){
|
||||
*puch = (unsigned char)ch;
|
||||
++puch;
|
||||
}
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
|
||||
struct default_init
|
||||
{
|
||||
static void* operator new(std::size_t sz)
|
||||
{
|
||||
void *const p = ::operator new(sz);
|
||||
return std::memset(p, 0xFF, sz);
|
||||
//Make sure they are not optimized out
|
||||
volatile_memset(p, 0xFF, sz);
|
||||
std::cout << "0xFF" << '\n';
|
||||
return p;
|
||||
}
|
||||
static void* operator new[](std::size_t sz)
|
||||
{
|
||||
void *const p = ::operator new[](sz);
|
||||
return std::memset(p, 0xEE, sz);
|
||||
//Make sure they are not optimized out
|
||||
volatile_memset(p, 0xEE, sz);
|
||||
std::cout << "0xEE" << '\n';
|
||||
return p;
|
||||
}
|
||||
static void* operator new(std::size_t sz, const std::nothrow_t &)
|
||||
{
|
||||
void *const p = ::operator new(sz);
|
||||
return std::memset(p, 0xDD, sz);
|
||||
//Make sure they are not optimized out
|
||||
volatile_memset(p, 0xDD, sz);
|
||||
std::cout << "0xDD" << '\n';
|
||||
return p;
|
||||
}
|
||||
static void* operator new[](std::size_t sz, const std::nothrow_t &)
|
||||
{
|
||||
void *const p = ::operator new[](sz);
|
||||
return std::memset(p, 0xCC, sz);
|
||||
//Make sure they are not optimized out
|
||||
volatile_memset(p, 0xCC, sz);
|
||||
std::cout << "0xCC" << '\n';
|
||||
return p;
|
||||
}
|
||||
unsigned char buf[PatternSize];
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace bml = ::boost::movelib;
|
||||
|
||||
////////////////////////////////
|
||||
@ -88,11 +134,12 @@ void test()
|
||||
reset_counters();
|
||||
{
|
||||
bml::unique_ptr<default_init> p(bml::make_unique_definit<default_init>());
|
||||
BOOST_TEST(0 == std::memcmp(p.get(), ff_patternbuf, sizeof(ff_patternbuf)));
|
||||
BOOST_TEST(0 == volatile_memcmp(p.get(), ff_patternbuf, sizeof(ff_patternbuf)));
|
||||
}
|
||||
{
|
||||
bml::unique_ptr<default_init> p(bml::make_unique_nothrow_definit<default_init>());
|
||||
BOOST_TEST(0 == std::memcmp(p.get(), dd_patternbuf, sizeof(dd_patternbuf)));
|
||||
|
||||
BOOST_TEST(0 == volatile_memcmp(p.get(), dd_patternbuf, sizeof(dd_patternbuf)));
|
||||
}
|
||||
|
||||
BOOST_TEST(A::count == 0);
|
||||
@ -167,14 +214,14 @@ void test()
|
||||
{
|
||||
bml::unique_ptr<default_init[]> p(bml::make_unique_definit<default_init[]>(10));
|
||||
for(unsigned i = 0; i != 10; ++i){
|
||||
BOOST_TEST(0 == std::memcmp(&p[i], ee_patternbuf, sizeof(ee_patternbuf)));
|
||||
BOOST_TEST(0 == volatile_memcmp(&p[i], ee_patternbuf, sizeof(ee_patternbuf)));
|
||||
}
|
||||
}
|
||||
reset_counters();
|
||||
{
|
||||
bml::unique_ptr<default_init[]> p(bml::make_unique_nothrow_definit<default_init[]>(10));
|
||||
for(unsigned i = 0; i != 10; ++i){
|
||||
BOOST_TEST(0 == std::memcmp(&p[i], cc_patternbuf, sizeof(cc_patternbuf)));
|
||||
BOOST_TEST(0 == volatile_memcmp(&p[i], cc_patternbuf, sizeof(cc_patternbuf)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user