From 5a040eedf54691d202e3099033d6d1c5c88a736e Mon Sep 17 00:00:00 2001 From: Emil Dotchevski Date: Tue, 24 Mar 2015 15:44:28 -0700 Subject: [PATCH] rvalue references support in error_info --- .../exception/detail/error_info_impl.hpp | 15 ++- include/boost/exception/info.hpp | 111 ++++++++++++++++ test/Jamfile.v2 | 1 + test/error_info_rv_test.cpp | 122 ++++++++++++++++++ 4 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 test/error_info_rv_test.cpp diff --git a/include/boost/exception/detail/error_info_impl.hpp b/include/boost/exception/detail/error_info_impl.hpp index 12e601b..dbe0afd 100644 --- a/include/boost/exception/detail/error_info_impl.hpp +++ b/include/boost/exception/detail/error_info_impl.hpp @@ -12,6 +12,8 @@ #pragma warning(push,1) #endif +#include +#include #include namespace @@ -41,11 +43,16 @@ boost error_info: public exception_detail::error_info_base { - public: + public: typedef T value_type; error_info( value_type const & value ); +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + error_info( error_info const & ); + error_info( value_type && value ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(value)))); + error_info( error_info && x ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(x.value_)))); +#endif ~error_info() throw(); value_type const & @@ -60,7 +67,11 @@ boost return value_; } - private: + private: + error_info & operator=( error_info const & ); +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + error_info & operator=( error_info && x ); +#endif std::string name_value_string() const; diff --git a/include/boost/exception/info.hpp b/include/boost/exception/info.hpp index 762a950..b362f48 100644 --- a/include/boost/exception/info.hpp +++ b/include/boost/exception/info.hpp @@ -46,6 +46,30 @@ boost { } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + inline + error_info:: + error_info( error_info const & x ): + value_(x.value_) + { + } + template + inline + error_info:: + error_info( value_type && value ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(value)))): + value_(std::move(value)) + { + } + template + inline + error_info:: + error_info( error_info && x ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(value_type(std::move(x.value_)))): + value_(std::move(x.value_)) + { + } +#endif + template inline error_info:: @@ -175,6 +199,83 @@ boost return x; } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + E const & set_info( E const &, error_info && ); + template + class + set_info_rv > + { + template + friend E const & set_info( E const &, error_info && ); + template + static + E const & + set( E const & x, error_info && v ) + { + typedef error_info error_info_tag_t; + shared_ptr p( new error_info_tag_t(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; + } + }; + template <> + class + set_info_rv + { + template + friend E const & set_info( E const &, error_info && ); + template + static + E const & + set( E const & x, throw_function && y ) + { + x.throw_function_=y.v_; + return x; + } + }; + template <> + class + set_info_rv + { + template + friend E const & set_info( E const &, error_info && ); + template + static + E const & + set( E const & x, throw_file && y ) + { + x.throw_file_=y.v_; + return x; + } + }; + template <> + class + set_info_rv + { + template + friend E const & set_info( E const &, error_info && ); + template + static + E const & + set( E const & x, throw_line && y ) + { + x.throw_line_=y.v_; + return x; + } + }; + template + inline + E const & + set_info( E const & x, error_info && v ) + { + return set_info_rv >::template set(x,std::move(v)); + } +#endif + template struct derives_boost_exception @@ -190,6 +291,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/Jamfile.v2 b/test/Jamfile.v2 index d2dfcd6..dceba8e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -35,6 +35,7 @@ run enable_error_info_test.cpp helper1.cpp ; run throw_exception_test.cpp helper2.cpp ; run errno_test.cpp ; run error_info_test.cpp ; +run error_info_rv_test.cpp ; run diagnostic_information_test.cpp ; run refcount_ptr_test.cpp ; run current_exception_cast_test.cpp ; diff --git a/test/error_info_rv_test.cpp b/test/error_info_rv_test.cpp new file mode 100644 index 0000000..40f975f --- /dev/null +++ b/test/error_info_rv_test.cpp @@ -0,0 +1,122 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//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 +#include + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +int +main() + { + BOOST_FAIL("Platform does not support rvalue references."); + return 1; + } +#else +struct move_only; +typedef boost::error_info test1; +struct +test_exception: + boost::exception + { + }; +struct +move_only + { + explicit move_only(int x) : x_(x) { } + move_only( move_only && other ) : x_(other.x_) { } + int x_; + private: + move_only( move_only const & ); + }; +void +throw_test1() + { + throw test_exception() << test1(move_only(7)); + } +void +throw_test_throw_file_rv() + { + throw test_exception() << std::move(boost::throw_file("throw_file")); + } +void +throw_test_throw_function_rv() + { + throw test_exception() << std::move(boost::throw_function("throw_function")); + } +void +throw_test_throw_line_rv() + { + throw test_exception() << std::move(boost::throw_line(42)); + } +int +main() + { + try + { + throw_test1(); + 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); + } + try + { + throw_test_throw_function_rv(); + BOOST_ASSERT(false); + } + catch( + boost::exception & x ) + { + BOOST_TEST(boost::get_error_info(x) && !strcmp(*boost::get_error_info(x),"throw_function")); + } + catch( + ... ) + { + BOOST_TEST(false); + } + try + { + throw_test_throw_file_rv(); + BOOST_ASSERT(false); + } + catch( + boost::exception & x ) + { + BOOST_TEST(boost::get_error_info(x) && !strcmp(*boost::get_error_info(x),"throw_file")); + } + catch( + ... ) + { + BOOST_TEST(false); + } + try + { + throw_test_throw_line_rv(); + BOOST_ASSERT(false); + } + catch( + boost::exception & x ) + { + BOOST_TEST(boost::get_error_info(x) && *boost::get_error_info(x)==42); + } + catch( + ... ) + { + BOOST_TEST(false); + } + return boost::report_errors(); + } +#endif