|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r85151 - in branches/release: boost libs/any libs/any/test
From: antoshkka_at_[hidden]
Date: 2013-07-24 11:01:41
Author: apolukhin
Date: 2013-07-24 11:01:41 EDT (Wed, 24 Jul 2013)
New Revision: 85151
URL: http://svn.boost.org/trac/boost/changeset/85151
Log:
Merge from trunk:
* bad_any_cast exception is now visible across modules (fixes #8751)
* portion of optimizations and tests for rvalues
* added ability to call any_cast<T&&> (which is equivalent to std::move(any_cast<T&>))
* added clear() member function
* added missing BOOST_NOEXCEPT
Text files modified:
branches/release/boost/any.hpp | 60 ++++++++++++++++++++++++++++++++++------
branches/release/libs/any/any_test.cpp | 56 ++++++++++++++++++++++++++++++++++++
branches/release/libs/any/test/any_test_rv.cpp | 39 +++++++++++++++++++++++++
3 files changed, 144 insertions(+), 11 deletions(-)
Modified: branches/release/boost/any.hpp
==============================================================================
--- branches/release/boost/any.hpp Wed Jul 24 09:14:00 2013 (r85150)
+++ branches/release/boost/any.hpp 2013-07-24 11:01:41 EDT (Wed, 24 Jul 2013) (r85151)
@@ -12,14 +12,17 @@
// with features contributed and bugs found by
// Antony Polukhin, Ed Brey, Mark Rodgers,
// Peter Dimov, and James Curran
-// when: July 2001, Aplril 2013
+// when: July 2001, April 2013 - May 2013
#include <algorithm>
#include <typeinfo>
#include "boost/config.hpp"
#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/decay.hpp>
+#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_const.hpp>
#include <boost/throw_exception.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/enable_if.hpp>
@@ -36,6 +39,11 @@
#include <cstring>
# endif
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable: 4172) // Mistakenly warns: returning address of local variable or temporary
+#endif
+
namespace boost
{
class any
@@ -49,7 +57,7 @@
template<typename ValueType>
any(const ValueType & value)
- : content(new holder<ValueType>(value))
+ : content(new holder<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>(value))
{
}
@@ -69,7 +77,7 @@
// Perfect forwarding of ValueType
template<typename ValueType>
any(ValueType&& value, typename boost::disable_if<boost::is_same<any&, ValueType> >::type* = 0)
- : content(new holder< typename remove_reference<ValueType>::type >(static_cast<ValueType&&>(value)))
+ : content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value)))
{
}
#endif
@@ -133,7 +141,12 @@
return !content;
}
- const std::type_info & type() const
+ void clear() BOOST_NOEXCEPT
+ {
+ any().swap(*this);
+ }
+
+ const std::type_info & type() const BOOST_NOEXCEPT
{
return content ? content->type() : typeid(void);
}
@@ -154,7 +167,7 @@
public: // queries
- virtual const std::type_info & type() const = 0;
+ virtual const std::type_info & type() const BOOST_NOEXCEPT = 0;
virtual placeholder * clone() const = 0;
@@ -178,7 +191,7 @@
#endif
public: // queries
- virtual const std::type_info & type() const
+ virtual const std::type_info & type() const BOOST_NOEXCEPT
{
return typeid(ValueType);
}
@@ -221,10 +234,10 @@
lhs.swap(rhs);
}
- class bad_any_cast : public std::bad_cast
+ class BOOST_SYMBOL_VISIBLE bad_any_cast : public std::bad_cast
{
public:
- virtual const char * what() const throw()
+ virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
{
return "boost::bad_any_cast: "
"failed conversion using boost::any_cast";
@@ -268,7 +281,18 @@
nonref * result = any_cast<nonref>(&operand);
if(!result)
boost::throw_exception(bad_any_cast());
- return *result;
+
+ // Attempt to avoid construction of a temporary object in cases when
+ // `ValueType` is not a reference. Example:
+ // `static_cast<std::string>(*result);`
+ // which is equal to `std::string(*result);`
+ typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
+ boost::is_reference<ValueType>,
+ ValueType,
+ BOOST_DEDUCED_TYPENAME boost::add_reference<ValueType>::type
+ >::type ref_type;
+
+ return static_cast<ref_type>(*result);
}
template<typename ValueType>
@@ -285,6 +309,20 @@
return any_cast<const nonref &>(const_cast<any &>(operand));
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template<typename ValueType>
+ inline ValueType&& any_cast(any&& operand)
+ {
+ BOOST_STATIC_ASSERT_MSG(
+ boost::is_rvalue_reference<ValueType&&>::value
+ || boost::is_const< typename boost::remove_reference<ValueType>::type >::value,
+ "boost::any_cast shall not be used for getting nonconst references to temporary objects"
+ );
+ return any_cast<ValueType&&>(operand);
+ }
+#endif
+
+
// Note: The "unsafe" versions of any_cast are not part of the
// public interface and may be removed at any time. They are
// required where we know what type is stored in the any and can't
@@ -309,4 +347,8 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
#endif
Modified: branches/release/libs/any/any_test.cpp
==============================================================================
--- branches/release/libs/any/any_test.cpp Wed Jul 24 09:14:00 2013 (r85150)
+++ branches/release/libs/any/any_test.cpp 2013-07-24 11:01:41 EDT (Wed, 24 Jul 2013) (r85151)
@@ -36,6 +36,8 @@
void test_swap();
void test_null_copying();
void test_cast_to_reference();
+ void test_with_array();
+ void test_with_func();
const test_case test_cases[] =
{
@@ -47,7 +49,9 @@
{ "failed custom keyword cast", test_bad_cast },
{ "swap member function", test_swap },
{ "copying operations on a null", test_null_copying },
- { "cast to reference types", test_cast_to_reference }
+ { "cast to reference types", test_cast_to_reference },
+ { "storing an array inside", test_with_array },
+ { "implicit cast of returned value",test_with_func }
};
const test_case_iterator begin = test_cases;
@@ -249,6 +253,56 @@
"any_cast to incorrect const reference type");
}
+ void test_with_array()
+ {
+ any value1("Char array");
+ any value2;
+ value2 = "Char array";
+
+ check_false(value1.empty(), "type");
+ check_false(value2.empty(), "type");
+
+ check_equal(value1.type(), typeid(const char*), "type");
+ check_equal(value2.type(), typeid(const char*), "type");
+
+ check_non_null(any_cast<const char*>(&value1), "any_cast<const char*>");
+ check_non_null(any_cast<const char*>(&value2), "any_cast<const char*>");
+ }
+
+ const std::string& returning_string1()
+ {
+ static const std::string ret("foo");
+ return ret;
+ }
+
+ std::string returning_string2()
+ {
+ static const std::string ret("foo");
+ return ret;
+ }
+
+ void test_with_func()
+ {
+ std::string s;
+ s = any_cast<std::string>(returning_string1());
+ s = any_cast<const std::string&>(returning_string1());
+ //s = any_cast<std::string&>(returning_string1());
+
+ s = any_cast<std::string>(returning_string2());
+ s = any_cast<const std::string&>(returning_string2());
+ //s = any_cast<std::string&>(returning_string2());
+
+#if !defined(_MSC_VER) || _MSC_VER != 1600
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ //s = static_cast<std::string&&>(any_cast<std::string&>(returning_string1()));
+ s = any_cast<std::string&&>(returning_string1());
+
+ //s = static_cast<std::string&&>(any_cast<std::string&>(returning_string2()));
+ s = any_cast<std::string&&>(returning_string2());
+#endif
+#endif
+ }
+
}
// Copyright Kevlin Henney, 2000, 2001. All rights reserved.
Modified: branches/release/libs/any/test/any_test_rv.cpp
==============================================================================
--- branches/release/libs/any/test/any_test_rv.cpp Wed Jul 24 09:14:00 2013 (r85150)
+++ branches/release/libs/any/test/any_test_rv.cpp 2013-07-24 11:01:41 EDT (Wed, 24 Jul 2013) (r85151)
@@ -51,6 +51,7 @@
void test_move_assignment_from_value();
void test_copy_construction_from_value();
void test_copy_assignment_from_value();
+ void test_cast_to_rv();
const test_case test_cases[] =
@@ -63,7 +64,8 @@
{ "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 }
+ { "copy assignment from value", test_copy_assignment_from_value },
+ { "casting to rvalue reference", test_cast_to_rv }
};
const test_case_iterator begin = test_cases;
@@ -272,6 +274,41 @@
move_copy_conting_class::moves_count, 0u,
"checking move counts");
}
+
+ 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 = any_cast<move_copy_conting_class&&>(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 = any_cast<move_copy_conting_class&&>(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;
+*/
+ }
+
}
#endif
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk