1
0
mirror of https://git.suyu.dev/suyu/suyu synced 2025-09-20 04:52:06 -05:00

Initial commit

This commit is contained in:
Crimson-Hawk
2024-03-05 16:42:40 +08:00
commit f1e4595ebf
39576 changed files with 7006612 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
# Copyright 2018, 2019 Peter Dimov
# 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
include(BoostTest OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
if(NOT HAVE_BOOST_TEST)
return()
endif()
file(GLOB tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
set(BOOST_TEST_LINK_LIBRARIES Boost::move Boost::config Boost::container Boost::core Boost::static_assert)
foreach(test IN LISTS tests)
boost_test(SOURCES ${test})
endforeach()

View File

@@ -0,0 +1,29 @@
##############################################################################
##
## (C) Copyright Ion Gaztanaga 2008-2009 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)
##
##
##############################################################################
import testing ;
rule test_all
{
local all_rules = ;
for local fileb in [ glob *.cpp ]
{
all_rules += [ run $(fileb)
: # additional args
: # test-files
: # requirements
] ;
}
return $(all_rules) ;
}
test-suite move_test : [ test_all r ] ;

View File

@@ -0,0 +1,93 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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 <iostream> //std::cout
#include <boost/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/move/algo/detail/merge_sort.hpp>
#include <boost/move/detail/force_ptr.hpp>
#include "order_type.hpp"
#include "random_shuffle.hpp"
#include <boost/move/algo/adaptive_merge.hpp>
#include <boost/move/core.hpp>
#include <cstdlib>
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)
{
::random_shuffle(elements.get(), elements.get() + element_count);
for(std::size_t j = 0; j < (num_keys ? num_keys : element_count); ++j){
key_reps[j]=0;
}
for(std::size_t j = 0; j < element_count; ++j){
elements[j].val = key_reps[elements[j].key]++;
}
boost::movelib::unique_ptr<char[]> buf(new char [sizeof(T)*(element_count-element_count/2)]);
std::size_t const split = std::size_t(std::rand()) % element_count;
boost::movelib::merge_sort(elements.get(), elements.get()+split, order_type_less(), boost::move_detail::force_ptr<T*>(buf.get()));
boost::movelib::merge_sort(elements.get()+split, elements.get()+element_count, order_type_less(), boost::move_detail::force_ptr<T*>(buf.get()));
boost::movelib::adaptive_merge(elements.get(), elements.get()+split, elements.get()+element_count, order_type_less());
if (!is_order_type_ordered(elements.get(), element_count))
{
std::cout << "\n ERROR\n";
std::abort();
}
}
return true;
}
void instantiate_smalldiff_iterators()
{
typedef randit<int, short> short_rand_it_t;
boost::movelib::adaptive_merge(short_rand_it_t(), short_rand_it_t(), short_rand_it_t(), less_int());
typedef randit<int, signed char> schar_rand_it_t;
boost::movelib::adaptive_merge(schar_rand_it_t(), schar_rand_it_t(), schar_rand_it_t(), less_int());
}
int main()
{
instantiate_smalldiff_iterators();
const std::size_t NIter = 100;
test_random_shuffled<order_move_type>(10001, 3, NIter);
test_random_shuffled<order_move_type>(10001, 65, NIter);
test_random_shuffled<order_move_type>(10001, 101, NIter);
test_random_shuffled<order_move_type>(10001, 1023, NIter);
test_random_shuffled<order_move_type>(10001, 4095, NIter);
test_random_shuffled<order_move_type>(10001, 0, NIter);
return 0;
}

View File

@@ -0,0 +1,91 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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 <iostream> //std::cout
#include <boost/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/container/vector.hpp>
#include "order_type.hpp"
#include "random_shuffle.hpp"
#include <boost/move/algo/adaptive_sort.hpp>
#include <boost/move/core.hpp>
#include <cstdlib>
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 it = 0; it != num_iter; ++it)
{
::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::movelib::adaptive_sort(elements.get(), elements.get()+element_count, order_type_less());
if (!is_order_type_ordered(elements.get(), element_count))
{
std::cout << "\n ERROR\n";
std::abort();
}
}
return true;
}
void instantiate_smalldiff_iterators()
{
typedef randit<int, short> short_rand_it_t;
boost::movelib::adaptive_sort(short_rand_it_t(), short_rand_it_t(), less_int());
typedef randit<int, signed char> schar_rand_it_t;
boost::movelib::adaptive_sort(schar_rand_it_t(), schar_rand_it_t(), less_int());
}
int main()
{
instantiate_smalldiff_iterators();
const std::size_t NIter = 100;
//Below absolute minimal unique values
test_random_shuffled<order_move_type>(10001, 3, NIter);
//Above absolute minimal unique values, below internal buffer
test_random_shuffled<order_move_type>(10001, 65, NIter);
//Enough keys for internal buffer but below minimal keys
test_random_shuffled<order_move_type>(10001, 101, NIter);
//Enough keys for internal buffer and above minimal keys
test_random_shuffled<order_move_type>(10001, 200, NIter);
//Enough keys for internal buffer, and full keys
test_random_shuffled<order_move_type>(10001, 1023, NIter);
test_random_shuffled<order_move_type>(10001, 4095, NIter);
test_random_shuffled<order_move_type>(10001, 0, NIter);
return 0;
}

View File

@@ -0,0 +1,167 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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/adl_move_swap.hpp>
#include <boost/move/core.hpp>
#include <boost/core/lightweight_test.hpp>
class swap_stats
{
public:
static void reset_stats()
{
member_swap_calls = 0;
friend_swap_calls = 0;
move_cnstor_calls = 0;
move_assign_calls = 0;
copy_cnstor_calls = 0;
copy_assign_calls = 0;
}
static unsigned int member_swap_calls;
static unsigned int friend_swap_calls;
static unsigned int move_cnstor_calls;
static unsigned int move_assign_calls;
static unsigned int copy_cnstor_calls;
static unsigned int copy_assign_calls;
};
unsigned int swap_stats::member_swap_calls = 0;
unsigned int swap_stats::friend_swap_calls = 0;
unsigned int swap_stats::move_cnstor_calls = 0;
unsigned int swap_stats::move_assign_calls = 0;
unsigned int swap_stats::copy_cnstor_calls = 0;
unsigned int swap_stats::copy_assign_calls = 0;
class movable : public swap_stats
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(movable)
public:
movable() {}
movable(BOOST_RV_REF(movable)) { ++move_cnstor_calls; }
movable & operator=(BOOST_RV_REF(movable)){ ++move_assign_calls; return *this; }
friend void swap(movable &, movable &) { ++friend_swap_calls; }
};
class movable_swap_member : public swap_stats
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_swap_member)
public:
movable_swap_member() {}
movable_swap_member(BOOST_RV_REF(movable_swap_member)) { ++move_cnstor_calls; }
movable_swap_member & operator=(BOOST_RV_REF(movable_swap_member)){ ++move_assign_calls; return *this; }
void swap(movable_swap_member &) { ++member_swap_calls; }
friend void swap(movable_swap_member &, movable_swap_member &) { ++friend_swap_calls; }
};
class copyable : public swap_stats
{
public:
copyable() {}
copyable(const copyable &) { ++copy_cnstor_calls; }
copyable & operator=(const copyable&) { ++copy_assign_calls; return *this; }
void swap(copyable &) { ++member_swap_calls; }
friend void swap(copyable &, copyable &) { ++friend_swap_calls; }
};
class no_swap : public swap_stats
{
private: unsigned m_state;
public:
explicit no_swap(unsigned i): m_state(i){}
no_swap(const no_swap &x) { m_state = x.m_state; ++copy_cnstor_calls; }
no_swap & operator=(const no_swap& x) { m_state = x.m_state; ++copy_assign_calls; return *this; }
void swap(no_swap &) { ++member_swap_calls; }
friend bool operator==(const no_swap &x, const no_swap &y) { return x.m_state == y.m_state; }
friend bool operator!=(const no_swap &x, const no_swap &y) { return !(x==y); }
};
int main()
{
{ //movable
movable x, y;
swap_stats::reset_stats();
::boost::adl_move_swap(x, y);
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
//In non rvalue reference compilers,
//movable classes with no swap() member uses
//boost::move() to implement swap.
BOOST_TEST(swap_stats::friend_swap_calls == 0);
BOOST_TEST(swap_stats::member_swap_calls == 0);
BOOST_TEST(swap_stats::member_swap_calls == 0);
BOOST_TEST(swap_stats::move_cnstor_calls == 1);
BOOST_TEST(swap_stats::move_assign_calls == 2);
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
BOOST_TEST(swap_stats::copy_assign_calls == 0);
#else
//In compilers with rvalue references, this should call friend swap via ADL
BOOST_TEST(swap_stats::friend_swap_calls == 1);
BOOST_TEST(swap_stats::member_swap_calls == 0);
BOOST_TEST(swap_stats::member_swap_calls == 0);
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
BOOST_TEST(swap_stats::move_assign_calls == 0);
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
BOOST_TEST(swap_stats::copy_assign_calls == 0);
#endif
}
{ //movable_swap_member
movable_swap_member x, y;
swap_stats::reset_stats();
::boost::adl_move_swap(x, y);
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
//In non rvalue reference compilers,
//movable classes with no swap() member uses
//boost::move() to implement swap.
BOOST_TEST(swap_stats::friend_swap_calls == 0);
BOOST_TEST(swap_stats::member_swap_calls == 1);
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
BOOST_TEST(swap_stats::move_assign_calls == 0);
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
BOOST_TEST(swap_stats::copy_assign_calls == 0);
#else
//In compilers with rvalue references, this should call friend swap via ADL
BOOST_TEST(swap_stats::friend_swap_calls == 1);
BOOST_TEST(swap_stats::member_swap_calls == 0);
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
BOOST_TEST(swap_stats::move_assign_calls == 0);
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
BOOST_TEST(swap_stats::copy_assign_calls == 0);
#endif
}
{ //copyable
copyable x, y;
swap_stats::reset_stats();
::boost::adl_move_swap(x, y);
//This should call friend swap via ADL
BOOST_TEST(swap_stats::friend_swap_calls == 1);
BOOST_TEST(swap_stats::member_swap_calls == 0);
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
BOOST_TEST(swap_stats::move_assign_calls == 0);
BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
BOOST_TEST(swap_stats::copy_assign_calls == 0);
}
{ //no_swap
no_swap x(1), y(2), x_back(x), y_back(y);
swap_stats::reset_stats();
::boost::adl_move_swap(x, y);
//This should call std::swap which uses copies
BOOST_TEST(swap_stats::friend_swap_calls == 0);
BOOST_TEST(swap_stats::member_swap_calls == 0);
BOOST_TEST(swap_stats::move_cnstor_calls == 0);
BOOST_TEST(swap_stats::move_assign_calls == 0);
BOOST_TEST(swap_stats::copy_cnstor_calls == 1);
BOOST_TEST(swap_stats::copy_assign_calls == 2);
BOOST_TEST(x == y_back);
BOOST_TEST(y == x_back);
BOOST_TEST(x != y);
}
return ::boost::report_errors();
}

View File

@@ -0,0 +1,953 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2007-2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/move/algo/detail/set_difference.hpp>
#include "order_type.hpp"
#include <boost/core/lightweight_test.hpp>
#include <cstddef>
/*
///////////////////////////////////
//
// set_difference
//
///////////////////////////////////
void test_set_difference_normal()
{
order_perf_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_perf_type range1[4];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 1u;
range1[1].val = 1u;
range1[2].key = 3u;
range1[2].val = 1u;
range1[3].key = 4u;
range1[3].val = 1u;
order_perf_type out[20];
out[2].key = 998;
out[2].val = 999;
boost::movelib::set_difference(range1, range1+4, range2, range2+10, out, order_type_less());
BOOST_TEST(out[0].key == 1u);
BOOST_TEST(out[0].val == 1u);
BOOST_TEST(out[1].key == 3u);
BOOST_TEST(out[1].val == 1u);
BOOST_TEST(out[2].key == 998);
BOOST_TEST(out[2].val == 999);
}
void test_set_difference_range1_repeated()
{
order_perf_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_perf_type range1[4];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 2u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 6u;
range1[3].val = 1u;
order_perf_type out[20];
out[0].key = 998;
out[0].val = 999;
boost::movelib::set_difference(range1, range1+4, range2, range2+10, out, order_type_less());
BOOST_TEST(out[0].key == 998);
BOOST_TEST(out[0].val == 999);
}
void test_set_difference_range1_unique()
{
order_perf_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_perf_type range1[4];
range1[0].key = 1u;
range1[0].val = 1u;
range1[1].key = 3u;
range1[1].val = 1u;
range1[2].key = 5u;
range1[2].val = 1u;
range1[3].key = 7u;
range1[3].val = 1u;
order_perf_type out[20];
out[4].key = 998;
out[4].val = 999;
boost::movelib::set_difference(range1, range1+4, range2, range2+10, out, order_type_less());
BOOST_TEST(out[0].key == 1u);
BOOST_TEST(out[0].val == 1u);
BOOST_TEST(out[1].key == 3u);
BOOST_TEST(out[1].val == 1u);
BOOST_TEST(out[2].key == 5u);
BOOST_TEST(out[3].val == 1u);
BOOST_TEST(out[3].key == 7u);
BOOST_TEST(out[3].val == 1u);
BOOST_TEST(out[4].key == 998);
BOOST_TEST(out[4].val == 999);
}
*/
///////////////////////////////////
//
// set_difference
//
///////////////////////////////////
void test_set_difference_normal()
{
order_perf_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_perf_type range1[5];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 1u;
range1[1].val = 1u;
range1[2].key = 1u;
range1[2].val = 2u;
range1[3].key = 3u;
range1[3].val = 1u;
range1[4].key = 4u;
range1[4].val = 1u;
order_perf_type out[20];
out[3].key = 998;
out[3].val = 999;
order_perf_type *r =
boost::movelib::set_difference(range1, range1+5, range2, range2+10, out, order_type_less());
BOOST_TEST(&out[3] == r);
BOOST_TEST(out[0].key == 1u);
BOOST_TEST(out[0].val == 1u);
BOOST_TEST(out[1].key == 1u);
BOOST_TEST(out[1].val == 2u);
BOOST_TEST(out[2].key == 3u);
BOOST_TEST(out[2].val == 1u);
BOOST_TEST(out[3].key == 998);
BOOST_TEST(out[3].val == 999);
}
void test_set_difference_range1_repeated()
{
order_perf_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_perf_type range1[5];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 2u;
range1[1].val = 1u;
range1[2].key = 2u;
range1[2].val = 2u;
range1[3].key = 4u;
range1[3].val = 1u;
range1[4].key = 6u;
range1[4].val = 1u;
order_perf_type out[20];
out[0].key = 998;
out[0].val = 999;
order_perf_type *r =
boost::movelib::set_difference(range1, range1+5, range2, range2+10, out, order_type_less());
BOOST_TEST(&out[1] == r);
BOOST_TEST(out[0].key == 2);
BOOST_TEST(out[0].val == 2);
}
void test_set_difference_range1_unique()
{
order_perf_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_perf_type range1[5];
range1[0].key = 1u;
range1[0].val = 1u;
range1[1].key = 3u;
range1[1].val = 1u;
range1[2].key = 5u;
range1[2].val = 1u;
range1[3].key = 7u;
range1[3].val = 1u;
range1[4].key = 7u;
range1[4].val = 2u;
order_perf_type out[20];
out[5].key = 998;
out[5].val = 999;
order_perf_type *r =
boost::movelib::set_difference(range1, range1+5, range2, range2+10, out, order_type_less());
BOOST_TEST(&out[5] == r);
BOOST_TEST(out[0].key == 1u);
BOOST_TEST(out[0].val == 1u);
BOOST_TEST(out[1].key == 3u);
BOOST_TEST(out[1].val == 1u);
BOOST_TEST(out[2].key == 5u);
BOOST_TEST(out[2].val == 1u);
BOOST_TEST(out[3].key == 7u);
BOOST_TEST(out[3].val == 1u);
BOOST_TEST(out[4].key == 7u);
BOOST_TEST(out[4].val == 2u);
BOOST_TEST(out[5].key == 998);
BOOST_TEST(out[5].val == 999);
}
/*
///////////////////////////////////
//
// inplace_set_difference
//
///////////////////////////////////
void test_inplace_set_difference_normal()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[4];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 1u;
range1[1].val = 1u;
range1[2].key = 3u;
range1[2].val = 1u;
range1[3].key = 4u;
range1[3].val = 1u;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+2);
BOOST_TEST(range1[0].key == 1u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 3u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == order_move_type::moved_assign_mark);
BOOST_TEST(range1[2].val == order_move_type::moved_assign_mark);
}
void test_inplace_set_difference_range1_repeated()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[5];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 2u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 6u;
range1[3].val = 1u;
range1[4].key = order_move_type::moved_assign_mark;
range1[4].val = order_move_type::moved_assign_mark;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+0);
BOOST_TEST(range1[0].key == 0u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 2u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == 4u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[3].key == 6u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
}
void test_inplace_set_difference_range1_unique()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[5];
range1[0].key = 1u;
range1[0].val = 1u;
range1[1].key = 3u;
range1[1].val = 1u;
range1[2].key = 5u;
range1[2].val = 1u;
range1[3].key = 7u;
range1[3].val = 1u;
range1[4].key = order_move_type::moved_assign_mark;
range1[4].val = order_move_type::moved_assign_mark;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+4);
BOOST_TEST(range1[0].key == 1u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 3u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == 5u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[3].key == 7u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
}
void test_inplace_set_difference_range1_unique_long()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[11];
for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
range1[i].key = i*2+1;
range1[i].val = 1u;
}
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+11, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+11);
for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
BOOST_TEST(range1[i].key == i*2+1);
BOOST_TEST(range1[i].val == 1u);
}
}
void test_inplace_set_difference_range1_same_start()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[5];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 2u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 5u;
range1[3].val = 1u;
range1[4].key = 7u;
range1[4].val = 1u;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+2);
BOOST_TEST(range1[0].key == 5u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 7u);
BOOST_TEST(range1[1].val == 1u);
}
void test_inplace_set_difference_range1_same_end()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[5];
range1[0].key = 1u;
range1[0].val = 1u;
range1[1].key = 3u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 6u;
range1[3].val = 1u;
range1[4].key = 8u;
range1[4].val = 1u;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+2);
BOOST_TEST(range1[0].key == 1u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 3u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == 4u);
BOOST_TEST(range1[2].val == 1u);
BOOST_TEST(range1[3].key == 6u);
BOOST_TEST(range1[3].val == 1u);
}
*/
///////////////////////////////////
//
// inplace_set_difference
//
///////////////////////////////////
void test_inplace_set_difference_normal()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[4];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 1u;
range1[1].val = 1u;
range1[2].key = 3u;
range1[2].val = 1u;
range1[3].key = 4u;
range1[3].val = 1u;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+2);
BOOST_TEST(range1[0].key == 1u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 3u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == order_move_type::moved_assign_mark);
BOOST_TEST(range1[2].val == order_move_type::moved_assign_mark);
}
void test_inplace_set_difference_range1_repeated()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[5];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 2u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 6u;
range1[3].val = 1u;
range1[4].key = order_move_type::moved_assign_mark;
range1[4].val = order_move_type::moved_assign_mark;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+0);
BOOST_TEST(range1[0].key == 0u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 2u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == 4u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[3].key == 6u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
}
void test_inplace_set_difference_range1_unique()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[5];
range1[0].key = 1u;
range1[0].val = 1u;
range1[1].key = 3u;
range1[1].val = 1u;
range1[2].key = 5u;
range1[2].val = 1u;
range1[3].key = 7u;
range1[3].val = 1u;
range1[4].key = order_move_type::moved_assign_mark;
range1[4].val = order_move_type::moved_assign_mark;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+4, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+4);
BOOST_TEST(range1[0].key == 1u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 3u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == 5u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[3].key == 7u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
}
void test_inplace_set_difference_range1_unique_long()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[11];
for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
range1[i].key = i*2+1;
range1[i].val = 1u;
}
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+11, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+11);
for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
BOOST_TEST(range1[i].key == i*2+1);
BOOST_TEST(range1[i].val == 1u);
}
}
void test_inplace_set_difference_range1_same_start()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[5];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 2u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 5u;
range1[3].val = 1u;
range1[4].key = 7u;
range1[4].val = 1u;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+2);
BOOST_TEST(range1[0].key == 5u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 7u);
BOOST_TEST(range1[1].val == 1u);
}
void test_inplace_set_difference_range1_same_end()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[5];
range1[0].key = 1u;
range1[0].val = 1u;
range1[1].key = 3u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 6u;
range1[3].val = 1u;
range1[4].key = 8u;
range1[4].val = 1u;
order_move_type *ret = boost::movelib::inplace_set_difference(range1, range1+5, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+2);
BOOST_TEST(range1[0].key == 1u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 3u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == 4u);
BOOST_TEST(range1[2].val == 1u);
BOOST_TEST(range1[3].key == 6u);
BOOST_TEST(range1[3].val == 1u);
}
///////////////////////////////////
//
// set_unique_difference
//
///////////////////////////////////
void test_set_unique_difference_normal()
{
order_perf_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_perf_type range1[10];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 1u;
range1[1].val = 1u;
range1[2].key = 1u;
range1[2].val = 2u;
range1[3].key = 3u;
range1[3].val = 1u;
range1[4].key = 4u;
range1[4].val = 1u;
range1[5].key = 4u;
range1[5].val = 2u;
range1[6].key = 21u;
range1[6].val = 1u;
range1[7].key = 21u;
range1[7].val = 2u;
range1[8].key = 23u;
range1[8].val = 1u;
range1[9].key = 23u;
range1[9].val = 2u;
order_perf_type out[20];
out[4].key = 998;
out[4].val = 999;
order_perf_type * r =
boost::movelib::set_unique_difference(range1, range1+10, range2, range2+10, out, order_type_less());
BOOST_TEST(&out[4] == r);
BOOST_TEST(out[0].key == 1u);
BOOST_TEST(out[0].val == 1u);
BOOST_TEST(out[1].key == 3u);
BOOST_TEST(out[1].val == 1u);
BOOST_TEST(out[2].key == 21u);
BOOST_TEST(out[2].val == 1u);
BOOST_TEST(out[3].key == 23u);
BOOST_TEST(out[3].val == 1u);
BOOST_TEST(out[4].key == 998);
BOOST_TEST(out[4].val == 999);
}
void test_set_unique_difference_range1_repeated()
{
order_perf_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_perf_type range1[11];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 0u;
range1[1].val = 2u;
range1[2].key = 0u;
range1[2].val = 2u;
range1[3].key = 2u;
range1[3].val = 1u;
range1[4].key = 2u;
range1[4].val = 2u;
range1[5].key = 4u;
range1[5].val = 1u;
range1[6].key = 6u;
range1[6].val = 1u;
range1[7].key = 6u;
range1[7].val = 2u;
range1[8].key = 6u;
range1[8].val = 3u;
range1[9].key = 6u;
range1[9].val = 4u;
range1[10].key = 6u;
range1[10].val = 5u;
order_perf_type out[20];
out[0].key = 998;
out[0].val = 999;
order_perf_type * r =
boost::movelib::set_unique_difference(range1, range1+11, range2, range2+10, out, order_type_less());
BOOST_TEST(&out[0] == r);
BOOST_TEST(out[0].key == 998);
BOOST_TEST(out[0].val == 999);
}
void test_set_unique_difference_range1_unique()
{
order_perf_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_perf_type range1[7];
range1[0].key = 1u;
range1[0].val = 1u;
range1[1].key = 3u;
range1[1].val = 1u;
range1[2].key = 3u;
range1[2].val = 2u;
range1[3].key = 5u;
range1[3].val = 1u;
range1[4].key = 7u;
range1[4].val = 1u;
range1[5].key = 7u;
range1[5].val = 2u;
range1[6].key = 7u;
range1[6].val = 3u;
order_perf_type out[20];
out[4].key = 998;
out[4].val = 999;
order_perf_type * r =
boost::movelib::set_unique_difference(range1, range1+7, range2, range2+10, out, order_type_less());
BOOST_TEST(&out[4] == r);
BOOST_TEST(out[0].key == 1u);
BOOST_TEST(out[0].val == 1u);
BOOST_TEST(out[1].key == 3u);
BOOST_TEST(out[1].val == 1u);
BOOST_TEST(out[2].key == 5u);
BOOST_TEST(out[2].val == 1u);
BOOST_TEST(out[3].key == 7u);
BOOST_TEST(out[3].val == 1u);
BOOST_TEST(out[4].key == 998);
BOOST_TEST(out[4].val == 999);
}
///////////////////////////////////
//
// inplace_set_unique_difference
//
///////////////////////////////////
void test_inplace_set_unique_difference_normal()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[4];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 1u;
range1[1].val = 1u;
range1[2].key = 3u;
range1[2].val = 1u;
range1[3].key = 4u;
range1[3].val = 1u;
order_move_type *ret = boost::movelib::inplace_set_unique_difference(range1, range1+4, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+2);
BOOST_TEST(range1[0].key == 1u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 3u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == order_move_type::moved_assign_mark);
BOOST_TEST(range1[2].val == order_move_type::moved_assign_mark);
}
void test_inplace_set_unique_difference_range1_repeated()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[5];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 2u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 6u;
range1[3].val = 1u;
range1[4].key = order_move_type::moved_assign_mark;
range1[4].val = order_move_type::moved_assign_mark;
order_move_type *ret = boost::movelib::inplace_set_unique_difference(range1, range1+4, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+0);
BOOST_TEST(range1[0].key == 0u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 2u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == 4u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[3].key == 6u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[4].key == order_move_type::moved_assign_mark);
BOOST_TEST(range1[4].val == order_move_type::moved_assign_mark);
}
void test_inplace_set_unique_difference_range1_unique()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[9];
range1[0].key = 1u;
range1[0].val = 1u;
range1[1].key = 1u;
range1[1].val = 2u;
range1[2].key = 3u;
range1[2].val = 1u;
range1[3].key = 3u;
range1[3].val = 2u;
range1[4].key = 5u;
range1[4].val = 1u;
range1[5].key = 7u;
range1[5].val = 1u;
range1[6].key = 7u;
range1[6].val = 2u;
range1[7].key = 7u;
range1[7].val = 3u;
range1[8].val = 3u;
range1[8].key = order_move_type::moved_assign_mark;
range1[8].val = order_move_type::moved_assign_mark;
order_move_type *ret =
boost::movelib::inplace_set_unique_difference(range1, range1+8, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+4);
BOOST_TEST(range1[0].key == 1u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 3u);
BOOST_TEST(range1[1].val == 1u);
BOOST_TEST(range1[2].key == 5u);
BOOST_TEST(range1[3].val == 1u);
BOOST_TEST(range1[3].key == 7u);
BOOST_TEST(range1[3].val == 1u);
}
void test_inplace_set_unique_difference_range1_unique_long()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[22];
for(std::size_t i = 0; i != sizeof(range1)/sizeof(*range1); ++i){
range1[i].key = (i/2)*2+1;
range1[i].val = i%2;
}
order_move_type *ret =
boost::movelib::inplace_set_unique_difference(range1, range1+22, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+11);
for(std::size_t i = 0; i != 11; ++i){
BOOST_TEST(range1[i].key == i*2+1);
BOOST_TEST(range1[i].val == 0u);
}
}
void test_inplace_set_unique_difference_range1_same_start()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[6];
range1[0].key = 0u;
range1[0].val = 1u;
range1[1].key = 2u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 4u;
range1[3].val = 2u;
range1[4].key = 5u;
range1[4].val = 1u;
range1[5].key = 7u;
range1[5].val = 1u;
order_move_type *ret =
boost::movelib::inplace_set_unique_difference(range1, range1+6, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+2);
BOOST_TEST(range1[0].key == 5u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 7u);
BOOST_TEST(range1[1].val == 1u);
}
void test_inplace_set_unique_difference_range1_same_end()
{
order_move_type range2[10];
for(std::size_t i = 0; i != sizeof(range2)/sizeof(*range2); ++i){
range2[i].key = i*2;
range2[i].val = 0u;
}
order_move_type range1[8];
range1[0].key = 1u;
range1[0].val = 1u;
range1[1].key = 3u;
range1[1].val = 1u;
range1[2].key = 4u;
range1[2].val = 1u;
range1[3].key = 4u;
range1[3].val = 2u;
range1[4].key = 6u;
range1[4].val = 1u;
range1[5].key = 8u;
range1[5].val = 1u;
range1[6].key = 8u;
range1[6].val = 2u;
range1[7].key = 8u;
range1[7].val = 3u;
order_move_type *ret =
boost::movelib::inplace_set_unique_difference(range1, range1+8, range2, range2+10, order_type_less());
BOOST_TEST(ret == range1+2);
BOOST_TEST(range1[0].key == 1u);
BOOST_TEST(range1[0].val == 1u);
BOOST_TEST(range1[1].key == 3u);
BOOST_TEST(range1[1].val == 1u);
}
int main()
{
//set_difference
test_set_difference_normal();
test_set_difference_range1_repeated();
test_set_difference_range1_unique();
//inplace_set_difference
test_inplace_set_difference_normal();
test_inplace_set_difference_range1_repeated();
test_inplace_set_difference_range1_unique();
test_inplace_set_difference_range1_unique_long();
test_inplace_set_difference_range1_same_start();
test_inplace_set_difference_range1_same_end();
//set_unique_difference
test_set_unique_difference_normal();
test_set_unique_difference_range1_repeated();
test_set_unique_difference_range1_unique();
//inplace_set_unique_difference
test_inplace_set_unique_difference_normal();
test_inplace_set_unique_difference_range1_repeated();
test_inplace_set_unique_difference_range1_unique();
test_inplace_set_unique_difference_range1_unique_long();
test_inplace_set_unique_difference_range1_same_start();
test_inplace_set_unique_difference_range1_same_end();
return boost::report_errors();
}

View File

@@ -0,0 +1,78 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
// 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.
//
//////////////////////////////////////////////////////////////////////////////
// move
#include <boost/move/algorithm.hpp>
#include <boost/move/iterator.hpp>
// container
#include <boost/container/deque.hpp>
#include <boost/container/list.hpp>
#include <boost/container/stable_vector.hpp>
#include "../example/movable.hpp"
template<class Container>
int move_test()
{
bool use_move_iterator = false;
bool done = false;
while(!done){
//Default construct 10 movable objects
Container v(10);
//Test default constructed value
if(v.begin()->moved()){
return 1;
}
//Move values
Container v2;
if(use_move_iterator){
::boost::copy_or_move( boost::make_move_iterator(v.begin())
, boost::make_move_iterator(v.end())
, boost::back_move_inserter(v2));
}
else{
std::copy(v.begin(), v.end(), boost::back_move_inserter(v2));
}
//Test values have been moved
if(!v.begin()->moved()){
return 1;
}
if(v2.size() != 10){
return 1;
}
if(v2.begin()->moved()){
return 1;
}
done = use_move_iterator;
use_move_iterator = true;
}
return 0;
}
int main()
{
namespace bc = ::boost::container;
if(move_test< bc::vector<movable> >()){
return 1;
}
if(move_test< bc::list<movable> >()){
return 1;
}
if(move_test< bc::stable_vector<movable> >()){
return 1;
}
return 0;
}

View File

@@ -0,0 +1,331 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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.
//
//////////////////////////////////////////////////////////////////////////////
//#define BOOST_MOVE_ADAPTIVE_SORT_STATS
//#define BOOST_MOVE_ADAPTIVE_SORT_STATS_LEVEL 2
#include <algorithm> //std::inplace_merge
#include <cstdio> //std::printf
#include <iostream> //std::cout
#include <boost/container/vector.hpp> //boost::container::vector
#include <boost/config.hpp>
#include <cstdlib>
#include <boost/move/unique_ptr.hpp>
#include <boost/move/detail/nsec_clock.hpp>
#include <boost/move/detail/force_ptr.hpp>
#include "order_type.hpp"
#include "random_shuffle.hpp"
using boost::move_detail::cpu_timer;
using boost::move_detail::nanosecond_type;
void print_stats(const char *str, boost::ulong_long_type element_count)
{
std::printf( "%sCmp:%8.04f Cpy:%9.04f\n", str
, double(order_perf_type::num_compare)/double(element_count)
, double(order_perf_type::num_copy)/double(element_count));
}
#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(boost::container::vector<T> &elements, std::size_t L, std::size_t NK, Compare comp)
{
elements.resize(L);
boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[NK ? NK : L]);
std::srand(0);
for (std::size_t i = 0; i < (NK ? NK : L); ++i) {
key_reps[i] = 0;
}
for (std::size_t i = 0; i < L; ++i) {
std::size_t key = NK ? (i % NK) : i;
elements[i].key = key;
}
::random_shuffle(elements.data(), elements.data() + L);
::random_shuffle(elements.data(), elements.data() + L);
for (std::size_t i = 0; i < L; ++i) {
elements[i].val = key_reps[elements[i].key]++;
}
std::size_t split_count = L / 2;
std::stable_sort(elements.data(), elements.data() + split_count, comp);
std::stable_sort(elements.data() + split_count, elements.data() + L, comp);
return split_count;
}
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, boost::move_detail::force_ptr<T*>(mem.get()), BufLen);
}
template<class T, class Compare>
void std_like_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::merge_adaptive_ONlogN(elements, mid, last, comp, boost::move_detail::force_ptr<T*>(mem.get()), BufLen);
}
enum AlgoType
{
StdMerge,
AdaptMerge,
SqrtHAdaptMerge,
SqrtAdaptMerge,
Sqrt2AdaptMerge,
QuartAdaptMerge,
StdInplaceMerge,
StdSqrtHAdaptMerge,
StdSqrtAdaptMerge,
StdSqrt2AdaptMerge,
StdQuartAdaptMerge,
MaxMerge
};
const char *AlgoNames [] = { "StdMerge "
, "AdaptMerge "
, "SqrtHAdaptMerge "
, "SqrtAdaptMerge "
, "Sqrt2AdaptMerge "
, "QuartAdaptMerge "
, "StdInplaceMerge "
, "StdSqrtHAdaptMerge "
, "StdSqrtAdaptMerge "
, "StdSqrt2AdaptMerge "
, "StdQuartAdaptMerge "
};
BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxMerge);
template<class T>
bool measure_algo(T *elements, std::size_t element_count, std::size_t split_pos, std::size_t alg, nanosecond_type &prev_clock)
{
std::printf("%s ", AlgoNames[alg]);
order_perf_type::num_compare=0;
order_perf_type::num_copy=0;
order_perf_type::num_elements = element_count;
cpu_timer timer;
timer.resume();
switch(alg)
{
case StdMerge:
std::inplace_merge(elements, elements+split_pos, elements+element_count, order_type_less());
break;
case AdaptMerge:
boost::movelib::adaptive_merge(elements, elements+split_pos, elements+element_count, order_type_less());
break;
case SqrtHAdaptMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
break;
case SqrtAdaptMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case Sqrt2AdaptMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case QuartAdaptMerge:
adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
, (element_count)/4+1);
break;
case StdInplaceMerge:
boost::movelib::merge_bufferless_ONlogN(elements, elements+split_pos, elements+element_count, order_type_less());
break;
case StdSqrtHAdaptMerge:
std_like_adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
break;
case StdSqrtAdaptMerge:
std_like_adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case StdSqrt2AdaptMerge:
std_like_adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case StdQuartAdaptMerge:
std_like_adaptive_merge_buffered( elements, elements+split_pos, elements+element_count, order_type_less()
, (element_count)/4+1);
break;
}
timer.stop();
if(order_perf_type::num_elements == element_count){
std::printf(" Tmp Ok ");
} else{
std::printf(" Tmp KO ");
}
nanosecond_type new_clock = timer.elapsed().wall;
//std::cout << "Cmp:" << order_perf_type::num_compare << " Cpy:" << order_perf_type::num_copy; //for old compilers without ll size argument
std::printf("Cmp:%8.04f Cpy:%9.04f", double(order_perf_type::num_compare)/double(element_count), double(order_perf_type::num_copy)/double(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 = is_order_type_ordered(elements, element_count, true);
return res;
}
template<class T>
bool measure_all(std::size_t L, std::size_t NK)
{
boost::container::vector<T> original_elements, elements;
std::size_t split_pos = generate_elements(original_elements, L, NK, order_type_less());
std::printf("\n - - N: %u, NK: %u - -\n", (unsigned)L, (unsigned)NK);
nanosecond_type prev_clock = 0;
nanosecond_type back_clock;
bool res = true;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, StdMerge, prev_clock);
back_clock = prev_clock;
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, QuartAdaptMerge, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, StdQuartAdaptMerge, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, Sqrt2AdaptMerge, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, StdSqrt2AdaptMerge, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, SqrtAdaptMerge, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, StdSqrtAdaptMerge, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, SqrtHAdaptMerge, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, StdSqrtHAdaptMerge, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos, AdaptMerge, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, split_pos,StdInplaceMerge, prev_clock);
//
if (!res)
std::abort();
return res;
}
//Undef it to run the long test
#define BENCH_MERGE_SHORT
#define BENCH_SORT_UNIQUE_VALUES
int main()
{
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(101,1);
measure_all<order_perf_type>(101,5);
measure_all<order_perf_type>(101,7);
measure_all<order_perf_type>(101,31);
#endif
measure_all<order_perf_type>(101,0);
//
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(1101,1);
measure_all<order_perf_type>(1001,7);
measure_all<order_perf_type>(1001,31);
measure_all<order_perf_type>(1001,127);
measure_all<order_perf_type>(1001,511);
#endif
measure_all<order_perf_type>(1001,0);
//
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(10001,65);
measure_all<order_perf_type>(10001,255);
measure_all<order_perf_type>(10001,1023);
measure_all<order_perf_type>(10001,4095);
#endif
measure_all<order_perf_type>(10001,0);
//
#if defined(NDEBUG)
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(100001,511);
measure_all<order_perf_type>(100001,2047);
measure_all<order_perf_type>(100001,8191);
measure_all<order_perf_type>(100001,32767);
#endif
measure_all<order_perf_type>(100001,0);
//
#if !defined(BENCH_MERGE_SHORT)
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(1000001, 8192);
measure_all<order_perf_type>(1000001, 32768);
measure_all<order_perf_type>(1000001, 131072);
measure_all<order_perf_type>(1000001, 524288);
#endif
measure_all<order_perf_type>(1000001,0);
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(10000001, 65536);
measure_all<order_perf_type>(10000001, 262144);
measure_all<order_perf_type>(10000001, 1048576);
measure_all<order_perf_type>(10000001, 4194304);
#endif
measure_all<order_perf_type>(10000001,0);
#endif //#ifndef BENCH_MERGE_SHORT
#endif //#ifdef NDEBUG
return 0;
}

View File

@@ -0,0 +1,380 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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/container/vector.hpp> //boost::container::vector
#include <boost/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/move/detail/nsec_clock.hpp>
#include <boost/move/detail/force_ptr.hpp>
#include <cstdlib>
using boost::move_detail::cpu_timer;
using boost::move_detail::nanosecond_type;
#include "order_type.hpp"
#include "random_shuffle.hpp"
//#define BOOST_MOVE_ADAPTIVE_SORT_STATS
//#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
void print_stats(const char *str, boost::ulong_long_type element_count)
{
std::printf( "%sCmp:%7.03f Cpy:%8.03f\n", str
, double(order_perf_type::num_compare)/double(element_count)
, double(order_perf_type::num_copy)/double(element_count) );
}
#include <boost/move/algo/adaptive_sort.hpp>
#include <boost/move/algo/detail/merge_sort.hpp>
#include <boost/move/algo/detail/pdqsort.hpp>
#include <boost/move/algo/detail/heap_sort.hpp>
#include <boost/move/core.hpp>
template<class T>
void generate_elements(boost::container::vector<T> &elements, std::size_t L, std::size_t NK)
{
elements.resize(L);
boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[NK ? NK : L]);
std::srand(0);
for (std::size_t i = 0; i < (NK ? NK : L); ++i) {
key_reps[i] = 0;
}
for (std::size_t i = 0; i < L; ++i) {
std::size_t key = NK ? (i % NK) : i;
elements[i].key = key;
}
::random_shuffle(elements.data(), elements.data() + L);
::random_shuffle(elements.data(), elements.data() + L);
for (std::size_t i = 0; i < L; ++i) {
elements[i].val = key_reps[elements[i].key]++;
}
}
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, boost::move_detail::force_ptr<T*>(mem.get()), BufLen);
}
template<class T, class Compare>
void std_like_adaptive_stable_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::stable_sort_adaptive_ONlogN2(elements, elements + element_count, comp, boost::move_detail::force_ptr<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, boost::move_detail::force_ptr<T*>(mem.get()));
}
enum AlgoType
{
MergeSort,
StableSort,
PdQsort,
StdSort,
AdaptiveSort,
SqrtHAdaptiveSort,
SqrtAdaptiveSort,
Sqrt2AdaptiveSort,
QuartAdaptiveSort,
InplaceStableSort,
StdSqrtHAdpSort,
StdSqrtAdpSort,
StdSqrt2AdpSort,
StdQuartAdpSort,
SlowStableSort,
HeapSort,
MaxSort
};
const char *AlgoNames [] = { "MergeSort "
, "StableSort "
, "PdQsort "
, "StdSort "
, "AdaptSort "
, "SqrtHAdaptSort "
, "SqrtAdaptSort "
, "Sqrt2AdaptSort "
, "QuartAdaptSort "
, "InplStableSort "
, "StdSqrtHAdpSort"
, "StdSqrtAdpSort "
, "StdSqrt2AdpSort"
, "StdQuartAdpSort"
, "SlowSort "
, "HeapSort "
};
BOOST_STATIC_ASSERT((sizeof(AlgoNames)/sizeof(*AlgoNames)) == MaxSort);
template<class T>
bool measure_algo(T *elements, std::size_t element_count, std::size_t alg, nanosecond_type &prev_clock)
{
std::printf("%s ", AlgoNames[alg]);
order_perf_type::num_compare=0;
order_perf_type::num_copy=0;
order_perf_type::num_elements = element_count;
cpu_timer timer;
timer.resume();
switch(alg)
{
case MergeSort:
merge_sort_buffered(elements, element_count, order_type_less());
break;
case StableSort:
std::stable_sort(elements,elements+element_count,order_type_less());
break;
case PdQsort:
boost::movelib::pdqsort(elements,elements+element_count,order_type_less());
break;
case StdSort:
std::sort(elements,elements+element_count,order_type_less());
break;
case AdaptiveSort:
boost::movelib::adaptive_sort(elements, elements+element_count, order_type_less());
break;
case SqrtHAdaptiveSort:
adaptive_sort_buffered( elements, element_count, order_type_less()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
break;
case SqrtAdaptiveSort:
adaptive_sort_buffered( elements, element_count, order_type_less()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case Sqrt2AdaptiveSort:
adaptive_sort_buffered( elements, element_count, order_type_less()
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case QuartAdaptiveSort:
adaptive_sort_buffered( elements, element_count, order_type_less()
, (element_count-1)/4+1);
break;
case InplaceStableSort:
boost::movelib::inplace_stable_sort(elements, elements+element_count, order_type_less());
break;
case StdSqrtHAdpSort:
std_like_adaptive_stable_sort_buffered( elements, element_count, order_type_less()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count)/2+1);
break;
case StdSqrtAdpSort:
std_like_adaptive_stable_sort_buffered( elements, element_count, order_type_less()
, boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case StdSqrt2AdpSort:
std_like_adaptive_stable_sort_buffered( elements, element_count, order_type_less()
, 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count));
break;
case StdQuartAdpSort:
std_like_adaptive_stable_sort_buffered( elements, element_count, order_type_less()
, (element_count-1)/4+1);
break;
case SlowStableSort:
boost::movelib::detail_adaptive::slow_stable_sort(elements, elements+element_count, order_type_less());
break;
case HeapSort:
boost::movelib::heap_sort(elements, elements+element_count, order_type_less());
boost::movelib::heap_sort((order_move_type*)0, (order_move_type*)0, order_type_less());
break;
}
timer.stop();
if(order_perf_type::num_elements == element_count){
std::printf(" Tmp Ok ");
} else{
std::printf(" Tmp KO ");
}
nanosecond_type new_clock = timer.elapsed().wall;
//std::cout << "Cmp:" << order_perf_type::num_compare << " Cpy:" << order_perf_type::num_copy; //for old compilers without ll size argument
std::printf("Cmp:%7.03f Cpy:%8.03f", double(order_perf_type::num_compare)/double(element_count), double(order_perf_type::num_copy)/double(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 = is_order_type_ordered(elements, element_count, alg != HeapSort && alg != PdQsort && alg != StdSort);
return res;
}
template<class T>
bool measure_all(std::size_t L, std::size_t NK)
{
boost::container::vector<T> original_elements, elements;
generate_elements(original_elements, L, NK);
std::printf("\n - - N: %u, NK: %u - -\n", (unsigned)L, (unsigned)NK);
nanosecond_type prev_clock = 0;
nanosecond_type back_clock;
bool res = true;
elements = original_elements;
res = res && measure_algo(elements.data(), L,MergeSort, prev_clock);
back_clock = prev_clock;
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,StableSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,PdQsort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,StdSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,HeapSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,QuartAdaptiveSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, StdQuartAdpSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,Sqrt2AdaptiveSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, StdSqrt2AdpSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,SqrtAdaptiveSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, StdSqrtAdpSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,SqrtHAdaptiveSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L, StdSqrtHAdpSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,AdaptiveSort, prev_clock);
//
prev_clock = back_clock;
elements = original_elements;
res = res && measure_algo(elements.data(), L,InplaceStableSort, prev_clock);
//
//prev_clock = back_clock;
//elements = original_elements;
//res = res && measure_algo(elements.data(), L,SlowStableSort, prev_clock);
if(!res)
std::abort();
return res;
}
//Undef it to run the long test
#define BENCH_SORT_SHORT
#define BENCH_SORT_UNIQUE_VALUES
int main()
{
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(101,1);
measure_all<order_perf_type>(101,7);
measure_all<order_perf_type>(101,31);
#endif
measure_all<order_perf_type>(101,0);
//
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(1101,1);
measure_all<order_perf_type>(1001,7);
measure_all<order_perf_type>(1001,31);
measure_all<order_perf_type>(1001,127);
measure_all<order_perf_type>(1001,511);
#endif
measure_all<order_perf_type>(1001,0);
//
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(10001,65);
measure_all<order_perf_type>(10001,255);
measure_all<order_perf_type>(10001,1023);
measure_all<order_perf_type>(10001,4095);
#endif
measure_all<order_perf_type>(10001,0);
//
#ifdef NDEBUG
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(100001,511);
measure_all<order_perf_type>(100001,2047);
measure_all<order_perf_type>(100001,8191);
measure_all<order_perf_type>(100001,32767);
#endif
measure_all<order_perf_type>(100001,0);
//
#ifndef BENCH_SORT_SHORT
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(1000001, 8192);
measure_all<order_perf_type>(1000001, 32768);
measure_all<order_perf_type>(1000001, 131072);
measure_all<order_perf_type>(1000001, 524288);
#endif
measure_all<order_perf_type>(1000001,0);
#ifndef BENCH_SORT_UNIQUE_VALUES
measure_all<order_perf_type>(10000001, 65536);
measure_all<order_perf_type>(10000001, 262144);
measure_all<order_perf_type>(10000001, 1048576);
measure_all<order_perf_type>(10000001, 4194304);
#endif
measure_all<order_perf_type>(1000001,0);
#endif //#ifndef BENCH_SORT_SHORT
#endif //NDEBUG
//measure_all<order_perf_type>(100000001,0);
return 0;
}

View File

@@ -0,0 +1,116 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/move/utility_core.hpp>
#include <boost/utility/enable_if.hpp>
#include "../example/movable.hpp"
#include "../example/copymovable.hpp"
#include <cstdio>
class non_movable
{
public:
non_movable()
{}
};
template<class MaybeRvalue>
void catch_test(BOOST_RV_REF(MaybeRvalue)
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
,typename ::boost::enable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0
#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
)
{}
template<class MaybeRvalue>
void catch_test(BOOST_COPY_ASSIGN_REF(MaybeRvalue)
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
,typename ::boost::enable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0
#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
)
{}
template<class MaybeRvalue>
void catch_test(MaybeRvalue &
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
,typename ::boost::enable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0
#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
)
{}
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class MaybeRvalue>
void catch_test(const MaybeRvalue&
,typename ::boost::disable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0
)
{}
#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
movable create_movable()
{ return movable(); }
copy_movable create_copy_movable()
{ return copy_movable(); }
non_movable create_non_movable()
{ return non_movable(); }
void catch_test()
{
movable m;
const movable constm;
catch_test<movable>(boost::move(m));
#ifdef BOOST_CATCH_CONST_RLVALUE
catch_test<movable>(create_movable());
#endif
catch_test<movable>(m);
catch_test<movable>(constm);
copy_movable cm;
const copy_movable constcm;
catch_test<copy_movable>(boost::move(cm));
catch_test<copy_movable>(create_copy_movable());
catch_test<copy_movable>(cm);
catch_test<copy_movable>(constcm);
non_movable nm;
const non_movable constnm;
catch_test<non_movable>(boost::move(nm));
catch_test<non_movable>(create_non_movable());
catch_test<non_movable>(nm);
catch_test<non_movable>(constnm);
}
template<class MaybeMovableOnly, class MaybeRvalue>
void function_construct(BOOST_FWD_REF(MaybeRvalue) x)
{
//Moves in case Convertible is boost::rv<movable> copies otherwise
//For C++0x perfect forwarding
MaybeMovableOnly m(boost::forward<MaybeRvalue>(x));
}
void forward_test()
{
movable m;
function_construct<movable>(boost::move(m));
// non_movable nm;
// function_construct<non_movable>(boost::move(nm));
// const non_movable cnm;
// function_construct<non_movable>(cnm);
}
int main()
{
catch_test();
forward_test();
return 0;
}

View File

@@ -0,0 +1,414 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/move/utility_core.hpp>
#include <boost/move/detail/meta_utils.hpp>
#include <cassert>
#include <new>
#include <boost/move/detail/move_helpers.hpp>
enum ConstructionType { Copied, Moved, Other };
class conversion_source
{
public:
conversion_source(){}
operator int() const { return 0; }
};
class conversion_target
{
ConstructionType c_type_;
public:
conversion_target(conversion_source)
{ c_type_ = Other; }
conversion_target()
{ c_type_ = Other; }
conversion_target(const conversion_target &)
{ c_type_ = Copied; }
ConstructionType construction_type() const
{ return c_type_; }
};
class conversion_target_copymovable
{
ConstructionType c_type_;
BOOST_COPYABLE_AND_MOVABLE(conversion_target_copymovable)
public:
conversion_target_copymovable()
{ c_type_ = Other; }
conversion_target_copymovable(conversion_source)
{ c_type_ = Other; }
conversion_target_copymovable(const conversion_target_copymovable &)
{ c_type_ = Copied; }
conversion_target_copymovable(BOOST_RV_REF(conversion_target_copymovable) )
{ c_type_ = Moved; }
conversion_target_copymovable &operator=(BOOST_RV_REF(conversion_target_copymovable) )
{ c_type_ = Moved; return *this; }
conversion_target_copymovable &operator=(BOOST_COPY_ASSIGN_REF(conversion_target_copymovable) )
{ c_type_ = Copied; return *this; }
ConstructionType construction_type() const
{ return c_type_; }
};
class conversion_target_movable
{
ConstructionType c_type_;
BOOST_MOVABLE_BUT_NOT_COPYABLE(conversion_target_movable)
public:
conversion_target_movable()
{ c_type_ = Other; }
conversion_target_movable(conversion_source)
{ c_type_ = Other; }
conversion_target_movable(BOOST_RV_REF(conversion_target_movable) )
{ c_type_ = Moved; }
conversion_target_movable &operator=(BOOST_RV_REF(conversion_target_movable) )
{ c_type_ = Moved; return *this; }
ConstructionType construction_type() const
{ return c_type_; }
};
template<class T>
class container
{
T *storage_;
public:
struct const_iterator{};
struct iterator : const_iterator{};
container()
: storage_(0)
{}
~container()
{ delete storage_; }
container(const container &c)
: storage_(c.storage_ ? new T(*c.storage_) : 0)
{}
container &operator=(const container &c)
{
if(storage_){
delete storage_;
storage_ = 0;
}
storage_ = c.storage_ ? new T(*c.storage_) : 0;
return *this;
}
BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
template <class Iterator>
iterator insert(Iterator, Iterator){ return iterator(); }
ConstructionType construction_type() const
{ return construction_type_impl
(typename ::boost::move_detail::integral_constant<bool, ::boost::move_detail::is_class_or_union<T>::value>());
}
ConstructionType construction_type_impl(::boost::move_detail::true_type) const
{ return storage_->construction_type(); }
ConstructionType construction_type_impl(::boost::move_detail::false_type) const
{ return Copied; }
iterator begin() const { return iterator(); }
private:
template<class U>
void priv_construct(BOOST_MOVE_CATCH_FWD(U) x)
{
if(storage_){
delete storage_;
storage_ = 0;
}
storage_ = new T(::boost::forward<U>(x));
}
template<class U>
void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
{ priv_construct(::boost::forward<U>(x)); }
template<class U>
iterator priv_insert(const_iterator, BOOST_MOVE_CATCH_FWD(U) x)
{ priv_construct(::boost::forward<U>(x)); return iterator(); }
};
class recursive_container
{
BOOST_COPYABLE_AND_MOVABLE(recursive_container)
public:
recursive_container()
{}
recursive_container(const recursive_container &c)
: container_(c.container_)
{}
recursive_container(BOOST_RV_REF(recursive_container) c)
: container_(::boost::move(c.container_))
{}
recursive_container & operator =(BOOST_COPY_ASSIGN_REF(recursive_container) c)
{
container_= c.container_;
return *this;
}
recursive_container & operator =(BOOST_RV_REF(recursive_container) c)
{
container_= ::boost::move(c.container_);
return *this;
}
container<recursive_container> container_;
friend bool operator< (const recursive_container &a, const recursive_container &b)
{ return &a < &b; }
};
int main()
{
conversion_target_movable a;
conversion_target_movable b(::boost::move(a));
{
container<conversion_target> c;
{
conversion_target x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
const conversion_target x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
c.push_back(conversion_target());
assert(c.construction_type() == Copied);
c.insert(c.begin(), conversion_target());
assert(c.construction_type() == Copied);
}
{
conversion_source x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
const conversion_source x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
c.push_back(conversion_source());
assert(c.construction_type() == Copied);
c.insert(c.begin(), conversion_source());
assert(c.construction_type() == Copied);
}
}
{
container<conversion_target_copymovable> c;
{
conversion_target_copymovable x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
const conversion_target_copymovable x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
c.push_back(conversion_target_copymovable());
assert(c.construction_type() == Moved);
c.insert(c.begin(), conversion_target_copymovable());
assert(c.construction_type() == Moved);
}
{
conversion_source x;
c.push_back(x);
assert(c.construction_type() == Moved);
c.insert(c.begin(), x);
assert(c.construction_type() == Moved);
}
{
const conversion_source x;
c.push_back(x);
assert(c.construction_type() == Moved);
c.insert(c.begin(), x);
assert(c.construction_type() == Moved);
}
{
c.push_back(conversion_source());
assert(c.construction_type() == Moved);
c.insert(c.begin(), conversion_source());
assert(c.construction_type() == Moved);
}
}
{
container<conversion_target_movable> c;
//This should not compile
//{
// conversion_target_movable x;
// c.push_back(x);
// assert(c.construction_type() == Copied);
//}
//{
// const conversion_target_movable x;
// c.push_back(x);
// assert(c.construction_type() == Copied);
//}
{
c.push_back(conversion_target_movable());
assert(c.construction_type() == Moved);
c.insert(c.begin(), conversion_target_movable());
assert(c.construction_type() == Moved);
}
{
conversion_source x;
c.push_back(x);
assert(c.construction_type() == Moved);
c.insert(c.begin(), x);
assert(c.construction_type() == Moved);
}
{
const conversion_source x;
c.push_back(x);
assert(c.construction_type() == Moved);
c.insert(c.begin(), x);
assert(c.construction_type() == Moved);
}
{
c.push_back(conversion_source());
assert(c.construction_type() == Moved);
c.insert(c.begin(), conversion_source());
assert(c.construction_type() == Moved);
}
}
{
container<int> c;
{
int x = 0;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), c.construction_type());
assert(c.construction_type() == Copied);
}
{
const int x = 0;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
c.push_back(int(0));
assert(c.construction_type() == Copied);
c.insert(c.begin(), int(0));
assert(c.construction_type() == Copied);
}
{
conversion_source x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
const conversion_source x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
c.push_back(conversion_source());
assert(c.construction_type() == Copied);
c.insert(c.begin(), conversion_source());
assert(c.construction_type() == Copied);
}
//c.insert(c.begin(), c.begin());
}
{
container<int> c;
{
int x = 0;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), c.construction_type());
assert(c.construction_type() == Copied);
}
{
const int x = 0;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
c.push_back(int(0));
assert(c.construction_type() == Copied);
c.insert(c.begin(), int(0));
assert(c.construction_type() == Copied);
}
{
conversion_source x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
const conversion_source x;
c.push_back(x);
assert(c.construction_type() == Copied);
c.insert(c.begin(), x);
assert(c.construction_type() == Copied);
}
{
c.push_back(conversion_source());
assert(c.construction_type() == Copied);
c.insert(c.begin(), conversion_source());
assert(c.construction_type() == Copied);
}
c.insert(c.begin(), c.begin());
}
{
recursive_container c;
recursive_container internal;
c.container_.insert(c.container_.begin(), recursive_container());
c.container_.insert(c.container_.begin(), internal);
c.container_.insert(c.container_.begin(), c.container_.begin());
}
return 0;
}

View File

@@ -0,0 +1,175 @@
// Copyright David Abrahams 2009. 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)
#include <iostream>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/ignore_unused.hpp>
#ifdef NO_MOVE
# undef BOOST_COPY_ASSIGN_REF
# define BOOST_COPY_ASSIGN_REF(X) X const&
# undef BOOST_COPYABLE_AND_MOVABLE
# define BOOST_COPYABLE_AND_MOVABLE(X)
# define MOVE(x) (x)
#else
#include <boost/move/utility_core.hpp>
# define MOVE(x) boost::move(x)
#endif
struct X
{
X() : id(instances++)
{
std::cout << "X" << id << ": construct\n";
}
X(X const& rhs) : id(instances++)
{
std::cout << "X" << id << ": <- " << "X" << rhs.id << ": **copy**\n";
++copies;
}
// This particular test doesn't exercise assignment, but for
// completeness:
X& operator=(BOOST_COPY_ASSIGN_REF(X) rhs)
{
std::cout << "X" << id << ": <- " << "X" << rhs.id << ": assign\n";
return *this;
}
#ifndef NO_MOVE
X& operator=(BOOST_RV_REF(X) rhs)
{
std::cout << "X" << id << ": <- " << "X" << rhs.id << ": move assign\n";
return *this;
}
X(BOOST_RV_REF(X) rhs) : id(instances++)
{
std::cout << "X" << id << ": <- " << "X" << rhs.id << ": ..move construct..\n";
++copies;
}
#endif
~X() { std::cout << "X" << id << ": destroy\n"; }
unsigned id;
static unsigned copies;
static unsigned instances;
BOOST_COPYABLE_AND_MOVABLE(X)
};
unsigned X::copies = 0;
unsigned X::instances = 0;
#define CHECK_COPIES( stmt, min, max, comment ) \
{ \
unsigned const old_copies = X::copies; \
\
std::cout << "\n" comment "\n" #stmt "\n===========\n"; \
{ \
stmt; \
} \
unsigned const n = X::copies - old_copies; \
volatile unsigned const minv(min), maxv(max); \
BOOST_TEST(n <= maxv); \
if (n > maxv) \
std::cout << "*** max is too low or compiler is buggy ***\n"; \
BOOST_TEST(n >= minv); \
if (n < minv) \
std::cout << "*** min is too high or compiler is buggy ***\n"; \
\
std::cout << "-----------\n" \
<< n << "/" << max \
<< " possible copies/moves made\n" \
<< max - n << "/" << max - min \
<< " possible elisions performed\n\n"; \
\
if (n > minv) \
std::cout << "*** " << n - min \
<< " possible elisions missed! ***\n"; \
}
struct trace
{
trace(char const* name)
: m_name(name)
{
std::cout << "->: " << m_name << "\n";
}
~trace()
{
std::cout << "<-: " << m_name << "\n";
}
char const* m_name;
};
void sink(X)
{
trace t("sink");
}
X nrvo_source()
{
trace t("nrvo_source");
X a;
return a;
}
X urvo_source()
{
trace t("urvo_source");
return X();
}
X identity(X a)
{
trace t("identity");
return a;
}
X lvalue_;
X& lvalue()
{
return lvalue_;
}
typedef X rvalue;
X ternary( bool y )
{
X a, b;
return MOVE(y?a:b);
}
int main(int argc, char* argv[])
{
::boost::ignore_unused(argv);
// Double parens prevent "most vexing parse"
CHECK_COPIES( X a(( lvalue() )), 1U, 1U, "Direct initialization from lvalue");
CHECK_COPIES( X a(( rvalue() )), 0U, 1U, "Direct initialization from rvalue");
CHECK_COPIES( X a = lvalue(), 1U, 1U, "Copy initialization from lvalue" );
CHECK_COPIES( X a = rvalue(), 0U, 1U, "Copy initialization from rvalue" );
CHECK_COPIES( sink( lvalue() ), 1U, 1U, "Pass lvalue by value" );
CHECK_COPIES( sink( rvalue() ), 0U, 1U, "Pass rvalue by value" );
CHECK_COPIES( nrvo_source(), 0U, 1U, "Named return value optimization (NRVO)" );
CHECK_COPIES( urvo_source(), 0U, 1U, "Unnamed return value optimization (URVO)" );
// Just to prove these things compose properly
CHECK_COPIES( X a(urvo_source()), 0U, 2U, "Return value used as ctor arg" );
// Expect to miss one possible elision here
CHECK_COPIES( identity( rvalue() ), 0U, 2U, "Return rvalue passed by value" );
// Expect to miss an elision in at least one of the following lines
CHECK_COPIES( X a = ternary( argc == 1000 ), 0U, 2U, "Return result of ternary operation" );
CHECK_COPIES( X a = ternary( argc != 1000 ), 0U, 2U, "Return result of ternary operation again" );
return boost::report_errors();
}

View File

@@ -0,0 +1,105 @@
//We need to declare:
//
//2 conversions: rv<T> & and const rv<T> &
//1 rv<T> & constructor: move constructor
//1 const rv<T> & constructor: copy constructor
//1 T & constructor: copy constructor
//
//Optimization:
//Since RVO is better than move-construction,
//avoid copy constructor overloading.
#include <boost/move/utility_core.hpp>
#include <iostream>
bool moved = false;
class obj
{
BOOST_COPYABLE_AND_MOVABLE(obj)
public:
obj()
{
std::cout << "constructing obj" << "\n";
}
~obj()
{}
obj(const obj &)
{
std::cout << "copy construct from const obj" << "\n";
}
// copy construct from movable object (non-const rvalue, explicitly moved lvalue)
obj(BOOST_RV_REF(obj))
{
std::cout << "move construct from movable rvalue" << "\n";
}
obj& operator =(BOOST_COPY_ASSIGN_REF(obj))
{
std::cout << "copy assign from const obj" << "\n";
return *this;
}
obj& operator =(BOOST_RV_REF(obj))
{
std::cout << "move assign from movable rvalue" << "\n";
return *this;
}
};
obj rvalue_func() { return obj(); }
const obj const_rvalue_func() { return obj(); }
obj& lvalue_func() { static obj o; return o; }
const obj& const_lvalue_func() { static obj o; return o; }
obj produce() { return obj(); }
void consume(obj){}
int main()
{
{ consume(produce()); }
{ obj o = produce(); }
{ obj o(produce()); }
{
obj o1(rvalue_func());
obj o2 = const_rvalue_func();
obj o3 = lvalue_func();
obj o4 = const_lvalue_func();
// can't explicitly move temporaries
//obj o5 = boost::move(rvalue_func());
obj o5;
//Maybe missed optimization: copied
o5 = rvalue_func();
//Explicit forward works OK and optimized
o5 = boost::forward<obj>(rvalue_func());
obj o7 = boost::move(lvalue_func());
obj o8 = boost::move(const_lvalue_func());
obj o;
o = rvalue_func();
o = const_rvalue_func();
o = lvalue_func();
o = const_lvalue_func();
// can't explicitly move temporaries
//o = boost::move(rvalue_func());
o = boost::forward<obj>(rvalue_func());
o = boost::move(const_rvalue_func());
o = boost::move(lvalue_func());
o = boost::move(const_lvalue_func());
}
return 0;
}
//We need to declare:
//
//2 conversions: rv<T> & and const rv<T> &
//1 rv<T> & constructor: move constructor
//1 const rv<T> & constructor: copy constructor
//1 T & constructor: copy constructor

View File

@@ -0,0 +1,283 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2016-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.
//
//////////////////////////////////////////////////////////////////////////////
//#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
#define BOOST_MOVE_ADAPTIVE_SORT_STATS
#include "order_type.hpp"
#include <iostream> //std::cout
#include <boost/config.hpp>
#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
#include <boost/move/core.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/move/make_unique.hpp>
#include <boost/move/detail/type_traits.hpp>
#include <boost/core/lightweight_test.hpp>
#include <cstddef>
const std::size_t BlockSize = 7u;
#if defined(BOOST_MSVC)
#pragma warning (disable : 4267)
#endif
const std::size_t left_merge = 0;
const std::size_t buf_merge = 1;
const std::size_t unbuf_merge= 2;
const std::size_t max_merge = 3;
template<class Op>
void alternating_test(
const std::size_t NumBlocksA,
const std::size_t NumBlocksB,
const std::size_t ExtraA,
const std::size_t ExtraB,
Op op)
{
using namespace boost::movelib::detail_adaptive;
const std::size_t DataSize = ExtraA + NumBlocksA*BlockSize + NumBlocksB*BlockSize + ExtraB;
const std::size_t KeySize = NumBlocksA + NumBlocksB + 1;
const std::size_t HdrSize = BlockSize + KeySize;
const std::size_t ArraySize = HdrSize + DataSize;
boost::movelib::unique_ptr<order_move_type[]> testarray(boost::movelib::make_unique<order_move_type[]>(ArraySize));
for(std::size_t szt_merge = 0; szt_merge != max_merge; ++szt_merge){
//Order keys
for (std::size_t szt_i = 0u; szt_i != KeySize; ++szt_i) {
testarray[szt_i].key = szt_i;
testarray[szt_i].val = std::size_t(-1);
}
//Order buffer
for (std::size_t szt_i = 0u; szt_i != BlockSize; ++szt_i) {
testarray[KeySize+szt_i].key = std::size_t(-1);
testarray[KeySize+szt_i].val = szt_i;
}
//Block A
std::size_t szt_k = 0;
for (std::size_t szt_i = 0u; szt_i != ExtraA; ++szt_i) {
testarray[HdrSize+szt_k].key = (szt_k/2)*2;
testarray[HdrSize+szt_k].val = szt_k & 1;
++szt_k;
}
for (std::size_t szt_b = 0u; szt_b != NumBlocksA; ++szt_b)
for (std::size_t szt_i = 0u; szt_i != BlockSize; ++szt_i) {
testarray[HdrSize+szt_k].key = (szt_k/2)*2;
testarray[HdrSize+szt_k].val = szt_k & 1;
++szt_k;
}
//Block B
std::size_t szt_l = 0;
for (std::size_t szt_b = 0u, szt_t = 0; szt_b != NumBlocksB; ++szt_b)
for (std::size_t szt_i = 0u; szt_i != BlockSize; ++szt_i, ++szt_t) {
testarray[HdrSize+szt_k].key = (szt_l/2)*2+1;
testarray[HdrSize+szt_k].val = szt_l & 1;
++szt_k;
++szt_l;
}
for (std::size_t szt_i = 0u; szt_i != ExtraB; ++szt_i) {
testarray[HdrSize+szt_k].key = (szt_l/2)*2+1;
testarray[HdrSize+szt_k].val = szt_l & 1;
++szt_k;
++szt_l;
}
if(szt_merge == left_merge){
//Merge Left
op_merge_blocks_left
( testarray.get(), order_type_less()
, testarray.get()+HdrSize, BlockSize, ExtraA, NumBlocksA, NumBlocksB, ExtraB
, order_type_less(), op );
BOOST_TEST( is_order_type_ordered(testarray.get()+KeySize, DataSize) );
BOOST_TEST( is_key(testarray.get(), KeySize) );
BOOST_TEST(( !boost::move_detail::is_same<Op, boost::movelib::swap_op>::value
|| is_buffer(testarray.get()+ KeySize+DataSize, BlockSize) ));
}
else if(szt_merge == buf_merge){
//Merge with buf
op_merge_blocks_with_buf
( testarray.get(), order_type_less()
, testarray.get()+HdrSize, BlockSize, ExtraA, NumBlocksA, NumBlocksB, ExtraB
, order_type_less(), op, testarray.get()+KeySize );
BOOST_TEST( is_order_type_ordered(testarray.get()+HdrSize, DataSize) );
BOOST_TEST( is_key(testarray.get(), KeySize) );
BOOST_TEST(( !boost::move_detail::is_same<Op, boost::movelib::swap_op>::value
|| is_buffer(testarray.get()+ KeySize, BlockSize) ));
}
else if(szt_merge == unbuf_merge){
//Merge Left
merge_blocks_bufferless
( testarray.get(), order_type_less()
, testarray.get()+HdrSize, BlockSize, ExtraA, NumBlocksA, NumBlocksB, ExtraB
, order_type_less());
BOOST_TEST( is_order_type_ordered(testarray.get()+HdrSize, DataSize) );
BOOST_TEST( is_key(testarray.get(), KeySize) );
BOOST_TEST(( !boost::move_detail::is_same<Op, boost::movelib::swap_op>::value
|| is_buffer(testarray.get()+ KeySize, BlockSize) ));
}
}
}
int main()
{
{
const std::size_t NumBlocksA = 3u;
const std::size_t NumBlocksB = 3u;
const std::size_t ExtraA = BlockSize/2;
const std::size_t ExtraB = ExtraA;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 3u;
const std::size_t NumBlocksB = 3u;
const std::size_t ExtraA = 0u;
const std::size_t ExtraB = BlockSize/2;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 3u;
const std::size_t NumBlocksB = 3u;
const std::size_t ExtraA = BlockSize/2;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 3u;
const std::size_t NumBlocksB = 3u;
const std::size_t ExtraA = 0;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 6u;
const std::size_t NumBlocksB = 3u;
const std::size_t ExtraA = BlockSize/2;
const std::size_t ExtraB = ExtraA;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 6u;
const std::size_t NumBlocksB = 3u;
const std::size_t ExtraA = BlockSize/2;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 3u;
const std::size_t NumBlocksB = 5u;
const std::size_t ExtraA = BlockSize/2;
const std::size_t ExtraB = ExtraA;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 3u;
const std::size_t NumBlocksB = 5u;
const std::size_t ExtraA = BlockSize/2;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 0u;
const std::size_t NumBlocksB = 0u;
const std::size_t ExtraA = 0;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 0u;
const std::size_t NumBlocksB = 0u;
const std::size_t ExtraA = BlockSize/2;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 0u;
const std::size_t NumBlocksB = 0u;
const std::size_t ExtraA = 0;
const std::size_t ExtraB = BlockSize/2;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
//
{
const std::size_t NumBlocksA = 0u;
const std::size_t NumBlocksB = 1u;
const std::size_t ExtraA = 0;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 1u;
const std::size_t NumBlocksB = 0u;
const std::size_t ExtraA = 0;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 1u;
const std::size_t NumBlocksB = 0u;
const std::size_t ExtraA = BlockSize/2;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 0u;
const std::size_t NumBlocksB = 1u;
const std::size_t ExtraA = BlockSize/2;
const std::size_t ExtraB = 0;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 1u;
const std::size_t NumBlocksB = 0u;
const std::size_t ExtraA = 0;
const std::size_t ExtraB = BlockSize/2;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
{
const std::size_t NumBlocksA = 0u;
const std::size_t NumBlocksB = 1u;
const std::size_t ExtraA = 0;
const std::size_t ExtraB = BlockSize/2;
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::move_op());
alternating_test(NumBlocksA, NumBlocksB, ExtraA, ExtraB, boost::movelib::swap_op());
}
return ::boost::report_errors();
}

View File

@@ -0,0 +1,181 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
// (C) Copyright Ion Gaztanaga 2009-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/utility_core.hpp>
#include <boost/core/ignore_unused.hpp>
#include "../example/movable.hpp"
#include "../example/copymovable.hpp"
#include <boost/static_assert.hpp>
movable function(movable m)
{
return movable(boost::move(m));
}
movable functionr(BOOST_RV_REF(movable) m)
{
return movable(boost::move(m));
}
movable function2(movable m)
{
return boost::move(m);
}
BOOST_RV_REF(movable) function2r(BOOST_RV_REF(movable) m)
{
return boost::move(m);
}
movable move_return_function2 ()
{
return movable();
}
movable move_return_function ()
{
movable m;
return (boost::move(m));
}
//Catch by value
void function_value(movable)
{}
//Catch by reference
void function_ref(const movable &)
{}
//Catch by reference
void function_ref(BOOST_RV_REF(movable))
{}
movable create_movable()
{ return movable(); }
template<class Type>
struct factory
{
Type operator()() const
{
Type t;
return BOOST_MOVE_RET(Type, t);
}
};
template<class Type>
struct factory<Type &>
{
static Type t;
Type &operator()() const
{
return BOOST_MOVE_RET(Type&, t);
}
};
template<class Type>
Type factory<Type&>::t;
template <class R, class F>
R factory_wrapper(F f)
{
// lock();
R r = f();
// unlock();
return BOOST_MOVE_RET(R, r);
}
int main()
{
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_STATIC_ASSERT((boost::has_nothrow_move<movable>::value == true));
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<copyable>::value == false));
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<copyable*>::value == false));
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<int>::value == false));
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<int&>::value == false));
BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled<int*>::value == false));
#endif
{
movable m;
movable m2(boost::move(m));
movable m3(function(movable(boost::move(m2))));
movable m4(function(boost::move(m3)));
::boost::ignore_unused(m);::boost::ignore_unused(m2);::boost::ignore_unused(m3);::boost::ignore_unused(m4);
}
{
movable m;
movable m2(boost::move(m));
movable m3(functionr(movable(boost::move(m2))));
movable m4(functionr(boost::move(m3)));
::boost::ignore_unused(m);::boost::ignore_unused(m2);::boost::ignore_unused(m3);::boost::ignore_unused(m4);
}
{
movable m;
movable m2(boost::move(m));
movable m3(function2(movable(boost::move(m2))));
movable m4(function2(boost::move(m3)));
::boost::ignore_unused(m);::boost::ignore_unused(m2);::boost::ignore_unused(m3);::boost::ignore_unused(m4);
}
{
movable m;
movable m2(boost::move(m));
movable m3(function2r(movable(boost::move(m2))));
movable m4(function2r(boost::move(m3)));
::boost::ignore_unused(m);::boost::ignore_unused(m2);::boost::ignore_unused(m3);::boost::ignore_unused(m4);
}
{
movable m;
movable m2(boost::move(m));
movable m3(move_return_function());
::boost::ignore_unused(m);::boost::ignore_unused(m2);::boost::ignore_unused(m3);
}
{
movable m;
movable m2(boost::move(m));
movable m3(move_return_function2());
::boost::ignore_unused(m);::boost::ignore_unused(m2);::boost::ignore_unused(m3);
}
{
//movable
movable m (factory_wrapper<movable>(factory<movable>()));
m = factory_wrapper<movable>(factory<movable>());
movable&mr(factory_wrapper<movable&>(factory<movable&>()));
movable&mr2 = factory_wrapper<movable&>(factory<movable&>());
::boost::ignore_unused(mr);
::boost::ignore_unused(mr2);
::boost::ignore_unused(m);
}
{
//copyable
copyable c (factory_wrapper<copyable>(factory<copyable>()));
c = factory_wrapper<copyable>(factory<copyable>());
copyable&cr(factory_wrapper<copyable&>(factory<copyable&>()));
copyable&cr2 = factory_wrapper<copyable&>(factory<copyable&>());
::boost::ignore_unused(cr);
::boost::ignore_unused(cr2);
::boost::ignore_unused(c);
}
{
//copy_movable
copy_movable c (factory_wrapper<copy_movable>(factory<copy_movable>()));
c = factory_wrapper<copy_movable>(factory<copy_movable>());
copy_movable&cr(factory_wrapper<copy_movable&>(factory<copy_movable&>()));
copy_movable&cr2 = factory_wrapper<copy_movable&>(factory<copy_movable&>());
::boost::ignore_unused(cr);
::boost::ignore_unused(cr2);
::boost::ignore_unused(c);
}
return 0;
}

View File

@@ -0,0 +1,56 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
// 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/algorithm.hpp>
#include <boost/container/vector.hpp>
#include "../example/movable.hpp"
int main()
{
namespace bc = ::boost::container;
//Default construct 10 movable objects
bc::vector<movable> v(10);
bc::vector<movable> v2(10);
//Move to v2
boost::move(v.begin(), v.end(), v2.begin());
//Test values have been moved
if(!v[0].moved()){
return 1;
}
if(v2.size() != 10){
return 1;
}
if(v2[0].moved()){
return 1;
}
//Move to v again
boost::move_backward(v2.begin(), v2.end(), v.end());
//Test values have been moved
if(!v2[1].moved()){
return 1;
}
if(v.size() != 10){
return 1;
}
if(v[1].moved()){
return 1;
}
return 0;
}

View File

@@ -0,0 +1,228 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Antony Polukhin 2014.
// (C) Copyright Ion Gaztanaga 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/utility.hpp>
#include <boost/core/lightweight_test.hpp>
#include "../example/movable.hpp"
#include "../example/copymovable.hpp"
#include <boost/static_assert.hpp>
//////////////////////////////////////////////////////////////////////////////
//A copy_movable_noexcept class
class copy_movable_noexcept
{
BOOST_COPYABLE_AND_MOVABLE(copy_movable_noexcept)
int value_;
public:
copy_movable_noexcept() : value_(1){}
//Move constructor and assignment
copy_movable_noexcept(BOOST_RV_REF(copy_movable_noexcept) m)
{ value_ = m.value_; m.value_ = 0; }
copy_movable_noexcept(const copy_movable_noexcept &m)
{ value_ = m.value_; }
copy_movable_noexcept & operator=(BOOST_RV_REF(copy_movable_noexcept) m)
{ value_ = m.value_; m.value_ = 0; return *this; }
copy_movable_noexcept & operator=(BOOST_COPY_ASSIGN_REF(copy_movable_noexcept) m)
{ value_ = m.value_; return *this; }
bool moved() const //Observer
{ return value_ == 0; }
};
namespace boost{
template<>
struct has_nothrow_move<copy_movable_noexcept>
{
static const bool value = true;
};
} //namespace boost{
//////////////////////////////////////////////////////////////////////////////
//A movable_throwable class
class movable_throwable
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_throwable)
int value_;
public:
movable_throwable() : value_(1){}
//Move constructor and assignment
movable_throwable(BOOST_RV_REF(movable_throwable) m)
{ value_ = m.value_; m.value_ = 0; }
movable_throwable & operator=(BOOST_RV_REF(movable_throwable) m)
{ value_ = m.value_; m.value_ = 0; return *this; }
bool moved() const //Observer
{ return !value_; }
int value() const //Observer
{ return value_; }
};
//////////////////////////////////////////////////////////////////////////////
// Helper functions
movable function(movable m)
{
return movable(boost::move_if_noexcept(m));
}
copy_movable function(copy_movable m)
{
return copy_movable(boost::move_if_noexcept(m));
}
copy_movable_noexcept function(copy_movable_noexcept m)
{
return copy_movable_noexcept(boost::move_if_noexcept(m));
}
movable_throwable function(movable_throwable m)
{
return movable_throwable(boost::move_if_noexcept(m));
}
movable functionr(BOOST_RV_REF(movable) m)
{
return movable(boost::move_if_noexcept(m));
}
movable function2(movable m)
{
return boost::move_if_noexcept(m);
}
BOOST_RV_REF(movable) function2r(BOOST_RV_REF(movable) m)
{
return boost::move_if_noexcept(m);
}
movable move_return_function2 ()
{
return movable();
}
movable move_return_function ()
{
movable m;
return (boost::move_if_noexcept(m));
}
#define BOOST_CHECK(x) if (!(x)) { return __LINE__; }
int main()
{
{
movable m;
movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
movable m3(function(movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
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));
BOOST_CHECK(m.moved());
movable m3(functionr(movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
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));
BOOST_CHECK(m.moved());
movable m3(function2(movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
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));
BOOST_CHECK(m.moved());
movable m3(function2r(movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
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));
BOOST_CHECK(m.moved());
BOOST_CHECK(!m2.moved());
movable m3(move_return_function());
BOOST_CHECK(!m3.moved());
}
{
movable m;
movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
BOOST_CHECK(!m2.moved());
movable m3(move_return_function2());
BOOST_CHECK(!m3.moved());
}
// copy_movable may throw during move, so it must be copied
{
copy_movable m;
copy_movable m2(boost::move_if_noexcept(m));
BOOST_CHECK(!m.moved());
copy_movable m3(function(copy_movable(boost::move_if_noexcept(m2))));
BOOST_CHECK(!m2.moved());
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
{
copy_movable_noexcept m;
copy_movable_noexcept m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
copy_movable_noexcept m3(function(copy_movable_noexcept(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
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
{
movable_throwable m;
movable_throwable m2(boost::move_if_noexcept(m));
BOOST_CHECK(m.moved());
movable_throwable m3(function(movable_throwable(boost::move_if_noexcept(m2))));
BOOST_CHECK(m2.moved());
movable_throwable m4(function(boost::move_if_noexcept(m3)));
BOOST_CHECK(m3.moved());
BOOST_CHECK(!m4.moved());
}
return boost::report_errors();
}

View File

@@ -0,0 +1,42 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
// 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/iterator.hpp>
#include <boost/container/vector.hpp>
#include <boost/core/lightweight_test.hpp>
#include "../example/movable.hpp"
int main()
{
namespace bc = ::boost::container;
//Default construct 10 movable objects
bc::vector<movable> v(10);
//Test default constructed value
BOOST_TEST(!v[0].moved());
//Move values
bc::vector<movable> v2
(boost::make_move_iterator(v.begin()), boost::make_move_iterator(v.end()));
//Test values have been moved
BOOST_TEST(v[0].moved());
BOOST_TEST(v2.size() == 10);
//Move again
v.assign(boost::make_move_iterator(v2.begin()), boost::make_move_iterator(v2.end()));
//Test values have been moved
BOOST_TEST(v2[0].moved());
BOOST_TEST(!v[0].moved());
return ::boost::report_errors();
}

View File

@@ -0,0 +1,276 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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 <boost/move/core.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <cstddef>
#include <cstdio>
struct order_perf_type
{
public:
std::size_t key;
std::size_t val;
order_perf_type()
: key(), val()
{
++num_elements;
}
order_perf_type(const order_perf_type& other)
: key(other.key), val(other.val)
{
++num_elements;
++num_copy;
}
order_perf_type & operator=(const order_perf_type& other)
{
++num_copy;
key = other.key;
val = other.val;
return *this;
}
~order_perf_type ()
{
--num_elements;
}
static void reset_stats()
{
num_compare=0;
num_copy=0;
}
friend bool operator< (const order_perf_type& left, const order_perf_type& right)
{ ++num_compare; return left.key < right.key; }
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_perf_type::num_compare = 0;
boost::ulong_long_type order_perf_type::num_copy = 0;
boost::ulong_long_type order_perf_type::num_elements = 0;
struct order_move_type
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(order_move_type)
public:
std::size_t key;
std::size_t val;
static const std::size_t moved_constr_mark = std::size_t(-1);
static const std::size_t moved_assign_mark = std::size_t(-2);
order_move_type()
: key(0u), val(0u)
{}
order_move_type(BOOST_RV_REF(order_move_type) other)
: key(other.key), val(other.val)
{
other.key = other.val = std::size_t(-1);
}
order_move_type & operator=(BOOST_RV_REF(order_move_type) other)
{
key = other.key;
val = other.val;
other.key = other.val = std::size_t(-2);
return *this;
}
friend bool operator< (const order_move_type& left, const order_move_type& right)
{ return left.key < right.key; }
~order_move_type ()
{
key = val = std::size_t(-3);
}
};
struct order_type_less
{
template<class T, class U>
bool operator()(const T &a, U const &b) const
{ return a < b; }
};
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()(elements[i], elements[i-1])){
std::printf("\n Ord KO !!!!");
return false;
}
if( stable && !(order_type_less()(elements[i-1], elements[i])) && (elements[i-1].val > elements[i].val) ){
std::printf("\n Stb KO !!!! ");
return false;
}
}
return true;
}
namespace boost {
namespace movelib {
namespace detail_adaptive {
}}}
template<class T>
inline bool is_key(T *elements, std::size_t element_count)
{
for(std::size_t i = 1; i < element_count; ++i){
if(elements[i].key >= element_count){
std::printf("\n Key.key KO !!!!");
return false;
}
if(elements[i].val != std::size_t(-1)){
std::printf("\n Key.val KO !!!!");
return false;
}
}
return true;
}
template<class T>
inline bool is_buffer(T *elements, std::size_t element_count)
{
for(std::size_t i = 1; i < element_count; ++i){
if(elements[i].key != std::size_t(-1)){
std::printf("\n Buf.key KO !!!!");
return false;
}
if(elements[i].val >= element_count){
std::printf("\n Buf.val KO !!!!");
return false;
}
}
return true;
}
//size_type iterator
template <class T, class D>
class randit
{
public:
typedef std::random_access_iterator_tag iterator_category;
typedef T value_type;
typedef D difference_type;
typedef T* pointer;
typedef T& reference;
private:
T* m_ptr;
public:
explicit randit(T* ptr)
: m_ptr(ptr)
{}
public:
//Constructors
randit()
: m_ptr() //Value initialization to achieve "null iterators" (N3644)
{}
randit(const randit& other)
: m_ptr(other.m_ptr)
{}
randit & operator=(const randit& other)
{ m_ptr = other.m_ptr; return *this; }
//T* like operators
reference operator*() const
{ return *m_ptr; }
pointer operator->() const
{ return m_ptr; }
reference operator[](difference_type off) const
{ return m_ptr[off]; }
//Increment / Decrement
randit& operator++()
{ ++m_ptr; return *this; }
randit operator++(int)
{ return randit(m_ptr++); }
randit& operator--()
{ --m_ptr; return *this; }
randit operator--(int)
{ return randit(m_ptr--); }
//Arithmetic
randit& operator+=(difference_type off)
{ m_ptr += off; return *this; }
randit& operator-=(difference_type off)
{ m_ptr -= off; return *this; }
friend randit operator+(const randit &x, difference_type off)
{ return randit(x.m_ptr+off); }
friend randit operator+(difference_type off, randit right)
{ right.m_ptr += off; return right; }
friend randit operator-(randit left, difference_type off)
{ left.m_ptr -= off; return left; }
friend difference_type operator-(const randit &left, const randit& right)
{ return difference_type(left.m_ptr - right.m_ptr); }
//Comparison operators
friend bool operator== (const randit& l, const randit& r)
{ return l.m_ptr == r.m_ptr; }
friend bool operator!= (const randit& l, const randit& r)
{ return l.m_ptr != r.m_ptr; }
friend bool operator< (const randit& l, const randit& r)
{ return l.m_ptr < r.m_ptr; }
friend bool operator<= (const randit& l, const randit& r)
{ return l.m_ptr <= r.m_ptr; }
friend bool operator> (const randit& l, const randit& r)
{ return l.m_ptr > r.m_ptr; }
friend bool operator>= (const randit& l, const randit& r)
{ return l.m_ptr >= r.m_ptr; }
};
struct less_int
{
bool operator()(int l, int r)
{ return l < r; }
};
#endif //BOOST_MOVE_TEST_ORDER_TYPE_HPP

View File

@@ -0,0 +1,36 @@
#ifndef BOOST_MOVE_TEST_RANDOM_SHUFFLE_HPP
#define BOOST_MOVE_TEST_RANDOM_SHUFFLE_HPP
#include <boost/move/adl_move_swap.hpp>
#include <boost/move/detail/iterator_traits.hpp>
#include <stdlib.h>
inline unsigned long long rand_15_bit()
{
//Many rand implementation only use 15 bits
//so make sure we have only 15 bits
return (unsigned long long)((std::rand()) & 0x7fff);
}
inline unsigned long long ullrand()
{
return (rand_15_bit() << 54u) ^ (rand_15_bit() << 39u)
^ (rand_15_bit() << 26u) ^ (rand_15_bit() << 13u)
^ rand_15_bit();
}
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last )
{
std::size_t n = std::size_t (last - first);
for (std::size_t i = n-1; i > 0; --i) {
std::size_t j = static_cast<std::size_t >(ullrand() % (unsigned long long)(i+1));
if(j != i) {
boost::adl_move_swap(first[i], first[j]);
}
}
}
#endif// BOOST_MOVE_TEST_RANDOM_SHUFFLE_HPP

View File

@@ -0,0 +1,98 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/move/detail/type_traits.hpp>
#include <boost/move/core.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/lightweight_test.hpp>
//
// pod_struct
//
#if defined(BOOST_MOVE_IS_POD)
struct pod_struct
{
int i;
float f;
};
#endif
//
// deleted_copy_and_assign_type
//
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
struct deleted_copy_and_assign_type
{
deleted_copy_and_assign_type(const deleted_copy_and_assign_type&) = delete;
deleted_copy_and_assign_type & operator=(const deleted_copy_and_assign_type&) = delete;
};
#endif //defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
//
// boost_move_type
//
class boost_move_type
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(boost_move_type)
public:
boost_move_type(BOOST_RV_REF(boost_move_type)){}
boost_move_type & operator=(BOOST_RV_REF(boost_move_type)){ return *this; }
};
namespace is_pod_test
{
void test()
{
BOOST_STATIC_ASSERT((boost::move_detail::is_pod<int>::value));
#if defined(BOOST_MOVE_IS_POD)
BOOST_STATIC_ASSERT((boost::move_detail::is_pod<pod_struct>::value));
#endif
}
} //namespace is_pod_test
namespace trivially_memcopyable_test {
void test()
{
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible<deleted_copy_and_assign_type>::value));
BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable<deleted_copy_and_assign_type>::value));
#endif //#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
//boost_move_type
BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible<boost_move_type>::value));
BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable<boost_move_type>::value));
BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_constructible<boost_move_type>::value));
BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_assignable<boost_move_type>::value));
//POD
BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_constructible<int>::value));
BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_assignable<int>::value));
BOOST_STATIC_ASSERT((boost::move_detail::is_copy_constructible<int>::value));
BOOST_STATIC_ASSERT((boost::move_detail::is_copy_assignable<int>::value));
#if defined(BOOST_MOVE_IS_POD)
BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_constructible<pod_struct>::value));
BOOST_STATIC_ASSERT((boost::move_detail::is_trivially_copy_assignable<pod_struct>::value));
BOOST_STATIC_ASSERT((boost::move_detail::is_copy_constructible<pod_struct>::value));
BOOST_STATIC_ASSERT((boost::move_detail::is_copy_assignable<pod_struct>::value));
#endif
}
} //namespace trivially_memcopyable_test {
int main()
{
trivially_memcopyable_test::test();
is_pod_test::test();
boost::report_errors();
}

View File

@@ -0,0 +1,444 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (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/utility_core.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/lightweight_test.hpp>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
#include "unique_ptr_test_utils_beg.hpp"
namespace bml = ::boost::movelib;
////////////////////////////////
// unique_ptr_asgn_move_convert_defdel
////////////////////////////////
namespace unique_ptr_asgn_move_convert_defdel {
void test()
{
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<B> s(new B);
A* p = s.get();
bml::unique_ptr<A> s2(new A);
BOOST_TEST(A::count == 2);
s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[]> s(new A[2]);
A* p = s.get();
bml::unique_ptr<const A[]> s2(new const A[2]);
BOOST_TEST(A::count == 4);
s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[2]> s(new A[2]);
A* p = s.get();
bml::unique_ptr<const A[2]> s2(new const A[2]);
BOOST_TEST(A::count == 4);
s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
}
{
BOOST_TEST(A::count == 0);
bml::unique_ptr<A[2]> s(new A[2]);
A* p = s.get();
bml::unique_ptr<const A[]> s2(new const A[2]);
BOOST_TEST(A::count == 4);
s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_asgn_move_convert_defdel{
////////////////////////////////
// unique_ptr_asgn_move_convert_movdel
////////////////////////////////
namespace unique_ptr_asgn_move_convert_movedel{
void test()
{
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<B, move_constr_deleter<B> > s(new B);
A* p = s.get();
bml::unique_ptr<A, move_constr_deleter<A> > s2(new A);
BOOST_TEST(A::count == 2);
s2 = (boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[], move_constr_deleter<A[]> > s(new A[2]);
A* p = s.get();
bml::unique_ptr<const A[], move_constr_deleter<const A[]> > s2(new const A[2]);
BOOST_TEST(A::count == 4);
s2 = (boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s(new A[3]);
A* p = s.get();
bml::unique_ptr<const A[2], move_constr_deleter<const A[2]> > s2(new const A[2]);
BOOST_TEST(A::count == 5);
s2 = (boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 3);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
reset_counters();
{
bml::unique_ptr<A[2], move_constr_deleter<A[3]> > s(new A[2]);
A* p = s.get();
bml::unique_ptr<const A[], move_constr_deleter<const A[]> > s2(new const A[2]);
BOOST_TEST(A::count == 4);
s2 = (boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_asgn_move_convert_movedel{
////////////////////////////////
// unique_ptr_asgn_move_convert_copydelref
////////////////////////////////
namespace unique_ptr_asgn_move_convert_copydelref{
// test converting move assignment with reference deleters
void test()
{
//Single unique_ptr
reset_counters();
{
copy_constr_deleter<B> db(5);
bml::unique_ptr<B, copy_constr_deleter<B>&> s(new B, db);
A* p = s.get();
copy_constr_deleter<A> da(6);
bml::unique_ptr<A, copy_constr_deleter<A>&> s2(new A, da);
s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
BOOST_TEST(s2.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
copy_constr_deleter<A[]> db(5);
bml::unique_ptr<A[], copy_constr_deleter<A[]>&> s(new A[2], db);
A* p = s.get();
copy_constr_deleter<const A[]> da(6);
bml::unique_ptr<const A[], copy_constr_deleter<const A[]>&> s2(new const A[2], da);
BOOST_TEST(A::count == 4);
s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
copy_constr_deleter<A[2]> db(5);
bml::unique_ptr<A[2], copy_constr_deleter<A[2]>&> s(new A[2], db);
A* p = s.get();
copy_constr_deleter<const A[2]> da(6);
bml::unique_ptr<const A[2], copy_constr_deleter<const A[2]>&> s2(new const A[2], da);
BOOST_TEST(A::count == 4);
s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
reset_counters();
{
copy_constr_deleter<A[2]> db(5);
bml::unique_ptr<A[2], copy_constr_deleter<A[2]>&> s(new A[2], db);
A* p = s.get();
copy_constr_deleter<const A[]> da(6);
bml::unique_ptr<const A[], copy_constr_deleter<const A[]>&> s2(new const A[2], da);
BOOST_TEST(A::count == 4);
s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_asgn_move_convert_copydelref{
////////////////////////////////
// unique_ptr_asgn_move_defdel
////////////////////////////////
namespace unique_ptr_asgn_move_defdel {
void test()
{
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<A> s1(new A);
A* p = s1.get();
bml::unique_ptr<A> s2(new A);
BOOST_TEST(A::count == 2);
s2 = boost::move(s1);
BOOST_TEST(A::count == 1);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s1.get() == 0);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[]> s1(new A[2]);
A* p = s1.get();
bml::unique_ptr<A[]> s2(new A[2]);
BOOST_TEST(A::count == 4);
s2 = boost::move(s1);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s1.get() == 0);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[2]> s1(new A[2]);
A* p = s1.get();
bml::unique_ptr<A[2]> s2(new A[2]);
BOOST_TEST(A::count == 4);
s2 = boost::move(s1);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s1.get() == 0);
}
BOOST_TEST(A::count == 0);
}
} //unique_ptr_asgn_move_defdel
////////////////////////////////
// unique_ptr_asgn_move_movedel
////////////////////////////////
namespace unique_ptr_asgn_move_movedel {
void test()
{
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<A, move_constr_deleter<A> > s1(new A);
A* p = s1.get();
bml::unique_ptr<A, move_constr_deleter<A> > s2(new A);
BOOST_TEST(A::count == 2);
s2 = boost::move(s1);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s1.get() == 0);
BOOST_TEST(A::count == 1);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s1.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[], move_constr_deleter<A[]> > s1(new A[2]);
A* p = s1.get();
bml::unique_ptr<A[], move_constr_deleter<A[]> > s2(new A[2]);
BOOST_TEST(A::count == 4);
s2 = boost::move(s1);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s1.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s1.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s1(new A[2]);
A* p = s1.get();
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s2(new A[2]);
BOOST_TEST(A::count == 4);
s2 = boost::move(s1);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s1.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s1.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
}
} //unique_ptr_asgn_move_movedel
////////////////////////////////
// unique_ptr_asgn_move_copydelref
////////////////////////////////
namespace unique_ptr_asgn_move_copydelref {
void test()
{
//Single unique_ptr
reset_counters();
{
copy_constr_deleter<A> d1(5);
bml::unique_ptr<A, copy_constr_deleter<A>&> s1(new A, d1);
A* p = s1.get();
copy_constr_deleter<A> d2(6);
bml::unique_ptr<A, copy_constr_deleter<A>&> s2(new A, d2);
s2 = boost::move(s1);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s1.get() == 0);
BOOST_TEST(A::count == 1);
BOOST_TEST(d1.state() == 5);
BOOST_TEST(d2.state() == 5);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
copy_constr_deleter<A[]> d1(5);
bml::unique_ptr<A[], copy_constr_deleter<A[]>&> s1(new A[2], d1);
A* p = s1.get();
copy_constr_deleter<A[]> d2(6);
bml::unique_ptr<A[], copy_constr_deleter<A[]>&> s2(new A[2], d2);
BOOST_TEST(A::count == 4);
s2 = boost::move(s1);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s1.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(d1.state() == 5);
BOOST_TEST(d2.state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
copy_constr_deleter<A[2]> d1(5);
bml::unique_ptr<A[2], copy_constr_deleter<A[2]>&> s1(new A[2], d1);
A* p = s1.get();
copy_constr_deleter<A[2]> d2(6);
bml::unique_ptr<A[2], copy_constr_deleter<A[2]>&> s2(new A[2], d2);
BOOST_TEST(A::count == 4);
s2 = boost::move(s1);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s1.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(d1.state() == 5);
BOOST_TEST(d2.state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //unique_ptr_asgn_move_copydelref
////////////////////////////////
// main
////////////////////////////////
int main()
{
//Assignment
unique_ptr_asgn_move_convert_defdel::test();
unique_ptr_asgn_move_convert_movedel::test();
unique_ptr_asgn_move_convert_copydelref::test();
unique_ptr_asgn_move_defdel::test();
unique_ptr_asgn_move_movedel::test();
unique_ptr_asgn_move_copydelref::test();
//Test results
return boost::report_errors();
}
#include "unique_ptr_test_utils_end.hpp"

View File

@@ -0,0 +1,811 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (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/utility_core.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/lightweight_test.hpp>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
#include "unique_ptr_test_utils_beg.hpp"
namespace bml = ::boost::movelib;
////////////////////////////////
// unique_ptr_dtor_null
////////////////////////////////
namespace unique_ptr_dtor_null{
// The deleter is not called if get() == 0
void test()
{
//Single unique_ptr
{
def_constr_deleter<int> d;
BOOST_TEST(d.state() == 5);
{
bml::unique_ptr<int, def_constr_deleter<int>&> p(0, d);
BOOST_TEST(p.get() == 0);
BOOST_TEST(&p.get_deleter() == &d);
}
BOOST_TEST(d.state() == 5);
}
{
//Unbounded array unique_ptr
def_constr_deleter<int[]> d;
BOOST_TEST(d.state() == 5);
{
bml::unique_ptr<int[], def_constr_deleter<int[]>&> p(0, d);
BOOST_TEST(p.get() == 0);
BOOST_TEST(&p.get_deleter() == &d);
}
BOOST_TEST(d.state() == 5);
}
{
//Bounded array unique_ptr
def_constr_deleter<int[2]> d;
BOOST_TEST(d.state() == 5);
{
bml::unique_ptr<int[2], def_constr_deleter<int[2]>&> p(0, d);
BOOST_TEST(p.get() == 0);
BOOST_TEST(&p.get_deleter() == &d);
}
BOOST_TEST(d.state() == 5);
}
}
} //namespace unique_ptr_dtor_null{
////////////////////////////////
// unique_ptr_ctor_default_delreq
////////////////////////////////
namespace unique_ptr_ctor_default_delreq{
// default unique_ptr ctor should only require default deleter ctor
void test()
{
//Single unique_ptr
{
bml::unique_ptr<int> p;
BOOST_TEST(p.get() == 0);
}
{
bml::unique_ptr<int, def_constr_deleter<int> > p;
BOOST_TEST(p.get() == 0);
BOOST_TEST(p.get_deleter().state() == 5);
}
//Unbounded array unique_ptr
{
bml::unique_ptr<int[]> p;
BOOST_TEST(p.get() == 0);
}
{
bml::unique_ptr<int[], def_constr_deleter<int[]> > p;
BOOST_TEST(p.get() == 0);
BOOST_TEST(p.get_deleter().state() == 5);
}
//Unbounded array unique_ptr
{
bml::unique_ptr<int[]> p;
BOOST_TEST(p.get() == 0);
}
{
bml::unique_ptr<int[], def_constr_deleter<int[]> > p;
BOOST_TEST(p.get() == 0);
BOOST_TEST(p.get_deleter().state() == 5);
}
//Unbounded array unique_ptr
{
bml::unique_ptr<int[2]> p;
BOOST_TEST(p.get() == 0);
}
{
bml::unique_ptr<int[2], def_constr_deleter<int[2]> > p;
BOOST_TEST(p.get() == 0);
BOOST_TEST(p.get_deleter().state() == 5);
}
}
} //namespace unique_ptr_ctor_default_delreq{
////////////////////////////////
// unique_ptr_ctor_default_nocomplete
////////////////////////////////
namespace unique_ptr_ctor_default_nocomplete{
// default unique_ptr ctor shouldn't require complete type
void test()
{
//Single unique_ptr
reset_counters();
{
J<I> s;
BOOST_TEST(s.get() == 0);
}
check(0);
{
J<I, def_constr_deleter<I> > s;
BOOST_TEST(s.get() == 0);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
//Unbounded array unique_ptr
reset_counters();
{
J<I[]> s;
BOOST_TEST(s.get() == 0);
}
check(0);
{
J<I[], def_constr_deleter<I[]> > s;
BOOST_TEST(s.get() == 0);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
//Bounded array unique_ptr
reset_counters();
{
J<I[2]> s;
BOOST_TEST(s.get() == 0);
}
check(0);
{
J<I[2], def_constr_deleter<I[2]> > s;
BOOST_TEST(s.get() == 0);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
}
} //namespace unique_ptr_ctor_default_nocomplete{
////////////////////////////////
// unique_ptr_ctor_pointer_delreq
////////////////////////////////
namespace unique_ptr_ctor_pointer_delreq{
// unique_ptr(pointer) ctor should only require default deleter ctor
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
bml::unique_ptr<A> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
A* p = new A;
BOOST_TEST(A::count == 1);
bml::unique_ptr<A, def_constr_deleter<A> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<A[]> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<A[], def_constr_deleter<A[]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<A[2]> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<A[2], def_constr_deleter<A[2]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_delreq{
////////////////////////////////
// unique_ptr_ctor_pointer_nocomplete
////////////////////////////////
namespace unique_ptr_ctor_pointer_nocomplete{
// unique_ptr(pointer) ctor shouldn't require complete type
void test()
{
//Single unique_ptr
reset_counters();
{
I* p = get();
check(1);
J<I> s(p);
BOOST_TEST(s.get() == p);
}
check(0);
{
I* p = get();
check(1);
J<I, def_constr_deleter<I> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
//Unbounded array unique_ptr
reset_counters();
{
I* p = get_array(2);
check(2);
J<I[]> s(p);
BOOST_TEST(s.get() == p);
}
check(0);
{
I* p = get_array(2);
check(2);
J<I[], def_constr_deleter<I[]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
//Bounded array unique_ptr
reset_counters();
{
I* p = get_array(2);
check(2);
J<I[]> s(p);
BOOST_TEST(s.get() == p);
}
check(0);
{
I* p = get_array(2);
check(2);
J<I[2], def_constr_deleter<I[2]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
}
} //namespace unique_ptr_ctor_pointer_nocomplete{
////////////////////////////////
// unique_ptr_ctor_pointer_convert
////////////////////////////////
namespace unique_ptr_ctor_pointer_convert{
// unique_ptr(pointer) ctor should work with derived pointers
// or same types (cv aside) for unique_ptr<arrays>
void test()
{
//Single unique_ptr
reset_counters();
{
B* p = new B;
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
bml::unique_ptr<A> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
{
B* p = new B;
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
bml::unique_ptr<A, def_constr_deleter<A> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const A[]> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
const A* p = new const A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const volatile A[], def_constr_deleter<const volatile A[]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const A[2]> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
const A* p = new const A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const volatile A[2], def_constr_deleter<const volatile A[2]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_convert{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_movedel
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_movedel{
// test move ctor. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
// unique_ptr(pointer, deleter()) only requires MoveConstructible deleter
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
move_constr_deleter<A> d;
bml::unique_ptr<A, move_constr_deleter<A> > s(p, ::boost::move(d));
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
bml::unique_ptr<A, move_constr_deleter<A> > s2(s.release(), move_constr_deleter<A>(6));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s2.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
move_constr_deleter<A[]> d;
bml::unique_ptr<A[], move_constr_deleter<A[]> > s(p, ::boost::move(d));
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
bml::unique_ptr<A[], move_constr_deleter<A[]> > s2(s.release(), move_constr_deleter<A[]>(6));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s2.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
move_constr_deleter<A[2]> d;
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s(p, ::boost::move(d));
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s2(s.release(), move_constr_deleter<A[2]>(6));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s2.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_movedel{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_copydel
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_copydel{
// unique_ptr(pointer, d) requires CopyConstructible deleter
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
copy_constr_deleter<A> d;
bml::unique_ptr<A, copy_constr_deleter<A> > s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
copy_constr_deleter<A[]> d;
bml::unique_ptr<A[], copy_constr_deleter<A[]> > s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
copy_constr_deleter<A[2]> d;
bml::unique_ptr<A[2], copy_constr_deleter<A[2]> > s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_copydel{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_dfctrdelref
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_dfctrdelref{
// unique_ptr<T, D&>(pointer, d) does not requires CopyConstructible deleter
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
def_constr_deleter<A> d;
bml::unique_ptr<A, def_constr_deleter<A>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
def_constr_deleter<A[]> d;
bml::unique_ptr<A[], def_constr_deleter<A[]>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
def_constr_deleter<A[2]> d;
bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_dfctrdelref{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_dfctrdelconstref
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_dfctrdelconstref{
// unique_ptr<T, const D&>(pointer, d) does not requires CopyConstructible deleter
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
def_constr_deleter<A> d;
bml::unique_ptr<A, const def_constr_deleter<A>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
def_constr_deleter<A[]> d;
bml::unique_ptr<A[], const def_constr_deleter<A[]>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
def_constr_deleter<A[2]> d;
bml::unique_ptr<A[2], const def_constr_deleter<A[2]>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_dfctrdelconstref{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_convert
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_convert{
// unique_ptr(pointer, deleter) should work with derived pointers
// or same (cv aside) types for array unique_ptrs
void test()
{
//Single unique_ptr
reset_counters();
{
B* p = new B;
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
bml::unique_ptr<A, copy_constr_deleter<A> > s(p, copy_constr_deleter<A>());
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const A[], copy_constr_deleter<const A[]> > s(p, copy_constr_deleter<const A[]>());
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const A[2], copy_constr_deleter<const A[2]> > s(p, copy_constr_deleter<const A[2]>());
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_convert{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_void
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_void{
// unique_ptr(pointer, deleter) should work with function pointers
// unique_ptr<void> should work
bool my_free_called = false;
void my_free(void*)
{
my_free_called = true;
}
void test()
{
{
int i = 0;
bml::unique_ptr<void, void (*)(void*)> s(&i, my_free);
BOOST_TEST(s.get() == &i);
BOOST_TEST(s.get_deleter() == my_free);
BOOST_TEST(!my_free_called);
}
BOOST_TEST(my_free_called);
}
} //namespace unique_ptr_ctor_pointer_deleter_void{
////////////////////////////////
// return_unique_single_conversion
////////////////////////////////
namespace return_unique_single_conversion{
template<class T>
bml::unique_ptr<T> make_unique_ptr_of_t()
{
return bml::unique_ptr<T>(new T);
}
template<class T>
bml::unique_ptr<T const> return_const_unique_of_t()
{
return bml::unique_ptr<T const> (make_unique_ptr_of_t<T>());
}
void test()
{
reset_counters();
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A> p(return_const_unique_of_t<A>());
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A> p(return_const_unique_of_t<B>());
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
}
BOOST_TEST(A::count == 0);
}
} //namespace return_unique_single_conversion{
////////////////////////////////
// return_unique_array_conversion
////////////////////////////////
namespace return_unique_array_conversion{
template<class T>
bml::unique_ptr<T[]> return_unique_array_of_t(std::size_t n)
{
return bml::unique_ptr<T[]>(new T[n]);
}
template<class T>
bml::unique_ptr<const T[]> return_const_array_of_t(std::size_t n)
{
return bml::unique_ptr<const T[]>(return_unique_array_of_t<T>(n));
}
template<class T>
bml::unique_ptr<T[2]> return_unique_array_of_t_2()
{
return bml::unique_ptr<T[2]>(new T[2]);
}
template<class T>
bml::unique_ptr<const T[2]> return_const_array_of_t_2()
{
return bml::unique_ptr<const T[2]>(return_unique_array_of_t_2<T>());
}
void test()
{
reset_counters();
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A[]> p(return_unique_array_of_t<A>(2));
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const volatile A[]> p(return_unique_array_of_t<volatile A>(2));
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const volatile A[2]> p(return_const_array_of_t_2<A>());
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const volatile A[]> p(return_const_array_of_t_2<A>());
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
}
} //namespace return_unique_array_conversion{
////////////////////////////////
// main
////////////////////////////////
int main()
{
//Constructors/Destructor
unique_ptr_dtor_null::test();
unique_ptr_ctor_default_delreq::test();
unique_ptr_ctor_default_nocomplete::test();
unique_ptr_ctor_pointer_delreq::test();
unique_ptr_ctor_pointer_nocomplete::test();
unique_ptr_ctor_pointer_convert::test();
unique_ptr_ctor_pointer_deleter_movedel::test();
unique_ptr_ctor_pointer_deleter_copydel::test();
unique_ptr_ctor_pointer_deleter_dfctrdelref::test();
unique_ptr_ctor_pointer_deleter_dfctrdelconstref::test();
unique_ptr_ctor_pointer_deleter_convert::test();
unique_ptr_ctor_pointer_deleter_void::test();
return_unique_single_conversion::test();
return_unique_array_conversion::test();
//Test results
return boost::report_errors();
}
#include "unique_ptr_test_utils_end.hpp"

View File

@@ -0,0 +1,204 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (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/default_delete.hpp>
#include <boost/core/lightweight_test.hpp>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
////////////////////////////////
// unique_ptr_dltr_dflt_convert_ctor
////////////////////////////////
namespace bml = ::boost::movelib;
struct A
{
static int count;
A() {++count;}
A(const A&) {++count;}
virtual ~A() {--count;}
};
int A::count = 0;
struct B
: public A
{
static int count;
B() : A() {++count;}
B(const B&) : A() {++count;}
virtual ~B() {--count;}
};
int B::count = 0;
void reset_counters()
{ A::count = B::count = 0; }
namespace unique_ptr_dltr_dflt_convert_ctor{
void test()
{
//Single element deleter
{
reset_counters();
bml::default_delete<B> d2;
bml::default_delete<A> d1 = d2;
A* p = new B;
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
d1(p);
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
}
//Array element deleter
{
reset_counters();
bml::default_delete<A[]> d2;
bml::default_delete<const A[]> d1 = d2;
const A* p = new const A[2];
BOOST_TEST(A::count == 2);
d1(p);
BOOST_TEST(A::count == 0);
}
//Bounded array element deleter
{
reset_counters();
bml::default_delete<A[2]> d2;
bml::default_delete<const A[2]> d1 = d2;
const A* p = new const A[2];
BOOST_TEST(A::count == 2);
d1(p);
bml::default_delete<const A[]> d0 = d1;
d0(0);
BOOST_TEST(A::count == 0);
}
}
} //namespace unique_ptr_dltr_dflt_convert_ctor{
////////////////////////////////
// unique_ptr_dltr_dflt_convert_assign
////////////////////////////////
namespace unique_ptr_dltr_dflt_convert_assign{
void test()
{
//Single element deleter
{
reset_counters();
bml::default_delete<B> d2;
bml::default_delete<A> d1;
d1 = d2;
A* p = new B;
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
d1(p);
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
}
//Array element deleter
{
reset_counters();
bml::default_delete<A[]> d2;
bml::default_delete<const A[]> d1;
d1 = d2;
const A* p = new const A[2];
BOOST_TEST(A::count == 2);
d1(p);
BOOST_TEST(A::count == 0);
}
//Bounded array element deleter
{
reset_counters();
bml::default_delete<A[2]> d2;
bml::default_delete<const A[2]> d1;
d1 = d2;
const A* p = new const A[2];
BOOST_TEST(A::count == 2);
d1(p);
bml::default_delete<const A[]> d0;
d0 = d1;
d0(0);
BOOST_TEST(A::count == 0);
}
}
} //namespace unique_ptr_dltr_dflt_convert_assign{
////////////////////////////////
// unique_ptr_dltr_dflt_default
////////////////////////////////
namespace unique_ptr_dltr_dflt_default{
void test()
{
{
//Single element deleter
reset_counters();
bml::default_delete<A> d;
A* p = new A;
BOOST_TEST(A::count == 1);
d(p);
BOOST_TEST(A::count == 0);
}
{
//Array element deleter
reset_counters();
bml::default_delete<A[]> d;
A* p = new A[2];
BOOST_TEST(A::count == 2);
d(p);
BOOST_TEST(A::count == 0);
}
{
//Bounded Array element deleter
reset_counters();
bml::default_delete<A[10]> d;
A* p = new A[10];
BOOST_TEST(A::count == 10);
d(p);
BOOST_TEST(A::count == 0);
}
}
} //namespace unique_ptr_dltr_dflt_default{
////////////////////////////////
// main
////////////////////////////////
int main()
{
unique_ptr_dltr_dflt_convert_ctor::test();
unique_ptr_dltr_dflt_convert_assign::test();
unique_ptr_dltr_dflt_default::test();
//Test results
return boost::report_errors();
}

View File

@@ -0,0 +1,395 @@
//////////////////////////////////////////////////////////////////////////////
//
// (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/make_unique.hpp>
#include <boost/core/lightweight_test.hpp>
#include <cstring>
struct A
{
int a, b, c;
static int count;
A() : a (999), b(1000), c(1001) {++count;}
A(int x) : a (x), b(1000), c(1001) {++count;}
A(int x, int y) : a (x), b(y), c(1001) {++count;}
A(int x, int y, int z) : a (x), b(y), c(z) {++count;}
A(const A&) {++count;}
virtual ~A() {--count;}
};
int A::count = 0;
struct B
: public A
{
static int count;
B() : A() {++count;}
B(const B&) : A() {++count;}
virtual ~B() {--count;}
};
int B::count = 0;
void reset_counters()
{ A::count = B::count = 0; }
static const unsigned PatternSize = 8;
static const unsigned char ff_patternbuf[PatternSize] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const unsigned char ee_patternbuf[PatternSize] = { 0xEE, 0xEE, 0xEE, 0xEE, 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);
//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);
//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);
//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);
//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;
////////////////////////////////
// make_unique_single
////////////////////////////////
namespace make_unique_single{
void test()
{
//Single element deleter
reset_counters();
{
bml::unique_ptr<default_init> p(bml::make_unique_definit<default_init>());
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 == volatile_memcmp(p.get(), dd_patternbuf, sizeof(dd_patternbuf)));
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A> p(bml::make_unique<A>());
BOOST_TEST(A::count == 1);
BOOST_TEST(p->a == 999);
BOOST_TEST(p->b == 1000);
BOOST_TEST(p->c == 1001);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A> p(bml::make_unique_nothrow<A>(0));
BOOST_TEST(A::count == 1);
BOOST_TEST(p->a == 0);
BOOST_TEST(p->b == 1000);
BOOST_TEST(p->c == 1001);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A> p(bml::make_unique<A>(0, 1));
BOOST_TEST(A::count == 1);
BOOST_TEST(p->a == 0);
BOOST_TEST(p->b == 1);
BOOST_TEST(p->c == 1001);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A> p(bml::make_unique_nothrow<A>(0, 1, 2));
BOOST_TEST(A::count == 1);
BOOST_TEST(p->a == 0);
BOOST_TEST(p->b == 1);
BOOST_TEST(p->c == 2);
}
BOOST_TEST(A::count == 0);
}
} //namespace make_unique_single{
////////////////////////////////
// make_unique_array
////////////////////////////////
namespace make_unique_array{
void test()
{
//Array element
reset_counters();
{
bml::unique_ptr<A[]> p(bml::make_unique<A[]>(10));
BOOST_TEST(A::count == 10u);
for(std::size_t i = 0; i != 10u; ++i){
BOOST_TEST(p[i].a == 999);
BOOST_TEST(p[i].b == 1000);
BOOST_TEST(p[i].c == 1001);
}
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[]> p(bml::make_unique_nothrow<A[]>(10));
BOOST_TEST(A::count == 10u);
for(std::size_t i = 0; i != 10u; ++i){
BOOST_TEST(p[i].a == 999);
BOOST_TEST(p[i].b == 1000);
BOOST_TEST(p[i].c == 1001);
}
}
BOOST_TEST(A::count == 0);
reset_counters();
{
bml::unique_ptr<default_init[]> p(bml::make_unique_definit<default_init[]>(10));
for(std::size_t i = 0; i != 10u; ++i){
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(std::size_t i = 0; i != 10u; ++i){
BOOST_TEST(0 == volatile_memcmp(&p[i], cc_patternbuf, sizeof(cc_patternbuf)));
}
}
}
} //namespace make_unique_array{
////////////////////////////////
// unique_compare
////////////////////////////////
namespace unique_compare{
void test()
{
//Single element deleter
reset_counters();
{
bml::unique_ptr<A> pa(bml::make_unique<A>());
bml::unique_ptr<A> pb(bml::make_unique<A>());
BOOST_TEST(A::count == 2);
//Take references to less and greater
bml::unique_ptr<A> &rpl = pa < pb ? pa : pb;
bml::unique_ptr<A> &rpg = pa < pb ? pb : pa;
//Now test operations with .get()
//Equal
BOOST_TEST(rpl == rpl && rpl.get() == rpl.get());
BOOST_TEST(!(rpl == rpg) && !(rpl.get() == rpg.get()));
//Unequal
BOOST_TEST(rpl != rpg && rpl.get() != rpg.get());
BOOST_TEST(!(rpl != rpl) && !(rpl.get() != rpl.get()));
//Less
BOOST_TEST(rpl < rpg && rpl.get() < rpg.get());
BOOST_TEST(!(rpg < rpl) && !(rpg.get() < rpl.get()));
//Greater
BOOST_TEST(rpg > rpl && rpg.get() > rpl.get());
BOOST_TEST(!(rpg > rpg) && !(rpg.get() > rpg.get()));
//Less or equal
BOOST_TEST(rpl <= rpg && rpl.get() <= rpg.get());
BOOST_TEST(rpl <= rpl && rpl.get() <= rpl.get());
BOOST_TEST(!(rpg <= rpl) && !(rpg.get() <= rpl.get()));
//Greater or equal
BOOST_TEST(rpg >= rpl && rpg.get() >= rpl.get());
BOOST_TEST(rpg >= rpg && rpg.get() >= rpg.get());
BOOST_TEST(!(rpl >= rpg) && !(rpl.get() >= rpg.get()));
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_compare{
////////////////////////////////
// unique_compare_zero
////////////////////////////////
namespace unique_compare_zero{
void test()
{
//Single element deleter
reset_counters();
{
bml::unique_ptr<A> pa(bml::make_unique<A>());
bml::unique_ptr<A> pb;
BOOST_TEST(A::count == 1);
//Equal
BOOST_TEST(!(pa == 0));
BOOST_TEST(!(0 == pa));
BOOST_TEST((pb == 0));
BOOST_TEST((0 == pb));
//Unequal
BOOST_TEST((pa != 0));
BOOST_TEST((0 != pa));
BOOST_TEST(!(pb != 0));
BOOST_TEST(!(0 != pb));
//Less
BOOST_TEST((pa < 0) == (pa.get() < (A*)0));
BOOST_TEST((0 < pa) == ((A*)0 < pa.get()));
BOOST_TEST((pb < 0) == (pb.get() < (A*)0));
BOOST_TEST((0 < pb) == ((A*)0 < pb.get()));
//Greater
BOOST_TEST((pa > 0) == (pa.get() > (A*)0));
BOOST_TEST((0 > pa) == ((A*)0 > pa.get()));
BOOST_TEST((pb > 0) == (pb.get() > (A*)0));
BOOST_TEST((0 > pb) == ((A*)0 > pb.get()));
//Less or equal
BOOST_TEST((pa <= 0) == (pa.get() <= (A*)0));
BOOST_TEST((0 <= pa) == ((A*)0 <= pa.get()));
BOOST_TEST((pb <= 0) == (pb.get() <= (A*)0));
BOOST_TEST((0 <= pb) == ((A*)0 <= pb.get()));
//Greater or equal
BOOST_TEST((pa >= 0) == (pa.get() >= (A*)0));
BOOST_TEST((0 >= pa) == ((A*)0 >= pa.get()));
BOOST_TEST((pb >= 0) == (pb.get() >= (A*)0));
BOOST_TEST((0 >= pb) == ((A*)0 >= pb.get()));
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_compare_zero{
////////////////////////////////
// unique_compare_nullptr
////////////////////////////////
namespace unique_compare_nullptr{
void test()
{
#if !defined(BOOST_NO_CXX11_NULLPTR)
//Single element deleter
reset_counters();
{
bml::unique_ptr<A> pa(bml::make_unique<A>());
bml::unique_ptr<A> pb;
BOOST_TEST(A::count == 1);
//Equal
BOOST_TEST(!(pa == nullptr));
BOOST_TEST(!(nullptr == pa));
BOOST_TEST((pb == nullptr));
BOOST_TEST((nullptr == pb));
//Unequal
BOOST_TEST((pa != nullptr));
BOOST_TEST((nullptr != pa));
BOOST_TEST(!(pb != nullptr));
BOOST_TEST(!(nullptr != pb));
//Less
BOOST_TEST((pa < nullptr) == (pa.get() < (A*)nullptr));
BOOST_TEST((nullptr < pa) == ((A*)nullptr < pa.get()));
BOOST_TEST((pb < nullptr) == (pb.get() < (A*)nullptr));
BOOST_TEST((nullptr < pb) == ((A*)nullptr < pb.get()));
//Greater
BOOST_TEST((pa > nullptr) == (pa.get() > (A*)nullptr));
BOOST_TEST((nullptr > pa) == ((A*)nullptr > pa.get()));
BOOST_TEST((pb > nullptr) == (pb.get() > (A*)nullptr));
BOOST_TEST((nullptr > pb) == ((A*)nullptr > pb.get()));
//Less or equal
BOOST_TEST((pa <= nullptr) == (pa.get() <= (A*)nullptr));
BOOST_TEST((nullptr <= pa) == ((A*)nullptr <= pa.get()));
BOOST_TEST((pb <= nullptr) == (pb.get() <= (A*)nullptr));
BOOST_TEST((nullptr <= pb) == ((A*)nullptr <= pb.get()));
//Greater or equal
BOOST_TEST((pa >= nullptr) == (pa.get() >= (A*)nullptr));
BOOST_TEST((nullptr >= pa) == ((A*)nullptr >= pa.get()));
BOOST_TEST((pb >= nullptr) == (pb.get() >= (A*)nullptr));
BOOST_TEST((nullptr >= pb) == ((A*)nullptr >= pb.get()));
}
BOOST_TEST(A::count == 0);
#endif //#if !defined(BOOST_NO_CXX11_NULLPTR)
}
} //namespace unique_compare_nullptr{
////////////////////////////////
// main
////////////////////////////////
int main()
{
make_unique_single::test();
make_unique_array::test();
unique_compare::test();
unique_compare_zero::test();
unique_compare_nullptr::test();
//Test results
return boost::report_errors();
}

View File

@@ -0,0 +1,382 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (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/utility_core.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/static_assert.hpp>
#include <boost/move/adl_move_swap.hpp>
#include <boost/core/lightweight_test.hpp>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
#include "unique_ptr_test_utils_beg.hpp"
namespace bml = ::boost::movelib;
////////////////////////////////
// unique_ptr_modifiers_release
////////////////////////////////
namespace unique_ptr_modifiers_release{
void test()
{
//Single unique_ptr
{
bml::unique_ptr<int> p(new int(3));
int* i = p.get();
int* j = p.release();
BOOST_TEST(p.get() == 0);
BOOST_TEST(i == j);
p.reset(j);
}
//Unbounded array unique_ptr
{
bml::unique_ptr<int[]> p(new int[2]);
int* i = p.get();
int* j = p.release();
BOOST_TEST(p.get() == 0);
BOOST_TEST(i == j);
p.reset(j);
}
//Bounded array unique_ptr
{
bml::unique_ptr<int[2]> p(new int[2]);
int* i = p.get();
int* j = p.release();
BOOST_TEST(p.get() == 0);
BOOST_TEST(i == j);
p.reset(j);
}
}
} //namespace unique_ptr_modifiers_release{
////////////////////////////////
// unique_ptr_modifiers_reset
////////////////////////////////
namespace unique_ptr_modifiers_reset{
void test()
{
//Single unique_ptr
{
reset_counters();
{ //reset()
bml::unique_ptr<A> p(new A);
BOOST_TEST(A::count == 1);
A* i = p.get();
::boost::ignore_unused(i);
p.reset();
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
{ //reset(p)
bml::unique_ptr<A> p(new A);
BOOST_TEST(A::count == 1);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(new A);
BOOST_TEST(A::count == 1);
}
BOOST_TEST(A::count == 0);
{ //reset(0)
bml::unique_ptr<A> p(new A);
BOOST_TEST(A::count == 1);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(0);
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
}
//Unbounded array unique_ptr
{
reset_counters();
{ //reset()
bml::unique_ptr<A[]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p.reset();
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
{ //reset(p)
bml::unique_ptr<A[]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(new A[3]);
BOOST_TEST(A::count == 3);
}
BOOST_TEST(A::count == 0);
{ //reset(0)
bml::unique_ptr<A[]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(0);
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
}
{
//Bounded array unique_ptr
reset_counters();
{ //reset()
bml::unique_ptr<A[2]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p.reset();
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
{ //reset(p)
bml::unique_ptr<A[2]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(new A[3]);
BOOST_TEST(A::count == 3);
}
BOOST_TEST(A::count == 0);
{ //reset(0)
bml::unique_ptr<A[2]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(0);
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
}
}
} //namespace unique_ptr_modifiers_reset{
////////////////////////////////
// unique_ptr_modifiers_reset_convert
////////////////////////////////
namespace unique_ptr_modifiers_reset_convert{
void test()
{
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<A> p(new A);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 0);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(new B);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
{
bml::unique_ptr<A> p(new B);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(new B);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<const volatile A[2]> p(new const A[2]);
BOOST_TEST(A::count == 2);
const volatile A* i = p.get();
::boost::ignore_unused(i);
p.reset(new volatile A[3]);
BOOST_TEST(A::count == 3);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A[2]> p(new A[2]);
BOOST_TEST(A::count == 2);
const A* i = p.get();
::boost::ignore_unused(i);
p.reset(new const A[3]);
BOOST_TEST(A::count == 3);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<const volatile A[2]> p(new const A[2]);
BOOST_TEST(A::count == 2);
const volatile A* i = p.get();
::boost::ignore_unused(i);
p.reset(new volatile A[3]);
BOOST_TEST(A::count == 3);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A[2]> p(new A[2]);
BOOST_TEST(A::count == 2);
const A* i = p.get();
::boost::ignore_unused(i);
p.reset(new const A[3]);
BOOST_TEST(A::count == 3);
}
BOOST_TEST(A::count == 0);
}
} //unique_ptr_modifiers_reset_convert
////////////////////////////////
// unique_ptr_modifiers
////////////////////////////////
namespace unique_ptr_modifiers_swap{
// test swap
void test()
{
//Single unique_ptr
reset_counters();
{
A* p1 = new A(1);
move_constr_deleter<A> d1(1);
bml::unique_ptr<A, move_constr_deleter<A> > s1(p1, ::boost::move(d1));
A* p2 = new A(2);
move_constr_deleter<A> d2(2);
bml::unique_ptr<A, move_constr_deleter<A> > s2(p2, ::boost::move(d2));
BOOST_TEST(s1.get() == p1);
BOOST_TEST(*s1 == A(1));
BOOST_TEST(s1.get_deleter().state() == 1);
BOOST_TEST(s2.get() == p2);
BOOST_TEST(*s2 == A(2));
BOOST_TEST(s2.get_deleter().state() == 2);
boost::adl_move_swap(s1, s2);
BOOST_TEST(s1.get() == p2);
BOOST_TEST(*s1 == A(2));
BOOST_TEST(s1.get_deleter().state() == 2);
BOOST_TEST(s2.get() == p1);
BOOST_TEST(*s2 == A(1));
BOOST_TEST(s2.get_deleter().state() == 1);
}
//Unbounded array unique_ptr
reset_counters();
{
A* p1 = new A[2];
p1[0].set(1);
p1[1].set(2);
move_constr_deleter<A[]> d1(1);
bml::unique_ptr<A[], move_constr_deleter<A[]> > s1(p1, ::boost::move(d1));
A* p2 = new A[2];
p2[0].set(3);
p2[1].set(4);
move_constr_deleter<A[]> d2(2);
bml::unique_ptr<A[], move_constr_deleter<A[]> > s2(p2, ::boost::move(d2));
BOOST_TEST(s1.get() == p1);
BOOST_TEST(s1[0] == A(1));
BOOST_TEST(s1[1] == A(2));
BOOST_TEST(s1.get_deleter().state() == 1);
BOOST_TEST(s2.get() == p2);
BOOST_TEST(s2[0] == A(3));
BOOST_TEST(s2[1] == A(4));
BOOST_TEST(s2.get_deleter().state() == 2);
swap(s1, s2);
BOOST_TEST(s1.get() == p2);
BOOST_TEST(s1[0] == A(3));
BOOST_TEST(s1[1] == A(4));
BOOST_TEST(s1.get_deleter().state() == 2);
BOOST_TEST(s2.get() == p1);
BOOST_TEST(s2[0] == A(1));
BOOST_TEST(s2[1] == A(2));
BOOST_TEST(s2.get_deleter().state() == 1);
}
//Bounded array unique_ptr
reset_counters();
{
A* p1 = new A[2];
p1[0].set(1);
p1[1].set(2);
move_constr_deleter<A[2]> d1(1);
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s1(p1, ::boost::move(d1));
A* p2 = new A[2];
p2[0].set(3);
p2[1].set(4);
move_constr_deleter<A[2]> d2(2);
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s2(p2, ::boost::move(d2));
BOOST_TEST(s1.get() == p1);
BOOST_TEST(s1[0] == A(1));
BOOST_TEST(s1[1] == A(2));
BOOST_TEST(s1.get_deleter().state() == 1);
BOOST_TEST(s2.get() == p2);
BOOST_TEST(s2[0] == A(3));
BOOST_TEST(s2[1] == A(4));
BOOST_TEST(s2.get_deleter().state() == 2);
swap(s1, s2);
BOOST_TEST(s1.get() == p2);
BOOST_TEST(s1[0] == A(3));
BOOST_TEST(s1[1] == A(4));
BOOST_TEST(s1.get_deleter().state() == 2);
BOOST_TEST(s2.get() == p1);
BOOST_TEST(s2[0] == A(1));
BOOST_TEST(s2[1] == A(2));
BOOST_TEST(s2.get_deleter().state() == 1);
}
}
} //namespace unique_ptr_modifiers_swap{
////////////////////////////////
// main
////////////////////////////////
int main()
{
//Modifiers
unique_ptr_modifiers_release::test();
unique_ptr_modifiers_reset::test();
unique_ptr_modifiers_reset_convert::test();
unique_ptr_modifiers_swap::test();
//Test results
return boost::report_errors();
}
#include "unique_ptr_test_utils_end.hpp"

View File

@@ -0,0 +1,517 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (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/utility_core.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/lightweight_test.hpp>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
#include "unique_ptr_test_utils_beg.hpp"
namespace bml = ::boost::movelib;
namespace bmupmu = ::boost::move_upmu;
////////////////////////////////
// unique_ptr_ctor_move_defdel
////////////////////////////////
namespace unique_ptr_ctor_move_defdel{
// test converting move ctor. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
void test()
{
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<A> s(new A);
A* p = s.get();
bml::unique_ptr<A> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 1);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[]> s(new A[2]);
A* p = s.get();
bml::unique_ptr<A[]> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[2]> s(new A[2]);
A* p = s.get();
bml::unique_ptr<A[2]> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_move_defdel{
////////////////////////////////
// unique_ptr_ctor_move_movedel
////////////////////////////////
namespace unique_ptr_ctor_move_movedel{
// test converting move ctor. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
void test()
{
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<A, move_constr_deleter<A> > s(new A);
A* p = s.get();
bml::unique_ptr<A, move_constr_deleter<A> > s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 1);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[], move_constr_deleter<A[]> > s(new A[2]);
A* p = s.get();
bml::unique_ptr<A[], move_constr_deleter<A[]> > s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[2]> s(new A[2]);
A* p = s.get();
bml::unique_ptr<A[2]> s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_move_movedel{
////////////////////////////////
// unique_ptr_ctor_move_dfctrdelref
////////////////////////////////
namespace unique_ptr_ctor_move_dfctrdelref{
// test converting move ctor. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
void test()
{
//Single unique_ptr
reset_counters();
{
def_constr_deleter<A> d;
bml::unique_ptr<A, def_constr_deleter<A>&> s(new A, d);
A* p = s.get();
bml::unique_ptr<A, def_constr_deleter<A>&> s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 1);
d.set_state(6);
BOOST_TEST(s2.get_deleter().state() == d.state());
BOOST_TEST(s.get_deleter().state() == d.state());
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
def_constr_deleter<A[]> d;
bml::unique_ptr<A[], def_constr_deleter<A[]>&> s(new A[2], d);
A* p = s.get();
bml::unique_ptr<A[], def_constr_deleter<A[]>&> s2 = boost::move(s);
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
d.set_state(6);
BOOST_TEST(s2.get_deleter().state() == d.state());
BOOST_TEST(s.get_deleter().state() == d.state());
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
def_constr_deleter<A[2]> d;
bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> s(new A[2], d);
A* p = s.get();
bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
d.set_state(6);
BOOST_TEST(s2.get_deleter().state() == d.state());
BOOST_TEST(s.get_deleter().state() == d.state());
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_move_dfctrdelref{
////////////////////////////////
// unique_ptr_ctor_move_convert_defdel
////////////////////////////////
namespace unique_ptr_ctor_move_convert_defdel{
// test converting move ctor. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
void test()
{
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<B> s(new B);
A* p = s.get();
bml::unique_ptr<A> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[]> s(new A[2]);
A* p = s.get();
bml::unique_ptr<const volatile A[]> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[2]> s(new A[2]);
A* p = s.get();
bml::unique_ptr<const volatile A[2]> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[2]> s(new A[2]);
A* p = s.get();
bml::unique_ptr<const volatile A[]> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_move_convert_defdel{
////////////////////////////////
// unique_ptr_ctor_move_convert_movedel
////////////////////////////////
namespace unique_ptr_ctor_move_convert_movedel{
// test converting move ctor. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
void test()
{
//Single unique_ptr
reset_counters();
BOOST_STATIC_ASSERT((bmupmu::is_convertible<B, A>::value));
{
bml::unique_ptr<B, move_constr_deleter<B> > s(new B);
A* p = s.get();
bml::unique_ptr<A, move_constr_deleter<A> > s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<const A[], move_constr_deleter<const A[]> > s(new const A[2]);
const A* p = s.get();
bml::unique_ptr<const volatile A[], move_constr_deleter<const volatile A[]> > s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<const A[2], move_constr_deleter<const A[2]> > s(new const A[2]);
const A* p = s.get();
bml::unique_ptr<const volatile A[2], move_constr_deleter<const volatile A[2]> > s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
{
bml::unique_ptr<const A[2], move_constr_deleter<const A[2]> > s(new const A[2]);
const A* p = s.get();
bml::unique_ptr<const volatile A[], move_constr_deleter<const volatile A[]> > s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
BOOST_TEST(s2.get_deleter().state() == 5);
BOOST_TEST(s.get_deleter().state() == 0);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
}
} //namespace unique_ptr_ctor_move_convert_movedel{
////////////////////////////////
// unique_ptr_ctor_move_convert_dfctrdelref
////////////////////////////////
namespace unique_ptr_ctor_move_convert_dfctrdelref{
// test converting move ctor. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
void test()
{
//Single unique_ptr
reset_counters();
{
def_constr_deleter<A> d;
bml::unique_ptr<B, def_constr_deleter<A>&> s(new B, d);
A* p = s.get();
bml::unique_ptr<A, def_constr_deleter<A>&> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
d.set_state(6);
BOOST_TEST(s2.get_deleter().state() == d.state());
BOOST_TEST(s.get_deleter().state() == d.state());
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
def_constr_deleter<volatile A[]> d;
bml::unique_ptr<A[], def_constr_deleter<volatile A[]>&> s(new A[2], d);
A* p = s.get();
bml::unique_ptr<volatile A[], def_constr_deleter<volatile A[]>&> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
d.set_state(6);
BOOST_TEST(s2.get_deleter().state() == d.state());
BOOST_TEST(s.get_deleter().state() == d.state());
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
def_constr_deleter<volatile A[2]> d;
bml::unique_ptr<A[2], def_constr_deleter<volatile A[2]>&> s(new A[2], d);
A* p = s.get();
bml::unique_ptr<volatile A[2], def_constr_deleter<volatile A[2]>&> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
d.set_state(6);
BOOST_TEST(s2.get_deleter().state() == d.state());
BOOST_TEST(s.get_deleter().state() == d.state());
}
BOOST_TEST(A::count == 0);
{
def_constr_deleter<volatile A[]> d;
bml::unique_ptr<A[2], def_constr_deleter<volatile A[]>&> s(new A[2], d);
A* p = s.get();
bml::unique_ptr<volatile A[], def_constr_deleter<volatile A[]>&> s2(boost::move(s));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s.get() == 0);
BOOST_TEST(A::count == 2);
d.set_state(6);
BOOST_TEST(s2.get_deleter().state() == d.state());
BOOST_TEST(s.get_deleter().state() == d.state());
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_move_convert_dfctrdelref{
////////////////////////////////
// unique_ptr_ctor_move_sourcesink
////////////////////////////////
namespace unique_ptr_ctor_move_sourcesink{
// test move ctor. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
bml::unique_ptr<A> source1()
{ return bml::unique_ptr<A>(new A); }
bml::unique_ptr<A[]> source1_unbounded_array()
{ return bml::unique_ptr<A[]> (new A[2]); }
bml::unique_ptr<A[2]> source1_bounded_array()
{ return bml::unique_ptr<A[2]> (new A[2]); }
void sink1(bml::unique_ptr<A>)
{}
void sink1_unbounded_array(bml::unique_ptr<A[]>)
{}
void sink1_bounded_array(bml::unique_ptr<A[2]>)
{}
bml::unique_ptr<A, move_constr_deleter<A> > source2()
{ return bml::unique_ptr<A, move_constr_deleter<A> > (new A); }
bml::unique_ptr<A[], move_constr_deleter<A[]> > source2_unbounded_array()
{ return bml::unique_ptr<A[], move_constr_deleter<A[]> >(new A[2]); }
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > source2_bounded_array()
{ return bml::unique_ptr<A[2], move_constr_deleter<A[2]> >(new A[2]); }
void sink2(bml::unique_ptr<A, move_constr_deleter<A> >)
{}
void sink2_unbounded_array(bml::unique_ptr<A[], move_constr_deleter<A[]> >)
{}
void sink2_bounded_array(bml::unique_ptr<A[2], move_constr_deleter<A[2]> >)
{}
bml::unique_ptr<A, def_constr_deleter<A>&> source3()
{
static def_constr_deleter<A> d;
return bml::unique_ptr<A, def_constr_deleter<A>&>(new A, d);
}
bml::unique_ptr<A[], def_constr_deleter<A[]>&> source3_unbounded_array()
{
static def_constr_deleter<A[]> d;
return bml::unique_ptr<A[], def_constr_deleter<A[]>&>(new A[2], d);
}
bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> source3_bounded_array()
{
static def_constr_deleter<A[2]> d;
return bml::unique_ptr<A[2], def_constr_deleter<A[2]>&>(new A[2], d);
}
void sink3(bml::unique_ptr<A, def_constr_deleter<A>&> )
{}
void sink3_unbounded_array(bml::unique_ptr<A[], def_constr_deleter<A[]>&> )
{}
void sink3_bounded_array(bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> )
{}
void test()
{
//Single unique_ptr
reset_counters();
sink1(source1());
sink2(source2());
sink3(source3());
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
sink1_unbounded_array(source1_unbounded_array());
sink2_unbounded_array(source2_unbounded_array());
sink3_unbounded_array(source3_unbounded_array());
BOOST_TEST(A::count == 0);
//Bbounded array unique_ptr
reset_counters();
sink1_bounded_array(source1_bounded_array());
sink2_bounded_array(source2_bounded_array());
sink3_bounded_array(source3_bounded_array());
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_move_sourcesink{
////////////////////////////////
// main
////////////////////////////////
int main()
{
//Move Constructor
unique_ptr_ctor_move_defdel::test();
unique_ptr_ctor_move_movedel::test();
unique_ptr_ctor_move_dfctrdelref::test();
unique_ptr_ctor_move_convert_defdel::test();
unique_ptr_ctor_move_convert_movedel::test();
unique_ptr_ctor_move_convert_dfctrdelref::test();
unique_ptr_ctor_move_sourcesink::test();
//Test results
return boost::report_errors();
}
#include "unique_ptr_test_utils_end.hpp"

View File

@@ -0,0 +1,229 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (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/utility_core.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/lightweight_test.hpp>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
#include "unique_ptr_test_utils_beg.hpp"
namespace bml = ::boost::movelib;
////////////////////////////////
// unique_ptr_zero
////////////////////////////////
namespace unique_ptr_zero {
// test initialization/assignment from zero
void test()
{
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<A> s2(0);
BOOST_TEST(A::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A> s2(new A);
BOOST_TEST(A::count == 1);
s2 = 0;
BOOST_TEST(A::count == 0);
BOOST_TEST(s2.get() == 0);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
{
bml::unique_ptr<A[]> s2(0);
BOOST_TEST(A::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[]> s2(new A[2]);
BOOST_TEST(A::count == 2);
s2 = 0;
BOOST_TEST(A::count == 0);
BOOST_TEST(s2.get() == 0);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
{
bml::unique_ptr<A[2]> s2(0);
BOOST_TEST(A::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[2]> s2(new A[2]);
BOOST_TEST(A::count == 2);
s2 = 0;
BOOST_TEST(A::count == 0);
BOOST_TEST(s2.get() == 0);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_zero {
////////////////////////////////
// unique_ptr_nullptr
////////////////////////////////
namespace unique_ptr_nullptr{
void test()
{
#if !defined(BOOST_NO_CXX11_NULLPTR)
//Single unique_ptr
reset_counters();
{
bml::unique_ptr<A> p(new A);
BOOST_TEST(A::count == 1);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(nullptr);
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A> p(new A);
BOOST_TEST(A::count == 1);
A* i = p.get();
::boost::ignore_unused(i);
p = nullptr;
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A> pi(nullptr);
BOOST_TEST(pi.get() == nullptr);
BOOST_TEST(pi.get() == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A> pi(nullptr, bml::unique_ptr<A>::deleter_type());
BOOST_TEST(pi.get() == nullptr);
BOOST_TEST(pi.get() == 0);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(nullptr);
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p = nullptr;
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[]> pi(nullptr);
BOOST_TEST(pi.get() == nullptr);
BOOST_TEST(pi.get() == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[]> pi(nullptr, bml::unique_ptr<A[]>::deleter_type());
BOOST_TEST(pi.get() == nullptr);
BOOST_TEST(pi.get() == 0);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
bml::unique_ptr<A[2]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p.reset(nullptr);
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[2]> p(new A[2]);
BOOST_TEST(A::count == 2);
A* i = p.get();
::boost::ignore_unused(i);
p = nullptr;
BOOST_TEST(A::count == 0);
BOOST_TEST(p.get() == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[2]> pi(nullptr);
BOOST_TEST(pi.get() == nullptr);
BOOST_TEST(pi.get() == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<A[2]> pi(nullptr, bml::unique_ptr<A[2]>::deleter_type());
BOOST_TEST(pi.get() == nullptr);
BOOST_TEST(pi.get() == 0);
}
BOOST_TEST(A::count == 0);
#endif
}
} //namespace unique_ptr_nullptr{
////////////////////////////////
// main
////////////////////////////////
int main()
{
//nullptr
unique_ptr_zero::test();
unique_ptr_nullptr::test();
//Test results
return boost::report_errors();
}
#include "unique_ptr_test_utils_end.hpp"

View File

@@ -0,0 +1,287 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (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/utility_core.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/lightweight_test.hpp>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
#include "unique_ptr_test_utils_beg.hpp"
namespace bml = ::boost::movelib;
////////////////////////////////
// unique_ptr_observers_dereference
////////////////////////////////
namespace unique_ptr_observers_dereference{
void test()
{
//Single unique_ptr
{
bml::unique_ptr<int> p(new int(3));
BOOST_TEST(*p == 3);
}
//Unbounded array unique_ptr
{
int *pi = new int[2];
pi[0] = 3;
pi[1] = 4;
bml::unique_ptr<int[]> p(pi);
BOOST_TEST(p[0] == 3);
BOOST_TEST(p[1] == 4);
}
//Bounded array unique_ptr
{
int *pi = new int[2];
pi[0] = 3;
pi[1] = 4;
bml::unique_ptr<int[2]> p(pi);
BOOST_TEST(p[0] == 3);
BOOST_TEST(p[1] == 4);
}
}
} //namespace unique_ptr_observers_dereference{
////////////////////////////////
// unique_ptr_observers_dereference
////////////////////////////////
namespace unique_ptr_observers_explicit_bool{
void test()
{
//Single unique_ptr
{
bml::unique_ptr<int> p(new int(3));
if (p)
;
else
BOOST_TEST(false);
if (!p)
BOOST_TEST(false);
}
{
bml::unique_ptr<int> p;
if (!p)
;
else
BOOST_TEST(false);
if (p)
BOOST_TEST(false);
}
//Unbounded array unique_ptr
{
bml::unique_ptr<int[]> p(new int[2]);
if (p)
;
else
BOOST_TEST(false);
if (!p)
BOOST_TEST(false);
}
{
bml::unique_ptr<int[]> p;
if (!p)
;
else
BOOST_TEST(false);
if (p)
BOOST_TEST(false);
}
//Bounded array unique_ptr
{
bml::unique_ptr<int[2]> p(new int[2]);
if (p)
;
else
BOOST_TEST(false);
if (!p)
BOOST_TEST(false);
}
{
bml::unique_ptr<int[2]> p;
if (!p)
;
else
BOOST_TEST(false);
if (p)
BOOST_TEST(false);
}
}
} //namespace unique_ptr_observers_explicit_bool{
////////////////////////////////
// unique_ptr_observers_get
////////////////////////////////
namespace unique_ptr_observers_get{
void test()
{
//Single unique_ptr
{
int* p = new int;
bml::unique_ptr<int> s(p);
BOOST_TEST(s.get() == p);
}
//Unbounded array unique_ptr
{
int* p = new int[2];
bml::unique_ptr<int[]> s(p);
BOOST_TEST(s.get() == p);
}
{
int* p = new int[2];
bml::unique_ptr<int[2]> s(p);
BOOST_TEST(s.get() == p);
}
//Bounded array unique_ptr
{
int *pi = new int[2];
pi[0] = 3;
pi[1] = 4;
bml::unique_ptr<int[2]> p(pi);
BOOST_TEST(p[0] == 3);
BOOST_TEST(p[1] == 4);
}
}
} //namespace unique_ptr_observers_get{
////////////////////////////////
// unique_ptr_observers_get_deleter
////////////////////////////////
namespace unique_ptr_observers_get_deleter{
struct Deleter
{
void operator()(void*) {}
int test() {return 5;}
int test() const {return 6;}
};
void test()
{
//Single unique_ptr
{
bml::unique_ptr<int, Deleter> p;
BOOST_TEST(p.get_deleter().test() == 5);
}
{
const bml::unique_ptr<int, Deleter> p;
BOOST_TEST(p.get_deleter().test() == 6);
}
//Unbounded array unique_ptr
{
bml::unique_ptr<int[], Deleter> p;
BOOST_TEST(p.get_deleter().test() == 5);
}
{
const bml::unique_ptr<int[], Deleter> p;
BOOST_TEST(p.get_deleter().test() == 6);
}
//Bounded array unique_ptr
{
bml::unique_ptr<int[2], Deleter> p;
BOOST_TEST(p.get_deleter().test() == 5);
}
{
const bml::unique_ptr<int[2], Deleter> p;
BOOST_TEST(p.get_deleter().test() == 6);
}
}
} //namespace unique_ptr_observers_get_deleter{
////////////////////////////////
// unique_ptr_observers_op_arrow
////////////////////////////////
namespace unique_ptr_observers_op_arrow{
void test()
{
//Single unique_ptr
{
bml::unique_ptr<A> p(new A);
BOOST_TEST(p->state_ == 999);
}
}
} //namespace unique_ptr_observers_op_arrow{
namespace unique_ptr_observers_op_index{
void test()
{
//Unbounded array unique_ptr
{
A *pa = new A[2];
//pa[0] is left default constructed
pa[1].set(888);
bml::unique_ptr<A[]> p(pa);
BOOST_TEST(p[0].state_ == 999);
BOOST_TEST(p[1].state_ == 888);
}
//Bounded array unique_ptr
{
A *pa = new A[2];
//pa[0] is left default constructed
pa[1].set(888);
bml::unique_ptr<A[2]> p(pa);
BOOST_TEST(p[0].state_ == 999);
BOOST_TEST(p[1].state_ == 888);
}
}
} //namespace unique_ptr_observers_op_index{
////////////////////////////////
// main
////////////////////////////////
int main()
{
//Observers
unique_ptr_observers_dereference::test();
unique_ptr_observers_explicit_bool::test();
unique_ptr_observers_get::test();
unique_ptr_observers_get_deleter::test();
unique_ptr_observers_op_arrow::test();
unique_ptr_observers_op_index::test();
//Test results
return boost::report_errors();
}
#include "unique_ptr_test_utils_end.hpp"

View File

@@ -0,0 +1,30 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (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.
//
//////////////////////////////////////////////////////////////////////////////
#define BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
#include <boost/move/unique_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
////////////////////////////////
// main
////////////////////////////////
int main()
{
//Just test compilation errors
boost::movelib::unique_ptr<int> a, b(boost::move(a));
BOOST_TEST(!(b.get() || a.get()));
b = boost::move(a);
b.release();
BOOST_TEST(!(b.get() || a.get()));
//Test results
return boost::report_errors();
}

View File

@@ -0,0 +1,210 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (C) Copyright Ion Gaztanaga 2014-2014.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP
#define BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP
#include <boost/move/core.hpp>
#include <boost/move/detail/unique_ptr_meta_utils.hpp>
#include <boost/static_assert.hpp>
#include <cstddef>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
//A deleter that can only default constructed
template <class T>
class def_constr_deleter
{
int state_;
def_constr_deleter(const def_constr_deleter&);
def_constr_deleter& operator=(const def_constr_deleter&);
public:
typedef typename ::boost::move_upmu::remove_extent<T>::type element_type;
static const bool is_array = ::boost::move_upmu::is_array<T>::value;
def_constr_deleter() : state_(5) {}
explicit def_constr_deleter(int s) : state_(s) {}
int state() const {return state_;}
void set_state(int s) {state_ = s;}
void operator()(element_type* p) const
{ is_array ? delete []p : delete p; }
void operator()(element_type* p)
{ ++state_; is_array ? delete []p : delete p; }
};
//A deleter that can be copy constructed
template <class T>
class copy_constr_deleter
{
int state_;
public:
typedef typename ::boost::move_upmu::remove_extent<T>::type element_type;
static const bool is_array = ::boost::move_upmu::is_array<T>::value;
copy_constr_deleter() : state_(5) {}
template<class U>
copy_constr_deleter(const copy_constr_deleter<U>&
, typename boost::move_upd::enable_def_del<U, T>::type* =0)
{ state_ = 5; }
explicit copy_constr_deleter(int s) : state_(s) {}
template <class U>
typename boost::move_upd::enable_def_del<U, T, copy_constr_deleter&>::type
operator=(const copy_constr_deleter<U> &d)
{
state_ = d.state();
return *this;
}
int state() const {return state_;}
void set_state(int s) {state_ = s;}
void operator()(element_type* p) const
{ is_array ? delete []p : delete p; }
void operator()(element_type* p)
{ ++state_; is_array ? delete []p : delete p; }
};
//A deleter that can be only move constructed
template <class T>
class move_constr_deleter
{
int state_;
BOOST_MOVABLE_BUT_NOT_COPYABLE(move_constr_deleter)
public:
typedef typename ::boost::move_upmu::remove_extent<T>::type element_type;
static const bool is_array = ::boost::move_upmu::is_array<T>::value;
move_constr_deleter() : state_(5) {}
move_constr_deleter(BOOST_RV_REF(move_constr_deleter) r)
: state_(r.state_)
{ r.state_ = 0; }
explicit move_constr_deleter(int s) : state_(s) {}
template <class U>
move_constr_deleter(BOOST_RV_REF(move_constr_deleter<U>) d
, typename boost::move_upd::enable_def_del<U, T>::type* =0)
: state_(d.state())
{ d.set_state(0); }
move_constr_deleter& operator=(BOOST_RV_REF(move_constr_deleter) r)
{
state_ = r.state_;
r.state_ = 0;
return *this;
}
template <class U>
typename boost::move_upd::enable_def_del<U, T, move_constr_deleter&>::type
operator=(BOOST_RV_REF(move_constr_deleter<U>) d)
{
state_ = d.state();
d.set_state(0);
return *this;
}
int state() const {return state_;}
void set_state(int s) {state_ = s;}
void operator()(element_type* p) const
{ is_array ? delete []p : delete p; }
void operator()(element_type* p)
{ ++state_; is_array ? delete []p : delete p; }
friend bool operator==(const move_constr_deleter& x, const move_constr_deleter& y)
{return x.state_ == y.state_;}
};
//A base class containing state with a static instance counter
struct A
{
int state_;
static int count;
A() : state_(999) {++count;}
explicit A(int i) : state_(i) {++count;}
A(const A& a) : state_(a.state_) {++count;}
A& operator=(const A& a) { state_ = a.state_; return *this; }
void set(int i) {state_ = i;}
virtual ~A() {--count;}
friend bool operator==(const A& x, const A& y) { return x.state_ == y.state_; }
};
int A::count = 0;
//A class derived from A with a static instance counter
struct B
: public A
{
static int count;
B() : A() {++count;}
B(const B &b) : A(b) {++count;}
virtual ~B() {--count;}
};
int B::count = 0;
void reset_counters();
BOOST_STATIC_ASSERT((::boost::move_upmu::is_convertible<B, A>::value));
//Incomplete Type function declarations
struct I;
void check(int i);
I* get();
I* get_array(std::size_t i);
#include <boost/move/unique_ptr.hpp>
template <class T, class D = ::boost::movelib::default_delete<T> >
struct J
{
typedef boost::movelib::unique_ptr<T, D> unique_ptr_type;
typedef typename unique_ptr_type::element_type element_type;
boost::movelib::unique_ptr<T, D> a_;
J() {}
explicit J(element_type*a) : a_(a) {}
~J();
element_type* get() const {return a_.get();}
D& get_deleter() {return a_.get_deleter();}
};
#endif //BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP

View File

@@ -0,0 +1,46 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (C) Copyright Ion Gaztanaga 2014-2014.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_END_HPP
#define BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_END_HPP
#ifndef BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP
#error "unique_ptr_test_utils_beg.hpp MUST be included before this header"
#endif
//Define the incomplete I type and out of line functions
struct I
{
static int count;
I() {++count;}
I(const A&) {++count;}
~I() {--count;}
};
int I::count = 0;
I* get() {return new I;}
I* get_array(std::size_t i) {return new I[i];}
void check(int i)
{
BOOST_TEST(I::count == i);
}
template <class T, class D>
J<T, D>::~J() {}
void reset_counters()
{ A::count = 0; B::count = 0; I::count = 0; }
#endif //BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_END_HPP

View File

@@ -0,0 +1,200 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (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/utility_core.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/move/detail/type_traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/lightweight_test.hpp>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
#include "unique_ptr_test_utils_beg.hpp"
namespace bml = ::boost::movelib;
namespace bmupmu = ::boost::move_upmu;
////////////////////////////////
// unique_ptr_pointer_type
////////////////////////////////
namespace unique_ptr_pointer_type {
struct Deleter
{
struct pointer {};
};
// Test unique_ptr::pointer type
void test()
{
//Single unique_ptr
{
typedef bml::unique_ptr<int> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, int*>::value));
}
{
typedef bml::unique_ptr<int, Deleter> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, Deleter::pointer>::value));
}
//Unbounded array unique_ptr
{
typedef bml::unique_ptr<int[]> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, int*>::value));
}
{
typedef bml::unique_ptr<int[], Deleter> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, Deleter::pointer>::value));
}
//Bounded array unique_ptr
{
typedef bml::unique_ptr<int[5]> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, int*>::value));
}
{
typedef bml::unique_ptr<int[5], Deleter> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, Deleter::pointer>::value));
}
//Unbounded array of bounded array unique_ptr
{
typedef int int_5_t [5];
typedef bml::unique_ptr<int_5_t[]> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, int_5_t*>::value));
}
{
typedef int int_5_t [5];
typedef bml::unique_ptr<int_5_t[], Deleter> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::pointer, Deleter::pointer>::value));
}
}
} //namespace unique_ptr_pointer_type {
////////////////////////////////
// unique_ptr_deleter_type
////////////////////////////////
namespace unique_ptr_deleter_type {
struct Deleter
{};
// Test unique_ptr::deleter type
void test()
{
//Single unique_ptr
{
typedef bml::unique_ptr<int> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, bml::default_delete<int> >::value));
}
{
typedef bml::unique_ptr<int, Deleter> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, Deleter >::value));
}
//Unbounded array unique_ptr
{
typedef bml::unique_ptr<int[]> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, bml::default_delete<int[]> >::value));
}
{
typedef bml::unique_ptr<int[], Deleter> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, Deleter >::value));
}
//Bounded array unique_ptr
{
typedef bml::unique_ptr<int[2]> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, bml::default_delete<int[2]> >::value));
}
{
typedef bml::unique_ptr<int[2], Deleter> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::deleter_type, Deleter >::value));
}
}
} //namespace unique_ptr_deleter_type {
////////////////////////////////
// unique_ptr_element_type
////////////////////////////////
namespace unique_ptr_element_type {
// Test unique_ptr::deleter type
void test()
{
//Single unique_ptr
{
typedef bml::unique_ptr<const int> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::element_type, const int>::value));
}
//Unbounded array unique_ptr
{
typedef bml::unique_ptr<const int[]> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::element_type, const int>::value));
}
//Bounded array unique_ptr
{
typedef bml::unique_ptr<const int[2]> P;
BOOST_STATIC_ASSERT((bmupmu::is_same<P::element_type, const int>::value));
}
}
} //namespace unique_ptr_element_type {
////////////////////////////////
// unique_ptr_construct_assign_traits
////////////////////////////////
namespace unique_ptr_construct_assign_traits {
void test()
{
typedef bml::unique_ptr<int> unique_ptr_t;
//Even if BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE is not defined
//boost::unique_ptr shall work with boost::movelib traits
BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_constructible<unique_ptr_t>::value));
//Even if BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE is not defined
//boost::unique_ptr shall work with boost::movelib traits
BOOST_STATIC_ASSERT(!(boost::move_detail::is_copy_assignable<unique_ptr_t>::value));
//Important traits for containers like boost::vector
BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_constructible<unique_ptr_t>::value));
BOOST_STATIC_ASSERT(!(boost::move_detail::is_trivially_copy_assignable<unique_ptr_t>::value));
}
} //namespace unique_ptr_construct_assign_traits {
////////////////////////////////
// main
////////////////////////////////
int main()
{
//General
unique_ptr_pointer_type::test();
unique_ptr_deleter_type::test();
unique_ptr_element_type::test();
unique_ptr_construct_assign_traits::test();
//Test results
return boost::report_errors();
}
#include "unique_ptr_test_utils_end.hpp"