Merge branch 'develop'

This commit is contained in:
Ion Gaztañaga
2016-08-10 10:17:38 +02:00
24 changed files with 2020 additions and 938 deletions

View File

@@ -661,6 +661,32 @@ An alternative is to implement a single `operator =()` for copyable and movable
However, "pass by value" is not optimal for classes (like containers, strings, etc.) that reuse resources
(like previously allocated memory) when x is assigned from a lvalue.
[endsect]
[section:templated_assignment_operator Templated assignment operator in copyable and movable types]
[import ../example/doc_template_assign.cpp]
Given a movable and copyable class, if a templated assignment operator (*) is added:
[template_assign_example_foo_bar]
C++98 and C++11 compilers will behave different when assigning from a `[const] Foo` lvalue:
[template_assign_example_main]
This different behaviour is a side-effect of the move emulation that can't be easily avoided by
[*Boost.Move]. One workaround is to SFINAE-out the templated assignment operator with `disable_if`:
[c++]
template<class U> // Modified templated assignment
typename boost::disable_if<boost::is_same<U, Foo>, Foo&>::type
operator=(const U& rhs)
{ i = -rhs.i; return *this; } //(2)
[endsect]
[endsect]
@@ -762,6 +788,14 @@ Many thanks to all boosters that have tested, reviewed and improved the library.
[section:release_notes Release Notes]
[section:release_notes_boost_1_62 Boost 1.62 Release]
* Documented new limitations reported in Trac tickets
[@https://svn.boost.org/trac/boost/ticket/12194 #12194 ['"Copy assignment on moveable and copyable classes uses wrong type"]] and
[@https://svn.boost.org/trac/boost/ticket/12307 #12307 ['"Copy assignment on moveable and copyable classes uses wrong type"]].
[endsect]
[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]

View File

@@ -0,0 +1,98 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/move/detail/config_begin.hpp>
#include <boost/move/detail/meta_utils_core.hpp>
#include <boost/move/move.hpp>
//[template_assign_example_foo_bar
class Foo
{
BOOST_COPYABLE_AND_MOVABLE(Foo)
public:
int i;
explicit Foo(int val) : i(val) {}
Foo(BOOST_RV_REF(Foo) obj) : i(obj.i) {}
Foo& operator=(BOOST_RV_REF(Foo) rhs)
{ i = rhs.i; rhs.i = 0; return *this; }
Foo& operator=(BOOST_COPY_ASSIGN_REF(Foo) rhs)
{ i = rhs.i; return *this; } //(1)
template<class U> //(*) TEMPLATED ASSIGNMENT, potential problem
//<-
#if 1
typename ::boost::move_detail::disable_if_same<U, Foo, Foo&>::type
operator=(const U& rhs)
#else
//->
Foo& operator=(const U& rhs)
//<-
#endif
//->
{ i = -rhs.i; return *this; } //(2)
};
//]
struct Bar
{
int i;
explicit Bar(int val) : i(val) {}
};
//<-
#ifdef NDEBUG
#undef NDEBUG
#endif
//->
#include <cassert>
int main()
{
//[template_assign_example_main
Foo foo1(1);
//<-
assert(foo1.i == 1);
//->
Foo foo2(2);
//<-
assert(foo2.i == 2);
Bar bar(3);
assert(bar.i == 3);
//->
foo2 = foo1; // Calls (1) in C++11 but (2) in C++98
//<-
assert(foo2.i == 1);
assert(foo1.i == 1); //Fails in C++98 unless workaround is applied
foo1 = bar;
assert(foo1.i == -3);
foo2 = boost::move(foo1);
assert(foo1.i == 0);
assert(foo2.i == -3);
//->
const Foo foo5(5);
foo2 = foo5; // Calls (1) in C++11 but (2) in C++98
//<-
assert(foo2.i == 5); //Fails in C++98 unless workaround is applied
assert(foo5.i == 5);
//->
//]
return 0;
}
#include <boost/move/detail/config_end.hpp>

View File

@@ -231,8 +231,8 @@ BOOST_MOVE_FORCEINLINE void adl_move_swap(T& x, T& y)
//! 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
//! 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.

View File

@@ -56,7 +56,7 @@ void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp
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);
::boost::movelib::detail_adaptive::adaptive_merge_impl(first, size_type(middle - first), size_type(last - middle), comp, xbuf);
}
} //namespace movelib {

File diff suppressed because it is too large Load Diff

View File

@@ -21,12 +21,14 @@
#include <boost/move/utility_core.hpp>
#include <boost/move/adl_move_swap.hpp>
#include <boost/move/detail/iterator_traits.hpp>
namespace boost {
namespace movelib {
struct forward_t{};
struct backward_t{};
struct three_way_t{};
struct move_op
{
@@ -41,6 +43,13 @@ struct move_op
template <class SourceIt, class DestinationIt>
DestinationIt operator()(backward_t, SourceIt first, SourceIt last, DestinationIt dest_last)
{ return ::boost::move_backward(first, last, dest_last); }
template <class SourceIt, class DestinationIt1, class DestinationIt2>
void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
{
*dest2it = boost::move(*dest1it);
*dest1it = boost::move(*srcit);
}
};
struct swap_op
@@ -56,6 +65,15 @@ struct swap_op
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); }
template <class SourceIt, class DestinationIt1, class DestinationIt2>
void operator()(three_way_t, SourceIt srcit, DestinationIt1 dest1it, DestinationIt2 dest2it)
{
typename ::boost::movelib::iterator_traits<SourceIt>::value_type tmp(boost::move(*dest2it));
*dest2it = boost::move(*dest1it);
*dest1it = boost::move(*srcit);
*srcit = boost::move(tmp);
}
};
}} //namespace boost::movelib

View File

@@ -167,7 +167,7 @@ void op_merge_left( RandIt buf_first
op(forward_t(), first2, last2, buf_first);
return;
}
else if(comp(*first2, *first1)){
else if(comp(*first2, *first1)){
op(first2, buf_first);
++first2;
}
@@ -214,7 +214,7 @@ void op_merge_right
{
RandIt const first2 = last1;
while(first1 != last1){
if(last2 == first2){
if(last2 == first2){
op(backward_t(), first1, last1, buf_last);
return;
}
@@ -230,7 +230,7 @@ void op_merge_right
++last1;
}
}
if(last2 != buf_last){ //In case all remaining elements are in the same place
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);
@@ -257,9 +257,104 @@ void swap_merge_right
op_merge_right(first1, last1, last2, buf_last, comp, swap_op());
}
// cost: min(L1,L2)^2+max(L1,L2)
template <class BidirIt, class Distance, class Compare>
void merge_bufferless_ONlogN_recursive
(BidirIt first, BidirIt middle, BidirIt last, Distance len1, Distance len2, Compare comp)
{
typedef typename iterator_traits<BidirIt>::size_type size_type;
while(1) {
//#define MERGE_BUFFERLESS_RECURSIVE_OPT
#ifndef MERGE_BUFFERLESS_RECURSIVE_OPT
if (len2 == 0) {
return;
}
if (!len1) {
return;
}
if ((len1 | len2) == 1) {
if (comp(*middle, *first))
adl_move_swap(*first, *middle);
return;
}
#else
if (len2 == 0) {
return;
}
if (!len1) {
return;
}
BidirIt middle_prev = middle; --middle_prev;
if(!comp(*middle, *middle_prev))
return;
while(true) {
if (comp(*middle, *first))
break;
++first;
if(--len1 == 1)
break;
}
if (len1 == 1 && len2 == 1) {
//comp(*middle, *first) == true already tested in the loop
adl_move_swap(*first, *middle);
return;
}
#endif
BidirIt first_cut = first;
BidirIt second_cut = middle;
Distance len11 = 0;
Distance len22 = 0;
if (len1 > len2) {
len11 = len1 / 2;
first_cut += len11;
second_cut = lower_bound(middle, last, *first_cut, comp);
len22 = size_type(second_cut - middle);
}
else {
len22 = len2 / 2;
second_cut += len22;
first_cut = upper_bound(first, middle, *second_cut, comp);
len11 = size_type(first_cut - first);
}
BidirIt new_middle = rotate_gcd(first_cut, middle, second_cut);
//Avoid one recursive call doing a manual tail call elimination on the biggest range
const Distance len_internal = len11+len22;
if( len_internal < (len1 + len2 - len_internal) ) {
merge_bufferless_ONlogN_recursive(first, first_cut, new_middle, len11, len22, comp);
//merge_bufferless_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
first = new_middle;
middle = second_cut;
len1 -= len11;
len2 -= len22;
}
else {
//merge_bufferless_recursive(first, first_cut, new_middle, len11, len22, comp);
merge_bufferless_ONlogN_recursive(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
middle = first_cut;
last = new_middle;
len1 = len11;
len2 = len22;
}
}
}
//Complexity: NlogN
template<class BidirIt, class Compare>
void merge_bufferless_ONlogN(BidirIt first, BidirIt middle, BidirIt last, Compare comp)
{
merge_bufferless_ONlogN_recursive
(first, middle, last, middle - first, last - middle, comp);
}
//Complexity: min(len1,len2)^2 + max(len1,len2)
template<class RandIt, class Compare>
void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
void merge_bufferless_ON2(RandIt first, RandIt middle, RandIt last, Compare comp)
{
if((middle - first) < (last - middle)){
while(first != middle){
@@ -271,12 +366,12 @@ void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
}
do{
++first;
} while(first != middle && !comp(*middle, *first));
} while(first != middle && !comp(*middle, *first));
}
}
else{
while(middle != last){
RandIt p = upper_bound(first, middle, last[-1], comp);
RandIt p = upper_bound(first, middle, last[-1], comp);
last = rotate_gcd(p, middle, last);
middle = p;
if(middle == first){
@@ -290,10 +385,21 @@ void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
}
}
template<class RandIt, class Compare>
void merge_bufferless(RandIt first, RandIt middle, RandIt last, Compare comp)
{
//#define BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
#ifdef BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
merge_bufferless_ONlogN(first, middle, last, comp);
#else
merge_bufferless_ON2(first, middle, last, comp);
#endif //BOOST_ADAPTIVE_MERGE_NLOGN_MERGE
}
template<class Comp>
struct antistable
{
antistable(Comp &comp)
explicit antistable(Comp &comp)
: m_comp(comp)
{}
@@ -306,6 +412,49 @@ struct antistable
Comp &m_comp;
};
template <class Comp>
class negate
{
public:
negate()
{}
explicit negate(Comp comp)
: m_comp(comp)
{}
template <class T1, class T2>
bool operator()(const T1& l, const T2& r)
{
return !m_comp(l, r);
}
private:
Comp m_comp;
};
template <class Comp>
class inverse
{
public:
inverse()
{}
explicit inverse(Comp comp)
: m_comp(comp)
{}
template <class T1, class T2>
bool operator()(const T1& l, const T2& r)
{
return m_comp(r, l);
}
private:
Comp m_comp;
};
// [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

View File

@@ -41,6 +41,21 @@ namespace movelib {
static const unsigned MergeSortInsertionSortThreshold = 16;
template <class RandIt, class Compare>
void inplace_stable_sort(RandIt first, RandIt last, Compare comp)
{
typedef typename iterator_traits<RandIt>::size_type size_type;
if (size_type(last - first) <= size_type(MergeSortInsertionSortThreshold)) {
insertion_sort(first, last, comp);
return;
}
RandIt middle = first + (last - first) / 2;
inplace_stable_sort(first, middle, comp);
inplace_stable_sort(middle, last, comp);
merge_bufferless_ONlogN_recursive
(first, middle, last, size_type(middle - first), size_type(last - middle), comp);
}
// @endcond
template<class RandIt, class RandIt2, class Compare>

View File

@@ -125,10 +125,10 @@ F uninitialized_move(I f, I l, F r
}
}
BOOST_CATCH(...){
for (; back != r; ++back){
for (; back != r; ++back){
back->~input_value_type();
}
BOOST_RETHROW;
BOOST_RETHROW;
}
BOOST_CATCH_END
return r;

View File

@@ -260,8 +260,8 @@
#define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
public:\
TYPE& operator=(TYPE &t)\
{ this->operator=(const_cast<const TYPE &>(t)); return *this;}\
BOOST_MOVE_FORCEINLINE TYPE& operator=(TYPE &t)\
{ this->operator=(const_cast<const TYPE&>(t)); return *this;}\
public:\
BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
{ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\

View File

@@ -114,6 +114,18 @@ struct is_same<T, T>
static const bool value = true;
};
//////////////////////////////////////
// enable_if_same
//////////////////////////////////////
template <class T, class U, class R = void>
struct enable_if_same : enable_if<is_same<T, U>, R> {};
//////////////////////////////////////
// disable_if_same
//////////////////////////////////////
template <class T, class U, class R = void>
struct disable_if_same : disable_if<is_same<T, U>, R> {};
} //namespace move_detail {
} //namespace boost {

View File

@@ -0,0 +1,171 @@
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2014-2014
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP
#define BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/move/detail/config_begin.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/detail/meta_utils.hpp>
namespace boost {
namespace movelib {
template<class It>
class reverse_iterator
{
public:
typedef typename boost::movelib::iterator_traits<It>::pointer pointer;
typedef typename boost::movelib::iterator_traits<It>::reference reference;
typedef typename boost::movelib::iterator_traits<It>::difference_type difference_type;
typedef typename boost::movelib::iterator_traits<It>::iterator_category iterator_category;
typedef typename boost::movelib::iterator_traits<It>::value_type value_type;
typedef It iterator_type;
reverse_iterator()
: m_current() //Value initialization to achieve "null iterators" (N3644)
{}
explicit reverse_iterator(It r)
: m_current(r)
{}
reverse_iterator(const reverse_iterator& r)
: m_current(r.base())
{}
template<class OtherIt>
reverse_iterator( const reverse_iterator<OtherIt>& r
, typename boost::move_detail::enable_if_convertible<OtherIt, It>::type* =0
)
: m_current(r.base())
{}
reverse_iterator & operator=( const reverse_iterator& r)
{ m_current = r.base(); return *this; }
template<class OtherIt>
typename boost::move_detail::enable_if_convertible<OtherIt, It, reverse_iterator &>::type
operator=( const reverse_iterator<OtherIt>& r)
{ m_current = r.base(); return *this; }
It base() const
{ return m_current; }
reference operator*() const
{
It temp(m_current);
--temp;
reference r = *temp;
return r;
}
pointer operator->() const
{
It temp(m_current);
--temp;
return iterator_arrow_result(temp);
}
reference operator[](difference_type off) const
{
return this->m_current[-off - 1];
}
reverse_iterator& operator++()
{
--m_current;
return *this;
}
reverse_iterator operator++(int)
{
reverse_iterator temp((*this));
--m_current;
return temp;
}
reverse_iterator& operator--()
{
++m_current;
return *this;
}
reverse_iterator operator--(int)
{
reverse_iterator temp((*this));
++m_current;
return temp;
}
friend bool operator==(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current == r.m_current; }
friend bool operator!=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current != r.m_current; }
friend bool operator<(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current > r.m_current; }
friend bool operator<=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current >= r.m_current; }
friend bool operator>(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current < r.m_current; }
friend bool operator>=(const reverse_iterator& l, const reverse_iterator& r)
{ return l.m_current <= r.m_current; }
reverse_iterator& operator+=(difference_type off)
{ m_current -= off; return *this; }
reverse_iterator& operator-=(difference_type off)
{ m_current += off; return *this; }
friend reverse_iterator operator+(reverse_iterator l, difference_type off)
{ return (l += off); }
friend reverse_iterator operator+(difference_type off, reverse_iterator r)
{ return (r += off); }
friend reverse_iterator operator-(reverse_iterator l, difference_type off)
{ return (l-= off); }
friend difference_type operator-(const reverse_iterator& l, const reverse_iterator& r)
{ return r.m_current - l.m_current; }
private:
It m_current; // the wrapped iterator
};
template< class Iterator >
reverse_iterator<Iterator> make_reverse_iterator( Iterator i )
{
return reverse_iterator<Iterator>(i);
}
} //namespace movelib {
} //namespace boost {
#include <boost/move/detail/config_end.hpp>
#endif //BOOST_MOVE_DETAIL_REVERSE_ITERATOR_HPP

View File

@@ -55,8 +55,10 @@
// BOOST_MOVE_IS_POD(T) should evaluate to true if T is a POD type
// BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect
// BOOST_MOVE_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy
// (Note: this trait does not guarantee T is copy constructible, the copy constructor could be deleted but still be trivial)
// BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) should evaluate to true if T(boost::move(t)) <==> memcpy
// BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy
// (Note: this trait does not guarantee T is assignable , the copy assignmen could be deleted but still be trivial)
// BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) should evaluate to true if t = boost::move(u) <==> memcpy
// BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect
// BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) should evaluate to true if "T x;" can not throw
@@ -117,9 +119,7 @@
# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
# endif
# if __has_feature(has_trivial_copy)
# //There are problems with deleted copy constructors detected as trivially copyable.
# //http://stackoverflow.com/questions/12754886/has-trivial-copy-behaves-differently-in-clang-and-gcc-whos-right
# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T) && ::boost::move_detail::is_copy_constructible<T>::value)
# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) __has_trivial_copy(T)
# endif
# if __has_feature(has_trivial_assign)
# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) )
@@ -235,7 +235,9 @@
#endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_COPY
#define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_COPY(T)
#define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value ||\
(::boost::move_detail::is_copy_constructible<T>::value &&\
BOOST_MOVE_HAS_TRIVIAL_COPY(T))
#else
#define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif
@@ -246,12 +248,6 @@
#define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_COPY
#define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_COPY(T)
#else
#define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
#endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR
#define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T)
#else
@@ -259,7 +255,9 @@
#endif
#ifdef BOOST_MOVE_HAS_TRIVIAL_ASSIGN
#define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T)
#define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value ||\
( ::boost::move_detail::is_copy_assignable<T>::value &&\
BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T))
#else
#define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
#endif
@@ -821,9 +819,7 @@ struct is_trivially_copy_constructible
{
//In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
//deleted copy constructors so make sure the type is copy constructible.
static const bool value = ::boost::move_detail::is_pod<T>::value ||
( ::boost::move_detail::is_copy_constructible<T>::value &&
BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) );
static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T);
};
//////////////////////////////////////
@@ -831,7 +827,7 @@ struct is_trivially_copy_constructible
//////////////////////////////////////
template<class T>
struct is_trivially_move_constructible
{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T); };
{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T); };
//////////////////////////////////////
// is_trivially_copy_assignable
@@ -841,9 +837,7 @@ struct is_trivially_copy_assignable
{
//In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
//deleted copy constructors so make sure the type is copy constructible.
static const bool value = ::boost::move_detail::is_pod<T>::value ||
( ::boost::move_detail::is_copy_assignable<T>::value &&
BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) );
static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T);
};
//////////////////////////////////////
@@ -1005,7 +999,7 @@ BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1000)
template<class T, std::size_t Len>
union aligned_union
{
{
T aligner;
char dummy[Len];
};
@@ -1023,7 +1017,7 @@ struct aligned_next<Len, Align, T, true>
//End of search defaults to max_align_t
template<std::size_t Len, std::size_t Align>
struct aligned_next<Len, Align, max_align_t, false>
{ typedef aligned_union<max_align_t, Len> type; };
{ typedef aligned_union<max_align_t, Len> type; };
//Now define a search list through types
#define BOOST_MOVE_ALIGNED_NEXT_STEP(TYPE, NEXT_TYPE)\

View File

@@ -119,6 +119,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_merge", "bench_merge.
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adaptive_sort_test", "adaptive_sort_test.vcproj", "{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adaptive_merge_test", "adaptive_merge_test.vcproj", "{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_template_assign", "doc_template_assign.vcproj", "{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
@@ -247,6 +259,18 @@ Global
{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
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.ActiveCfg = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.Build.0 = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.ActiveCfg = Release|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.Build.0 = Release|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.ActiveCfg = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Debug.Build.0 = Debug|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.ActiveCfg = Release|Win32
{CD617A28-6217-B79E-4CE2-6BA035379A6A}.Release.Build.0 = Release|Win32
{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}.Debug.ActiveCfg = Debug|Win32
{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}.Debug.Build.0 = Debug|Win32
{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}.Release.ActiveCfg = Release|Win32
{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionItems) = postSolution
..\..\..\..\boost\move\algo\adaptive_merge.hpp = ..\..\..\..\boost\move\algo\adaptive_merge.hpp
@@ -267,8 +291,8 @@ Global
..\..\..\..\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\algo\detail\merge.hpp = ..\..\..\..\boost\move\algo\detail\merge.hpp
..\..\..\..\boost\move\algo\detail\merge_sort.hpp = ..\..\..\..\boost\move\algo\detail\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

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="adaptive_merge_test"
ProjectGUID="{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/adaptive_merge_test"
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)/adaptive_merge_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/adaptive_merge_test.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/adaptive_merge_test"
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)/adaptive_merge_test.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="{163D8753-0546-A605-5C56-3B0FEAD7A52A}">
<File
RelativePath="..\..\test\adaptive_merge_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="adaptive_sort_test"
ProjectGUID="{CD617A28-6217-B79E-4CE2-6BA035379A6A}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/adaptive_sort_test"
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)/adaptive_sort_test_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/adaptive_sort_test.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/adaptive_sort_test"
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)/adaptive_sort_test.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="{163D8753-0546-A605-5C56-3B0FEAD7A52A}">
<File
RelativePath="..\..\test\adaptive_sort_test.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="doc_template_assign"
ProjectGUID="{7460CA18-D532-E4F8-F1F2-3A796D2A91E2}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../../Bin/Win32/Debug"
IntermediateDirectory="Debug/doc_template_assign"
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)/doc_template_assign_d.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="../../../../stage/lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/doc_template_assign.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/doc_template_assign"
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)/doc_template_assign.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="{475F3C87-6465-7BC5-05A6-2454C0A2A2CF}">
<File
RelativePath="..\..\example\doc_template_assign.cpp">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,87 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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::next_permutation
#include <iostream> //std::cout
#include <boost/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/container/vector.hpp>
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
#include "order_type.hpp"
#include <boost/move/algo/adaptive_merge.hpp>
#include <boost/move/core.hpp>
template<class T>
bool test_random_shuffled(std::size_t const element_count, std::size_t const num_keys, std::size_t const num_iter)
{
boost::movelib::unique_ptr<T[]> elements(new T[element_count]);
boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[num_keys ? num_keys : element_count]);
std::cout << "- - N: " << element_count << ", Keys: " << num_keys << ", It: " << num_iter << " \n";
//Initialize keys
for(std::size_t i=0; i < element_count; ++i){
std::size_t key = num_keys ? (i % num_keys) : i;
elements[i].key=key;
}
std::srand(0);
for (std::size_t i = 0; i != num_iter; ++i)
{
std::random_shuffle(elements.get(), elements.get() + element_count);
for(std::size_t i = 0; i < (num_keys ? num_keys : element_count); ++i){
key_reps[i]=0;
}
for(std::size_t i = 0; i < element_count; ++i){
elements[i].val = key_reps[elements[i].key]++;
}
boost::container::vector<order_type> tmp(elements.get(), elements.get()+element_count);
std::size_t const split = std::size_t(std::rand()) % element_count;
std::stable_sort(tmp.data(), tmp.data()+split, order_type_less<order_type>());
std::stable_sort(tmp.data()+split, tmp.data()+element_count, order_type_less<order_type>());
boost::movelib::adaptive_merge(tmp.data(), tmp.data()+split, tmp.data()+element_count, order_type_less<order_type>());
if (!is_order_type_ordered(tmp.data(), element_count))
{
std::cout << "\n ERROR\n";
throw int(0);
}
}
return true;
}
int main()
{
#ifdef NDEBUG
const std::size_t NIter = 100;
#else
const std::size_t NIter = 10;
#endif
test_random_shuffled<order_type>(10001, 65, NIter);
test_random_shuffled<order_type>(10001, 101, NIter);
test_random_shuffled<order_type>(10001, 1023, NIter);
test_random_shuffled<order_type>(10001, 4095, NIter);
test_random_shuffled<order_type>(10001, 0, NIter);
return 0;
}

View File

@@ -0,0 +1,83 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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::next_permutation
#include <iostream> //std::cout
#include <boost/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/container/vector.hpp>
#include <boost/timer/timer.hpp>
using boost::timer::cpu_timer;
using boost::timer::cpu_times;
using boost::timer::nanosecond_type;
#include "order_type.hpp"
#include <boost/move/algo/adaptive_sort.hpp>
#include <boost/move/core.hpp>
template<class T>
bool test_random_shuffled(std::size_t const element_count, std::size_t const num_keys, std::size_t const num_iter)
{
boost::movelib::unique_ptr<T[]> elements(new T[element_count]);
boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[num_keys ? num_keys : element_count]);
std::cout << "- - N: " << element_count << ", Keys: " << num_keys << ", It: " << num_iter << " \n";
//Initialize keys
for(std::size_t i=0; i < element_count; ++i){
std::size_t key = num_keys ? (i % num_keys) : i;
elements[i].key=key;
}
std::srand(0);
for (std::size_t i = 0; i != num_iter; ++i)
{
std::random_shuffle(elements.get(), elements.get() + element_count);
for(std::size_t i = 0; i < (num_keys ? num_keys : element_count); ++i){
key_reps[i]=0;
}
for(std::size_t i = 0; i < element_count; ++i){
elements[i].val = key_reps[elements[i].key]++;
}
boost::container::vector<order_type> tmp(elements.get(), elements.get()+element_count);
boost::movelib::adaptive_sort(tmp.data(), tmp.data()+element_count, order_type_less<order_type>());
if (!is_order_type_ordered(tmp.data(), element_count))
{
std::cout << "\n ERROR\n";
throw int(0);
}
}
return true;
}
int main()
{
#ifdef NDEBUG
const std::size_t NIter = 100;
#else
const std::size_t NIter = 10;
#endif
test_random_shuffled<order_type>(10001, 65, NIter);
test_random_shuffled<order_type>(10001, 101, NIter);
test_random_shuffled<order_type>(10001, 1023, NIter);
test_random_shuffled<order_type>(10001, 4095, NIter);
test_random_shuffled<order_type>(10001, 0, NIter);
return 0;
}

View File

@@ -18,62 +18,18 @@
#include <boost/move/unique_ptr.hpp>
#include <boost/timer/timer.hpp>
#include "order_type.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 );
std::printf("%sCmp:%8.04f Cpy:%9.04f\n", str, double(order_type::num_compare)/element_count, double(order_type::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>
@@ -101,21 +57,7 @@ std::size_t generate_elements(T elements[], std::size_t element_count, std::size
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)
@@ -126,23 +68,23 @@ void adaptive_merge_buffered(T *elements, T *mid, T *last, Compare comp, std::si
enum AlgoType
{
InplaceMerge,
StdMerge,
AdaptiveMerge,
SqrtHAdaptiveMerge,
SqrtAdaptiveMerge,
Sqrt2AdaptiveMerge,
QuartAdaptiveMerge,
BuflessMerge,
StdInplaceMerge,
MaxMerge
};
const char *AlgoNames [] = { "InplaceMerge "
const char *AlgoNames [] = { "StdMerge "
, "AdaptMerge "
, "SqrtHAdaptMerge "
, "SqrtAdaptMerge "
, "Sqrt2AdaptMerge "
, "QuartAdaptMerge "
, "BuflessMerge "
, "StdInplaceMerge "
};
BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxMerge);
@@ -150,53 +92,53 @@ 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::size_t const split_pos = generate_elements(elements, element_count, key_reps, key_len, order_type_less<T>());
std::printf("%s ", AlgoNames[alg]);
num_compare=0;
num_copy=0;
num_elements = element_count;
order_type::num_compare=0;
order_type::num_copy=0;
order_type::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>());
case StdMerge:
std::inplace_merge(elements, elements+split_pos, elements+element_count, order_type_less<T>());
break;
case AdaptiveMerge:
boost::movelib::adaptive_merge(elements, elements+split_pos, elements+element_count, counted_less<T>());
boost::movelib::adaptive_merge(elements, elements+split_pos, elements+element_count, order_type_less<T>());
break;
case SqrtHAdaptiveMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, counted_less<T>()
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_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>()
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_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>()
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_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>()
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less<T>()
, (element_count-1)/4+1);
break;
case BuflessMerge:
boost::movelib::merge_bufferless(elements, elements+split_pos, elements+element_count, counted_less<T>());
case StdInplaceMerge:
boost::movelib::merge_bufferless_ONlogN(elements, elements+split_pos, elements+element_count, order_type_less<T>());
break;
}
timer.stop();
if(num_elements == element_count){
if(order_type::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 );
//std::cout << "Cmp:" << order_type::num_compare << " Cpy:" << order_type::num_copy; //for old compilers without ll size argument
std::printf("Cmp:%8.04f Cpy:%9.04f", double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
double time = double(new_clock);
@@ -219,7 +161,7 @@ bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count
, units
, prev_clock ? double(new_clock)/double(prev_clock): 1.0);
prev_clock = new_clock;
bool res = test_order(elements, element_count, true);
bool res = is_order_type_ordered(elements, element_count, true);
return res;
}
@@ -235,7 +177,7 @@ bool measure_all(std::size_t L, std::size_t NK)
nanosecond_type prev_clock = 0;
nanosecond_type back_clock;
bool res = true;
res = res && measure_algo(A,Keys,L,NK,InplaceMerge, prev_clock);
res = res && measure_algo(A,Keys,L,NK,StdMerge, prev_clock);
back_clock = prev_clock;/*
//
prev_clock = back_clock;
@@ -253,70 +195,74 @@ bool measure_all(std::size_t L, std::size_t NK)
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);
prev_clock = back_clock;
res = res && measure_algo(A,Keys,L,NK,StdInplaceMerge, 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
#define BENCH_SORT_UNIQUE_VALUES
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);
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_type>(101,1);
measure_all<order_type>(101,7);
measure_all<order_type>(101,31);
#endif
measure_all<order_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_SORT_UNIQUE_VALUES
measure_all<order_type>(1101,1);
measure_all<order_type>(1001,7);
measure_all<order_type>(1001,31);
measure_all<order_type>(1001,127);
measure_all<order_type>(1001,511);
#endif
measure_all<order_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);
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_type>(10001,65);
measure_all<order_type>(10001,255);
measure_all<order_type>(10001,1023);
measure_all<order_type>(10001,4095);
#endif
measure_all<order_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);
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_type>(100001,511);
measure_all<order_type>(100001,2047);
measure_all<order_type>(100001,8191);
measure_all<order_type>(100001,32767);
#endif
measure_all<order_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);
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_type>(1000001,1);
measure_all<order_type>(1000001,1024);
measure_all<order_type>(1000001,32768);
measure_all<order_type>(1000001,524287);
#endif
measure_all<order_type>(1000001,0);
measure_all<order_type>(1500001,0);
//measure_all<order_type>(10000001,0);
//measure_all<order_type>(15000001,0);
//measure_all<order_type>(100000001,0);
#endif //NDEBUG
#endif //#ifndef BENCH_MERGE_SHORT
//measure_all<merged_type>(100000001,0);
//measure_all<order_type>(100000001,0);
}
catch(...)
{

View File

@@ -23,58 +23,15 @@ 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;
#include "order_type.hpp"
//#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 );
std::printf("%sCmp:%7.03f Cpy:%8.03f\n", str, double(order_type::num_compare)/element_count, double(order_type::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>
@@ -99,22 +56,6 @@ void generate_elements(T elements[], std::size_t element_count, std::size_t 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)
{
@@ -139,6 +80,7 @@ enum AlgoType
Sqrt2AdaptiveSort,
QuartAdaptiveSort,
NoBufMergeSort,
InplaceStableSort,
SlowStableSort,
HeapSort,
MaxSort
@@ -152,6 +94,7 @@ const char *AlgoNames [] = { "MergeSort "
, "Sqrt2AdaptSort "
, "QuartAdaptSort "
, "NoBufMergeSort "
, "InplStableSort "
, "SlowSort "
, "HeapSort "
};
@@ -164,60 +107,63 @@ bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count
generate_elements(elements, element_count, key_reps, key_len);
std::printf("%s ", AlgoNames[alg]);
num_compare=0;
num_copy=0;
num_elements = element_count;
order_type::num_compare=0;
order_type::num_copy=0;
order_type::num_elements = element_count;
cpu_timer timer;
timer.resume();
switch(alg)
{
case MergeSort:
merge_sort_buffered(elements, element_count, counted_less<T>());
merge_sort_buffered(elements, element_count, order_type_less<T>());
break;
case StableSort:
std::stable_sort(elements,elements+element_count,counted_less<T>());
std::stable_sort(elements,elements+element_count,order_type_less<T>());
break;
case AdaptiveSort:
boost::movelib::adaptive_sort(elements, elements+element_count, counted_less<T>());
boost::movelib::adaptive_sort(elements, elements+element_count, order_type_less<T>());
break;
case SqrtHAdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>()
adaptive_sort_buffered( elements, element_count, order_type_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>()
adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case Sqrt2AdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>()
adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case QuartAdaptiveSort:
adaptive_sort_buffered( elements, element_count, counted_less<T>()
adaptive_sort_buffered( elements, element_count, order_type_less<T>()
, (element_count-1)/4+1);
break;
case NoBufMergeSort:
boost::movelib::bufferless_merge_sort(elements, elements+element_count, counted_less<T>());
boost::movelib::bufferless_merge_sort(elements, elements+element_count, order_type_less<T>());
break;
case InplaceStableSort:
boost::movelib::inplace_stable_sort(elements, elements+element_count, order_type_less<T>());
break;
case SlowStableSort:
boost::movelib::detail_adaptive::slow_stable_sort(elements, elements+element_count, counted_less<T>());
boost::movelib::detail_adaptive::slow_stable_sort(elements, elements+element_count, order_type_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>());
std::make_heap(elements, elements+element_count, order_type_less<T>());
std::sort_heap(elements, elements+element_count, order_type_less<T>());
break;
}
timer.stop();
if(num_elements == element_count){
if(order_type::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 );
//std::cout << "Cmp:" << order_type::num_compare << " Cpy:" << order_type::num_copy; //for old compilers without ll size argument
std::printf("Cmp:%7.03f Cpy:%8.03f", double(order_type::num_compare)/element_count, double(order_type::num_copy)/element_count );
double time = double(new_clock);
@@ -240,7 +186,7 @@ bool measure_algo(T *elements, std::size_t key_reps[], std::size_t element_count
, 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);
bool res = is_order_type_ordered(elements, element_count, alg != HeapSort && alg != NoBufMergeSort);
return res;
}
@@ -281,6 +227,9 @@ bool measure_all(std::size_t L, std::size_t NK)
res = res && measure_algo(A,Keys,L,NK,AdaptiveSort, prev_clock);
//
prev_clock = back_clock;
res = res && measure_algo(A,Keys,L,NK,InplaceStableSort, prev_clock);
//
prev_clock = back_clock;
res = res && measure_algo(A,Keys,L,NK,NoBufMergeSort, prev_clock);
//
//prev_clock = back_clock;
@@ -293,59 +242,61 @@ bool measure_all(std::size_t L, std::size_t NK)
//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; }
};
#define BENCH_SORT_UNIQUE_VALUES
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);
#ifndef BENCH_SORT_UNIQUE_VALUES
//measure_all<order_type>(101,1);
measure_all<order_type>(101,7);
measure_all<order_type>(101,31);
#endif
measure_all<order_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_UNIQUE_VALUES
measure_all<order_type>(1101,1);
measure_all<order_type>(1001,7);
measure_all<order_type>(1001,31);
measure_all<order_type>(1001,127);
measure_all<order_type>(1001,511);
#endif
measure_all<order_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);
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_type>(10001,65);
measure_all<order_type>(10001,255);
measure_all<order_type>(10001,1023);
measure_all<order_type>(10001,4095);
measure_all<order_type>(10001,0);
#endif
//
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);
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_type>(100001,511);
measure_all<order_type>(100001,2047);
measure_all<order_type>(100001,8191);
measure_all<order_type>(100001,32767);
#endif
measure_all<order_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
//#ifdef NDEBUG
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_type>(1000001,1);
measure_all<order_type>(1000001,1024);
measure_all<order_type>(1000001,32768);
measure_all<order_type>(1000001,524287);
#endif
measure_all<order_type>(1000001,0);
measure_all<order_type>(1500001,0);
//measure_all<order_type>(10000001,0);
//#endif //NDEBUG
#endif //#ifndef BENCH_SORT_SHORT
//measure_all<sorted_type>(100000001,0);
//measure_all<order_type>(100000001,0);
return 0;
}

View File

@@ -139,7 +139,7 @@ int main()
movable m4(function(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
@@ -149,7 +149,7 @@ int main()
movable m4(functionr(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
@@ -159,7 +159,7 @@ int main()
movable m4(function2(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
@@ -169,7 +169,7 @@ int main()
movable m4(function2r(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
@@ -177,7 +177,7 @@ int main()
BOOST_CHECK(!m2.moved());
movable m3(move_return_function());
BOOST_CHECK(!m3.moved());
}
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
@@ -185,7 +185,7 @@ int main()
BOOST_CHECK(!m2.moved());
movable m3(move_return_function2());
BOOST_CHECK(!m3.moved());
}
}
// copy_movable may throw during move, so it must be copied
{
@@ -197,7 +197,7 @@ int main()
copy_movable m4(function(boost::move_if_noexcept(m3)));
BOOST_CHECK(!m3.moved());
BOOST_CHECK(!m4.moved());
}
}
// copy_movable_noexcept can not throw during move
@@ -210,7 +210,7 @@ int main()
copy_movable_noexcept m4(function(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
}
// movable_throwable can not throw during move but it has no copy constructor
{
@@ -222,7 +222,7 @@ int main()
movable_throwable m4(function(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
}
return boost::report_errors();
}

82
test/order_type.hpp Normal file
View File

@@ -0,0 +1,82 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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_TEST_ORDER_TYPE_HPP
#define BOOST_MOVE_TEST_ORDER_TYPE_HPP
#include <boost/config.hpp>
#include <cstddef>
#include <cstdio>
struct order_type
{
public:
std::size_t key;
std::size_t val;
order_type()
{
++num_elements;
}
order_type(const order_type& other)
: key(other.key), val(other.val)
{
++num_elements;
++num_copy;
}
order_type & operator=(const order_type& other)
{
++num_copy;
key = other.key;
val = other.val;
return *this;
}
~order_type ()
{
--num_elements;
}
static boost::ulong_long_type num_compare;
static boost::ulong_long_type num_copy;
static boost::ulong_long_type num_elements;
};
boost::ulong_long_type order_type::num_compare = 0;
boost::ulong_long_type order_type::num_copy = 0;
boost::ulong_long_type order_type::num_elements = 0;
template<class T>
struct order_type_less
{
bool operator()(const T &a,T const &b) const
{ ++order_type::num_compare; return a.key < b.key; }
};
template<class T>
inline bool is_order_type_ordered(T *elements, std::size_t element_count, bool stable = true)
{
for(std::size_t i = 1; i < element_count; ++i){
if(order_type_less<T>()(elements[i], elements[i-1])){
std::printf("\n Ord KO !!!!");
return false;
}
if( stable && !(order_type_less<T>()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
std::printf("\n Stb KO !!!! ");
return false;
}
}
return true;
}
#endif //BOOST_MOVE_TEST_ORDER_TYPE_HPP

View File

@@ -63,11 +63,11 @@ int volatile_memcmp(const volatile void *p1, const volatile void *p2, std::size_
unsigned char u1, u2;
for ( ; len-- ; s1++, s2++) {
u1 = *s1;
u2 = *s2;
if (u1 != u2) {
return (u1-u2);
}
u1 = *s1;
u2 = *s2;
if (u1 != u2) {
return (u1-u2);
}
}
return 0;
}