// See http://www.boost.org for most recent version, including documentation. // // Copyright Antony Polukhin, 2013-2023. // Copyright Ruslan Arutyunyan, 2019. // // 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). #ifndef BOOST_ANY_TESTS_MOVE_TEST_HPP_INCLUDED #define BOOST_ANY_TESTS_MOVE_TEST_HPP_INCLUDED #include #include #include #include "test.hpp" #include #include #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES namespace any_tests { template struct move_tests // test definitions { static void test_move_construction() { Any value0 = move_copy_conting_class(); move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; Any value(boost::move(value0)); check(value0.empty(), "moved away value is empty"); check_false(value.empty(), "empty"); check_equal(value.type(), boost::typeindex::type_id(), "type"); check_non_null(boost::any_cast(&value), "any_cast"); check_equal( move_copy_conting_class::copy_count, 0u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 0u, "checking move counts"); } static void test_move_assignment() { Any value0 = move_copy_conting_class(); Any value = move_copy_conting_class(); move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; value = boost::move(value0); check(value0.empty(), "moved away is empty"); check_false(value.empty(), "empty"); check_equal(value.type(), boost::typeindex::type_id(), "type"); check_non_null(boost::any_cast(&value), "any_cast"); check_equal( move_copy_conting_class::copy_count, 0u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 0u, "checking move counts"); } static void test_copy_construction() { Any value0 = move_copy_conting_class(); move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; Any value(value0); check_false(value0.empty(), "copied value is not empty"); check_false(value.empty(), "empty"); check_equal(value.type(), boost::typeindex::type_id(), "type"); check_non_null(boost::any_cast(&value), "any_cast"); check_equal( move_copy_conting_class::copy_count, 1u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 0u, "checking move counts"); } static void test_copy_assignment() { Any value0 = move_copy_conting_class(); Any value = move_copy_conting_class(); move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; value = value0; check_false(value0.empty(), "copied value is not empty"); check_false(value.empty(), "empty"); check_equal(value.type(), boost::typeindex::type_id(), "type"); check_non_null(boost::any_cast(&value), "any_cast"); check_equal( move_copy_conting_class::copy_count, 1u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 0u, "checking move counts"); } static void test_move_construction_from_value() { move_copy_conting_class value0; move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Any value(boost::move(value0)); #else Any value(value0); #endif check_false(value.empty(), "empty"); check_equal(value.type(), boost::typeindex::type_id(), "type"); check_non_null(boost::any_cast(&value), "any_cast"); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION check_equal( move_copy_conting_class::copy_count, 0u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 1u, "checking move counts"); #endif } static void test_move_assignment_from_value() { move_copy_conting_class value0; Any value; move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION value = boost::move(value0); #else value = value0; #endif check_false(value.empty(), "empty"); check_equal(value.type(), boost::typeindex::type_id(), "type"); check_non_null(boost::any_cast(&value), "any_cast"); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION check_equal( move_copy_conting_class::copy_count, 0u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 1u, "checking move counts"); #endif } static void test_copy_construction_from_value() { move_copy_conting_class value0; move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; Any value(value0); check_false(value.empty(), "empty"); check_equal(value.type(), boost::typeindex::type_id(), "type"); check_non_null(boost::any_cast(&value), "any_cast"); check_equal( move_copy_conting_class::copy_count, 1u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 0u, "checking move counts"); } static void test_copy_assignment_from_value() { move_copy_conting_class value0; Any value; move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; value = value0; check_false(value.empty(), "empty"); check_equal(value.type(), boost::typeindex::type_id(), "type"); check_non_null(boost::any_cast(&value), "any_cast"); check_equal( move_copy_conting_class::copy_count, 1u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 0u, "checking move counts"); } static const Any helper_method() { return true; } static const bool helper_method1() { return true; } static void test_construction_from_const_any_rv() { Any values[] = {helper_method(), helper_method1() }; (void)values; } static void test_cast_to_rv() { move_copy_conting_class value0; Any value; value = value0; move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; move_copy_conting_class value1 = boost::any_cast(value); check_equal( move_copy_conting_class::copy_count, 0u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 1u, "checking move counts"); (void)value1; // Following code shall fail to compile const Any cvalue = value0; move_copy_conting_class::copy_count = 0; move_copy_conting_class::moves_count = 0; move_copy_conting_class value2 = boost::any_cast(cvalue); check_equal( move_copy_conting_class::copy_count, 1u, "checking copy counts"); check_equal( move_copy_conting_class::moves_count, 0u, "checking move counts"); (void)value2; // } class move_copy_conting_class { public: static unsigned int moves_count; static unsigned int copy_count; move_copy_conting_class(){} move_copy_conting_class(move_copy_conting_class&& /*param*/) { ++ moves_count; } move_copy_conting_class& operator=(move_copy_conting_class&& /*param*/) { ++ moves_count; return *this; } move_copy_conting_class(const move_copy_conting_class&) { ++ copy_count; } move_copy_conting_class& operator=(const move_copy_conting_class& /*param*/) { ++ copy_count; return *this; } }; static int run_tests() { typedef test test_case; const test_case test_cases[] = { { "move construction of any", test_move_construction }, { "move assignment of any", test_move_assignment }, { "copy construction of any", test_copy_construction }, { "copy assignment of any", test_copy_assignment }, { "move construction from value", test_move_construction_from_value }, { "move assignment from value", test_move_assignment_from_value }, { "copy construction from value", test_copy_construction_from_value }, { "copy assignment from value", test_copy_assignment_from_value }, { "constructing from const any&&", test_construction_from_const_any_rv }, { "casting to rvalue reference", test_cast_to_rv } }; typedef const test_case * test_case_iterator; tester test_suite(test_cases, test_cases + sizeof(test_cases) / sizeof(test_cases[0])); return test_suite() ? EXIT_SUCCESS : EXIT_FAILURE; } }; // struct move_tests template unsigned int move_tests::move_copy_conting_class::moves_count = 0; template unsigned int move_tests::move_copy_conting_class::copy_count = 0; } // namespace any_tests #endif // BOOST_ANY_TESTS_MOVE_TEST_HPP_INCLUDED #endif // MOVE_TEST_INCLUDED