diff --git a/include/boost/exception/detail/error_info_impl.hpp b/include/boost/exception/detail/error_info_impl.hpp index 12e601b5..ab916794 100644 --- a/include/boost/exception/detail/error_info_impl.hpp +++ b/include/boost/exception/detail/error_info_impl.hpp @@ -12,7 +12,9 @@ #pragma warning(push,1) #endif +#include #include +#include namespace boost @@ -46,6 +48,15 @@ boost typedef T value_type; error_info( value_type const & value ); +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + error_info( value_type && value ); + error_info( error_info const & ); + error_info( error_info && other ) + BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(other.value_)))); + error_info& operator=( error_info const & other ); + error_info& operator=( error_info && other ) + BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(other.value_ = std::move(other.value_))); +#endif ~error_info() throw(); value_type const & diff --git a/include/boost/exception/info.hpp b/include/boost/exception/info.hpp index 762a950f..255354f4 100644 --- a/include/boost/exception/info.hpp +++ b/include/boost/exception/info.hpp @@ -16,8 +16,10 @@ #include #include #include +#include #include #include +#include namespace boost @@ -46,6 +48,54 @@ boost { } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + inline + error_info:: + error_info( value_type && value ): + value_(std::move(value)) + { + } + + template + inline + error_info:: + error_info( error_info const & other ): + value_(other.value_) + { + } + + template + inline + error_info:: + error_info( error_info && other ) + BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(other.value_)))) + : value_(std::move(other.value_)) + { + } + + template + inline + error_info& + error_info:: + operator=( error_info const & other ) + { + value_ = other.value_; + return *this; + } + + template + inline + error_info& + error_info:: + operator=( error_info && other ) + BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(other.value_ = std::move(other.value_))) + { + value_ = std::move(other.value_); + return *this; + } +#endif + template inline error_info:: @@ -175,6 +225,22 @@ boost return x; } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + inline + E const & + set_info( E const & x, error_info && v ) + { + typedef error_info error_info_tag_t; + shared_ptr p = boost::make_shared(std::move(v)); + exception_detail::error_info_container * c=x.data_.get(); + if( !c ) + x.data_.adopt(c=new exception_detail::error_info_container_impl); + c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); + return x; + } +#endif + template struct derives_boost_exception @@ -190,6 +256,16 @@ boost { return exception_detail::set_info(x,v); } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + inline + typename enable_if,E const &>::type + operator<<( E const & x, error_info && v ) + { + return exception_detail::set_info(x,std::move(v)); + } +#endif } #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) diff --git a/test/error_info_test.cpp b/test/error_info_test.cpp index f3dda1a9..96cf4ffb 100644 --- a/test/error_info_test.cpp +++ b/test/error_info_test.cpp @@ -11,6 +11,9 @@ struct throws_on_copy; struct non_printable { }; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +struct move_only; +#endif struct user_data @@ -43,6 +46,9 @@ typedef boost::error_info test_4; typedef boost::error_info test_5; typedef boost::error_info test_6; typedef boost::error_info test_7; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +typedef boost::error_info test_8; +#endif struct test_exception: @@ -63,6 +69,19 @@ throws_on_copy } }; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +struct +move_only + { + move_only(int x) : x_(x) {} + move_only( move_only && other ) : x_(other.x_) {} + int x_; + private: + move_only( move_only const & ) = delete; + }; +#endif + + void basic_test() { @@ -133,6 +152,14 @@ throw_test_2() throw test_exception() << test_6(non_printable()); } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +void +throw_test_3() + { + throw test_exception() << test_8(move_only(7)); + } +#endif + void throw_catch_add_file_name( char const * name ) { @@ -224,6 +251,25 @@ test_basic_throw_catch() { BOOST_TEST(false); } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + try + { + throw_test_3(); + BOOST_ASSERT(false); + } + catch( + boost::exception & x ) + { + BOOST_TEST(boost::get_error_info(x)); + BOOST_TEST(boost::get_error_info(x)->x_ == 7); + } + catch( + ... ) + { + BOOST_TEST(false); + } +#endif } void