From f9324a879070f4bc68657c664575dd2f5474cccd Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 2 Sep 2016 01:41:31 +0200 Subject: [PATCH] attempt fix at gcc 5.2 c++03 --- .../detail/optional_reference_spec.hpp | 69 ++++++++++++++++--- test/Jamfile.v2 | 1 + ...xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp | 2 +- 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 105f790..7beedd4 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -44,6 +44,23 @@ BOOST_DEDUCED_TYPENAME boost::remove_reference::type& forward_reference(T&& r #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + +template +struct is_const_integral +{ + static const bool value = boost::is_const::value && boost::is_integral::value; +}; + +template +struct is_const_integral_bad_for_conversion +{ +#if (!defined BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES) && (defined BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT) + static const bool value = boost::is_const::value && boost::is_integral::value; +#else + static const bool value = false; +#endif +}; + template void prevent_assignment_from_false_const_integral() { @@ -51,12 +68,13 @@ void prevent_assignment_from_false_const_integral() #ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT // MSVC compiler without rvalue refernces: we need to disable the asignment from // const integral lvalue reference, as it may be an invalid temporary - BOOST_STATIC_ASSERT_MSG(!(boost::is_const::value && boost::is_integral::value), + BOOST_STATIC_ASSERT_MSG(!is_const_interal::value, "binding const lvalue references to integral types is disabled in this compiler"); #endif #endif } + template struct is_optional_ { @@ -75,6 +93,21 @@ struct is_no_optional static const bool value = !is_optional_::type>::value; }; + +template + struct is_same_decayed + { + static const bool value = ::boost::is_same::type>::value + || ::boost::is_same::type>::value; + }; + +template +struct no_unboxing_cond +{ + static const bool value = is_no_optional::value && !is_same_decayed::value; +}; + + } // namespace detail template @@ -96,8 +129,15 @@ public: template explicit optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.ptr_) {} optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.ptr_) {} - optional(T& rhs) BOOST_NOEXCEPT : ptr_(boost::addressof(rhs)) {} + // the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with srewed conversion construction from const int + template + explicit optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && detail::is_const_integral_bad_for_conversion::value>::type* = 0) BOOST_NOEXCEPT + : ptr_(boost::addressof(rhs)) {} + + template + optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && !detail::is_const_integral_bad_for_conversion::value>::type* = 0) BOOST_NOEXCEPT + : ptr_(boost::addressof(rhs)) {} optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.ptr_; return *this; } template @@ -125,7 +165,7 @@ public: optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); } template - optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT + optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue(); } template @@ -157,19 +197,26 @@ public: #else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + // the following two implement a 'conditionally explicit' constructor template - optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(boost::addressof(v)) { } + explicit optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && detail::is_const_integral_bad_for_conversion::value >::type* = 0) BOOST_NOEXCEPT + : ptr_(boost::addressof(v)) { } + + template + optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && !detail::is_const_integral_bad_for_conversion::value >::type* = 0) BOOST_NOEXCEPT + : ptr_(boost::addressof(v)) { } template - optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {} + optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {} template - BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type - operator=(U& v) BOOST_NOEXCEPT - { - detail::prevent_assignment_from_false_const_integral(); - ptr_ = boost::addressof(v); return *this; - } + BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type + operator=(U& v) BOOST_NOEXCEPT + { + detail::prevent_assignment_from_false_const_integral(); + ptr_ = boost::addressof(v); return *this; + } template void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 180bbab..a44ea42 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -64,6 +64,7 @@ import testing ; [ compile-fail optional_test_fail_io_without_io.cpp ] [ compile-fail optional_test_fail_none_io_without_io.cpp ] [ compile-fail optional_test_fail_convert_assign_of_enums.cpp ] + [ run optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp ] [ run optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp ] [ run-fail optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp ] [ run optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp ] diff --git a/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp index 8cc1e70..030b9ba 100644 --- a/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp +++ b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp @@ -15,7 +15,7 @@ #if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (!defined BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF) -static_assert(false, "failed as requested"); +# error "failed as requested" #else