Index: boost/any.hpp =================================================================== --- boost/any.hpp (revision 83774) +++ boost/any.hpp (working copy) @@ -3,12 +3,16 @@ #ifndef BOOST_ANY_INCLUDED #define BOOST_ANY_INCLUDED +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + // what: variant type boost::any // who: contributed by Kevlin Henney, // with features contributed and bugs found by -// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran -// when: July 2001 -// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95 +// Antony Polukhin, Ed Brey, Mark Rodgers, +// Peter Dimov, and James Curran +// when: July 2001, Aplril 2013 #include #include @@ -18,6 +22,7 @@ #include #include #include +#include // See boost/python/type_id.hpp // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp @@ -30,27 +35,80 @@ #include # endif +#ifdef BOOST_MSVC +#pragma warning (push) +#pragma warning (disable : 4521 ) // multiple copy constructors specified +#pragma warning (disable : 4522 ) // multiple assignment operators specified +#endif + namespace boost { class any { + private: + // Mark this class copyable and movable + BOOST_COPYABLE_AND_MOVABLE(any) public: // structors - any() + any() BOOST_NOEXCEPT : content(0) { } + + any(const any & other) + : content(other.content ? other.content->clone() : 0) + { + } + //Move constructor + any(BOOST_RV_REF(any) other) BOOST_NOEXCEPT + : content(other.content) + { + other.content = 0; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + any(any & other) + : content(other.content ? other.content->clone() : 0) + { + } + template + any(ValueType&& value) + : content(new holder< BOOST_DEDUCED_TYPENAME remove_reference::type >( + ::boost::forward(value) + )) + { + } +#else + any(const ::boost::rv& other) + : content(other.content ? other.content->clone() : 0) + { + } + + template any(const ValueType & value) : content(new holder(value)) { + BOOST_STATIC_ASSERT_MSG(!boost::move_detail::is_rv::value, + "You compiler can not deal with emulated move semantics." + "Please remove moves of non boost::any types to boost::any container." + ); } +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + any(const ::boost::rv & value) + : content(new holder(value)) + { + } - any(const any & other) - : content(other.content ? other.content->clone() : 0) + template + any(::boost::rv & value) + : content(new holder(value)) { } +#endif +#endif // BOOST_NO_CXX11_RVALUE_REFERENCES ~any() { @@ -59,28 +117,58 @@ public: // modifiers - any & swap(any & rhs) + any & swap(any & rhs) BOOST_NOEXCEPT { std::swap(content, rhs.content); return *this; } + + any & operator=(BOOST_COPY_ASSIGN_REF(any) rhs) + { + any(rhs).swap(*this); + return *this; + } + any & operator=(BOOST_RV_REF(any) rhs) BOOST_NOEXCEPT + { + rhs.swap(*this); // noexcept + any().swap(rhs); // noexcept + return *this; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + any & operator=(any& rhs) + { + any(rhs).swap(*this); + return *this; + } + template + any & operator=(ValueType&& rhs) + { + any( ::boost::forward(rhs) ) + .swap(*this); + return *this; + } +#else + template any & operator=(const ValueType & rhs) { any(rhs).swap(*this); return *this; } - any & operator=(any rhs) + template + any & operator=(ValueType & rhs) { - rhs.swap(*this); + any(rhs).swap(*this); return *this; } +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION public: // queries - bool empty() const + bool empty() const BOOST_NOEXCEPT { return !content; } @@ -122,6 +210,10 @@ { } + holder(BOOST_RV_REF(ValueType) value) + : held( boost::move(value) ) + { + } public: // queries virtual const std::type_info & type() const @@ -147,7 +239,7 @@ private: // representation template - friend ValueType * any_cast(any *); + friend ValueType * any_cast(any *) BOOST_NOEXCEPT; template friend ValueType * unsafe_any_cast(any *); @@ -162,7 +254,7 @@ }; - inline void swap(any & lhs, any & rhs) + inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT { lhs.swap(rhs); } @@ -178,7 +270,7 @@ }; template - ValueType * any_cast(any * operand) + ValueType * any_cast(any * operand) BOOST_NOEXCEPT { return operand && #ifdef BOOST_AUX_ANY_TYPE_ID_NAME @@ -191,7 +283,7 @@ } template - inline const ValueType * any_cast(const any * operand) + inline const ValueType * any_cast(const any * operand) BOOST_NOEXCEPT { return any_cast(const_cast(operand)); } @@ -247,8 +339,12 @@ { return unsafe_any_cast(const_cast(operand)); } -} +} // namespace boost +#ifdef BOOST_MSVC +#pragma warning (pop) +#endif + // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. // // Distributed under the Boost Software License, Version 1.0. (See Index: libs/any/test/Jamfile.v2 =================================================================== --- libs/any/test/Jamfile.v2 (revision 83774) +++ libs/any/test/Jamfile.v2 (working copy) @@ -8,6 +8,7 @@ test-suite any : [ run ../any_test.cpp ] + [ run any_test_rv.cpp ] [ compile-fail any_cast_cv_failed.cpp ] ; Index: libs/any/test/any_test_rv.cpp =================================================================== --- libs/any/test/any_test_rv.cpp (revision 0) +++ libs/any/test/any_test_rv.cpp (working copy) @@ -0,0 +1,266 @@ +// Unit test for boost::any. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2013. +// +// 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 +#include +#include + +#include "boost/any.hpp" +#include "../test.hpp" + +namespace any_tests +{ + typedef test test_case; + typedef const test_case * test_case_iterator; + + extern const test_case_iterator begin, end; +} + +int main() +{ + using namespace any_tests; + tester test_suite(begin, end); + return test_suite() ? EXIT_SUCCESS : EXIT_FAILURE; +} + +namespace any_tests // test suite +{ + void test_move_construction(); + void test_move_assignment(); + void test_copy_construction(); + void test_copy_assignment(); + + void test_move_construction_from_value(); + void test_move_assignment_from_value(); + void test_copy_construction_from_value(); + void test_copy_assignment_from_value(); + + + 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 } + }; + + const test_case_iterator begin = test_cases; + const test_case_iterator end = + test_cases + (sizeof test_cases / sizeof *test_cases); + + + class move_copy_conting_class { + BOOST_COPYABLE_AND_MOVABLE(move_copy_conting_class) + public: + static unsigned int moves_count; + static unsigned int copy_count; + + move_copy_conting_class(){} + move_copy_conting_class(BOOST_RV_REF(move_copy_conting_class) /*param*/) { + ++ moves_count; + } + + move_copy_conting_class& operator=(BOOST_RV_REF(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=(BOOST_COPY_ASSIGN_REF(move_copy_conting_class) /*param*/) { + ++ copy_count; + return *this; + } + }; + + unsigned int move_copy_conting_class::moves_count = 0; + unsigned int move_copy_conting_class::copy_count = 0; +} + +namespace any_tests // test definitions +{ + using namespace boost; + + 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(), typeid(move_copy_conting_class), "type"); + check_non_null(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"); + } + + 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(), typeid(move_copy_conting_class), "type"); + check_non_null(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"); + } + + 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(), "copyed value is not empty"); + check_false(value.empty(), "empty"); + check_equal(value.type(), typeid(move_copy_conting_class), "type"); + check_non_null(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"); + } + + 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(), "copyied value is not empty"); + check_false(value.empty(), "empty"); + check_equal(value.type(), typeid(move_copy_conting_class), "type"); + check_non_null(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"); + } + + 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(), typeid(move_copy_conting_class), "type"); + check_non_null(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 + + } + + 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(), typeid(move_copy_conting_class), "type"); + check_non_null(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 + + } + + 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(), typeid(move_copy_conting_class), "type"); + check_non_null(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"); + } + + 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(), typeid(move_copy_conting_class), "type"); + check_non_null(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"); + } +} Property changes on: libs/any/test/any_test_rv.cpp ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property