diff options
Diffstat (limited to 'src/boost/libs/move/test')
31 files changed, 7863 insertions, 0 deletions
diff --git a/src/boost/libs/move/test/Jamfile.v2 b/src/boost/libs/move/test/Jamfile.v2 new file mode 100644 index 00000000..472517bd --- /dev/null +++ b/src/boost/libs/move/test/Jamfile.v2 @@ -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) /boost/timer//boost_timer + : # additional args + : # test-files + : # requirements + ] ; + } + + return $(all_rules) ; +} + +test-suite move_test : [ test_all r ] ; + diff --git a/src/boost/libs/move/test/adaptive_merge_test.cpp b/src/boost/libs/move/test/adaptive_merge_test.cpp new file mode 100644 index 00000000..1a647076 --- /dev/null +++ b/src/boost/libs/move/test/adaptive_merge_test.cpp @@ -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/move/algo/detail/merge_sort.hpp> + +#include "order_type.hpp" +#include "random_shuffle.hpp" + +#include <boost/move/algo/adaptive_merge.hpp> +#include <boost/move/core.hpp> + + +template<class T> +bool test_random_shuffled(std::size_t const element_count, std::size_t const num_keys, std::size_t const num_iter) +{ + boost::movelib::unique_ptr<T[]> elements(new T[element_count]); + boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[num_keys ? num_keys : element_count]); + std::cout << "- - N: " << element_count << ", Keys: " << num_keys << ", It: " << num_iter << " \n"; + + //Initialize keys + for(std::size_t i=0; i < element_count; ++i){ + std::size_t key = num_keys ? (i % num_keys) : i; + elements[i].key=key; + } + + std::srand(0); + + for (std::size_t i = 0; i != num_iter; ++i) + { + ::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(), (T*)buf.get()); + boost::movelib::merge_sort(elements.get()+split, elements.get()+element_count, order_type_less(), (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"; + throw int(0); + } + } + 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; +} diff --git a/src/boost/libs/move/test/adaptive_sort_test.cpp b/src/boost/libs/move/test/adaptive_sort_test.cpp new file mode 100644 index 00000000..973dd4c3 --- /dev/null +++ b/src/boost/libs/move/test/adaptive_sort_test.cpp @@ -0,0 +1,84 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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> + +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"; + throw int(0); + } + } + 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; + 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; +} diff --git a/src/boost/libs/move/test/adl_move_swap.cpp b/src/boost/libs/move/test/adl_move_swap.cpp new file mode 100644 index 00000000..200c6cb6 --- /dev/null +++ b/src/boost/libs/move/test/adl_move_swap.cpp @@ -0,0 +1,169 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include <boost/move/detail/config_begin.hpp> +#include <boost/move/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(); +} +#include <boost/move/detail/config_end.hpp> diff --git a/src/boost/libs/move/test/algo_test.cpp b/src/boost/libs/move/test/algo_test.cpp new file mode 100644 index 00000000..d4652e2e --- /dev/null +++ b/src/boost/libs/move/test/algo_test.cpp @@ -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(); +} diff --git a/src/boost/libs/move/test/back_move_inserter.cpp b/src/boost/libs/move/test/back_move_inserter.cpp new file mode 100644 index 00000000..6fc4829c --- /dev/null +++ b/src/boost/libs/move/test/back_move_inserter.cpp @@ -0,0 +1,80 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/detail/config_begin.hpp> +// 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; +} + +#include <boost/move/detail/config_end.hpp> diff --git a/src/boost/libs/move/test/bench_merge.cpp b/src/boost/libs/move/test/bench_merge.cpp new file mode 100644 index 00000000..2ef34400 --- /dev/null +++ b/src/boost/libs/move/test/bench_merge.cpp @@ -0,0 +1,335 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/move/unique_ptr.hpp> +#include <boost/timer/timer.hpp> + +#include "order_type.hpp" +#include "random_shuffle.hpp" + +using boost::timer::cpu_timer; +using boost::timer::cpu_times; +using boost::timer::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)/element_count, double(order_perf_type::num_copy)/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, reinterpret_cast<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, reinterpret_cast<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)/element_count, double(order_perf_type::num_copy)/element_count ); + + double time = double(new_clock); + + const char *units = "ns"; + if(time >= 1000000000.0){ + time /= 1000000000.0; + units = " s"; + } + else if(time >= 1000000.0){ + time /= 1000000.0; + units = "ms"; + } + else if(time >= 1000.0){ + time /= 1000.0; + units = "us"; + } + + std::printf(" %6.02f%s (%6.02f)\n" + , time + , units + , prev_clock ? double(new_clock)/double(prev_clock): 1.0); + prev_clock = new_clock; + bool res = 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) + throw int(0); + return res; +} + +//Undef it to run the long test +#define BENCH_MERGE_SHORT +#define BENCH_SORT_UNIQUE_VALUES + +int main() +{ + try{ + #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 + } + catch(...) + { + return 1; + } + + return 0; +} + diff --git a/src/boost/libs/move/test/bench_sort.cpp b/src/boost/libs/move/test/bench_sort.cpp new file mode 100644 index 00000000..11aba354 --- /dev/null +++ b/src/boost/libs/move/test/bench_sort.cpp @@ -0,0 +1,377 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/timer/timer.hpp> + +using boost::timer::cpu_timer; +using boost::timer::cpu_times; +using boost::timer::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)/element_count, double(order_perf_type::num_copy)/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, reinterpret_cast<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, reinterpret_cast<T*>(mem.get()), BufLen); +} + +template<class T, class Compare> +void merge_sort_buffered(T *elements, std::size_t element_count, Compare comp) +{ + boost::movelib::unique_ptr<char[]> mem(new char[sizeof(T)*((element_count+1)/2)]); + boost::movelib::merge_sort(elements, elements + element_count, comp, reinterpret_cast<T*>(mem.get())); +} + +enum AlgoType +{ + MergeSort, + StableSort, + 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)/element_count, double(order_perf_type::num_copy)/element_count ); + + double time = double(new_clock); + + const char *units = "ns"; + if(time >= 1000000000.0){ + time /= 1000000000.0; + units = " s"; + } + else if(time >= 1000000.0){ + time /= 1000000.0; + units = "ms"; + } + else if(time >= 1000.0){ + time /= 1000.0; + units = "us"; + } + + std::printf(" %6.02f%s (%6.02f)\n" + , time + , units + , prev_clock ? double(new_clock)/double(prev_clock): 1.0); + prev_clock = new_clock; + bool res = 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) + throw int(0); + 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; +} diff --git a/src/boost/libs/move/test/construct_forward.cpp b/src/boost/libs/move/test/construct_forward.cpp new file mode 100644 index 00000000..87c9a809 --- /dev/null +++ b/src/boost/libs/move/test/construct_forward.cpp @@ -0,0 +1,117 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/detail/config_begin.hpp> +#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) x + #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + ,typename ::boost::enable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0 + #endif //BOOST_NO_CXX11_RVALUE_REFERENCES + ) +{ (void)x;} + +template<class MaybeRvalue> +void catch_test(BOOST_COPY_ASSIGN_REF(MaybeRvalue) x + #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + ,typename ::boost::enable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0 + #endif //BOOST_NO_CXX11_RVALUE_REFERENCES + ) + +{ (void)x;} + +template<class MaybeRvalue> +void catch_test(MaybeRvalue &x + #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + ,typename ::boost::enable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0 + #endif //BOOST_NO_CXX11_RVALUE_REFERENCES + ) +{ (void)x;} + + #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +template<class MaybeRvalue> +void catch_test(const MaybeRvalue& x + ,typename ::boost::disable_if< ::boost::has_move_emulation_enabled<MaybeRvalue> >::type* = 0 + ) +{ (void)x;} + #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; +} + +#include <boost/move/detail/config_end.hpp> diff --git a/src/boost/libs/move/test/conversion_test.cpp b/src/boost/libs/move/test/conversion_test.cpp new file mode 100644 index 00000000..8e901f87 --- /dev/null +++ b/src/boost/libs/move/test/conversion_test.cpp @@ -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; +} diff --git a/src/boost/libs/move/test/copy_elision_test.cpp b/src/boost/libs/move/test/copy_elision_test.cpp new file mode 100644 index 00000000..39123e1d --- /dev/null +++ b/src/boost/libs/move/test/copy_elision_test.cpp @@ -0,0 +1,177 @@ +// 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 <boost/move/detail/config_begin.hpp> +#include <iostream> +#include <boost/core/lightweight_test.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[]) +{ + (void)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(); +} + +#include <boost/move/detail/config_end.hpp> diff --git a/src/boost/libs/move/test/copy_move_optimization.cpp b/src/boost/libs/move/test/copy_move_optimization.cpp new file mode 100644 index 00000000..06d18475 --- /dev/null +++ b/src/boost/libs/move/test/copy_move_optimization.cpp @@ -0,0 +1,107 @@ +//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/detail/config_begin.hpp> +#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 + +#include <boost/move/detail/config_end.hpp> diff --git a/src/boost/libs/move/test/inplace_merge_test.cpp b/src/boost/libs/move/test/inplace_merge_test.cpp new file mode 100644 index 00000000..b69bce0c --- /dev/null +++ b/src/boost/libs/move/test/inplace_merge_test.cpp @@ -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(); +} diff --git a/src/boost/libs/move/test/move.cpp b/src/boost/libs/move/test/move.cpp new file mode 100644 index 00000000..2d40ec81 --- /dev/null +++ b/src/boost/libs/move/test/move.cpp @@ -0,0 +1,183 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/detail/config_begin.hpp> +#include <boost/move/utility_core.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))); + (void)m;(void)m2;(void)m3;(void)m4; + } + { + movable m; + movable m2(boost::move(m)); + movable m3(functionr(movable(boost::move(m2)))); + movable m4(functionr(boost::move(m3))); + (void)m;(void)m2;(void)m3;(void)m4; + } + { + movable m; + movable m2(boost::move(m)); + movable m3(function2(movable(boost::move(m2)))); + movable m4(function2(boost::move(m3))); + (void)m;(void)m2;(void)m3;(void)m4; + } + { + movable m; + movable m2(boost::move(m)); + movable m3(function2r(movable(boost::move(m2)))); + movable m4(function2r(boost::move(m3))); + (void)m;(void)m2;(void)m3;(void)m4; + } + { + movable m; + movable m2(boost::move(m)); + movable m3(move_return_function()); + (void)m;(void)m2;(void)m3; + } + { + movable m; + movable m2(boost::move(m)); + movable m3(move_return_function2()); + (void)m;(void)m2;(void)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&>()); + (void)mr; + (void)mr2; + (void)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&>()); + (void)cr; + (void)cr2; + (void)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&>()); + (void)cr; + (void)cr2; + (void)c; + } + + return 0; +} + +#include <boost/move/detail/config_end.hpp> diff --git a/src/boost/libs/move/test/move_algorithm.cpp b/src/boost/libs/move/test/move_algorithm.cpp new file mode 100644 index 00000000..21783289 --- /dev/null +++ b/src/boost/libs/move/test/move_algorithm.cpp @@ -0,0 +1,58 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/detail/config_begin.hpp> +#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; +} + +#include <boost/move/detail/config_end.hpp> diff --git a/src/boost/libs/move/test/move_if_noexcept.cpp b/src/boost/libs/move/test/move_if_noexcept.cpp new file mode 100644 index 00000000..a03a8219 --- /dev/null +++ b/src/boost/libs/move/test/move_if_noexcept.cpp @@ -0,0 +1,230 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/detail/config_begin.hpp> +#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(); +} + +#include <boost/move/detail/config_end.hpp> diff --git a/src/boost/libs/move/test/move_iterator.cpp b/src/boost/libs/move/test/move_iterator.cpp new file mode 100644 index 00000000..fded99a8 --- /dev/null +++ b/src/boost/libs/move/test/move_iterator.cpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/detail/config_begin.hpp> +#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(); +} + +#include <boost/move/detail/config_end.hpp> diff --git a/src/boost/libs/move/test/order_type.hpp b/src/boost/libs/move/test/order_type.hpp new file mode 100644 index 00000000..de398abc --- /dev/null +++ b/src/boost/libs/move/test/order_type.hpp @@ -0,0 +1,275 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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() + { + ++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 diff --git a/src/boost/libs/move/test/random_shuffle.hpp b/src/boost/libs/move/test/random_shuffle.hpp new file mode 100644 index 00000000..907d195f --- /dev/null +++ b/src/boost/libs/move/test/random_shuffle.hpp @@ -0,0 +1,37 @@ +#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()) & 0x7fffu); +} + +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 ) +{ + typedef typename boost::movelib::iterator_traits<RandomIt>::difference_type difference_type; + difference_type n = last - first; + for (difference_type i = n-1; i > 0; --i) { + difference_type j = ullrand() % (i+1); + if(j != i) { + boost::adl_move_swap(first[i], first[j]); + } + } +} + + +#endif// BOOST_MOVE_TEST_RANDOM_SHUFFLE_HPP diff --git a/src/boost/libs/move/test/type_traits.cpp b/src/boost/libs/move/test/type_traits.cpp new file mode 100644 index 00000000..3625777a --- /dev/null +++ b/src/boost/libs/move/test/type_traits.cpp @@ -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(); +} diff --git a/src/boost/libs/move/test/unique_ptr_assign.cpp b/src/boost/libs/move/test/unique_ptr_assign.cpp new file mode 100644 index 00000000..088b7f4d --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_assign.cpp @@ -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" diff --git a/src/boost/libs/move/test/unique_ptr_ctordtor.cpp b/src/boost/libs/move/test/unique_ptr_ctordtor.cpp new file mode 100644 index 00000000..a583b926 --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_ctordtor.cpp @@ -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" diff --git a/src/boost/libs/move/test/unique_ptr_default_deleter.cpp b/src/boost/libs/move/test/unique_ptr_default_deleter.cpp new file mode 100644 index 00000000..1bf16eaa --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_default_deleter.cpp @@ -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(); +} diff --git a/src/boost/libs/move/test/unique_ptr_functions.cpp b/src/boost/libs/move/test/unique_ptr_functions.cpp new file mode 100644 index 00000000..d3b4d6d5 --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_functions.cpp @@ -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 a) : a (a), b(1000), c(1001) {++count;} + A(int a, int b) : a (a), b(b), c(1001) {++count;} + A(int a, int b, int c) : a (a), b(b), c(c) {++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 == 10); + for(int i = 0; i != 10; ++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 == 10); + for(int i = 0; i != 10; ++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(unsigned i = 0; i != 10; ++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(unsigned i = 0; i != 10; ++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(); +} diff --git a/src/boost/libs/move/test/unique_ptr_modifiers.cpp b/src/boost/libs/move/test/unique_ptr_modifiers.cpp new file mode 100644 index 00000000..376c1044 --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_modifiers.cpp @@ -0,0 +1,381 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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" diff --git a/src/boost/libs/move/test/unique_ptr_movector.cpp b/src/boost/libs/move/test/unique_ptr_movector.cpp new file mode 100644 index 00000000..ece216b2 --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_movector.cpp @@ -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" diff --git a/src/boost/libs/move/test/unique_ptr_nullptr.cpp b/src/boost/libs/move/test/unique_ptr_nullptr.cpp new file mode 100644 index 00000000..555fcc20 --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_nullptr.cpp @@ -0,0 +1,228 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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(); + (void)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" diff --git a/src/boost/libs/move/test/unique_ptr_observers.cpp b/src/boost/libs/move/test/unique_ptr_observers.cpp new file mode 100644 index 00000000..14376a0b --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_observers.cpp @@ -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" diff --git a/src/boost/libs/move/test/unique_ptr_test_utils_beg.hpp b/src/boost/libs/move/test/unique_ptr_test_utils_beg.hpp new file mode 100644 index 00000000..965732c0 --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_test_utils_beg.hpp @@ -0,0 +1,209 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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> + +////////////////////////////////////////////// +// +// 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(int 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 diff --git a/src/boost/libs/move/test/unique_ptr_test_utils_end.hpp b/src/boost/libs/move/test/unique_ptr_test_utils_end.hpp new file mode 100644 index 00000000..ca0fb920 --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_test_utils_end.hpp @@ -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(int 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 diff --git a/src/boost/libs/move/test/unique_ptr_types.cpp b/src/boost/libs/move/test/unique_ptr_types.cpp new file mode 100644 index 00000000..7dbc0c37 --- /dev/null +++ b/src/boost/libs/move/test/unique_ptr_types.cpp @@ -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" |