From 7ea2ca6c405ae7c49837b54438757f9e745d563b Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 19 Nov 2016 14:57:40 +0100 Subject: [PATCH] Fix #12563 --- include/boost/optional/optional.hpp | 14 ++++++++-- test/optional_test_convert_from_T.cpp | 26 ++++++++++++++++++- ...tional_test_sfinae_friendly_value_ctor.cpp | 17 +++++++++--- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 021588f..ef62aa7 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -745,6 +745,10 @@ struct is_convertible_to_T_or_factory , boost::true_type, boost::false_type>::type {}; +template +struct is_optional_constructible : boost::is_constructible +{}; + #else #define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT @@ -753,6 +757,10 @@ template struct is_convertible_to_T_or_factory : boost::true_type {}; +template +struct is_optional_constructible : boost::true_type +{}; + #endif // is_convertible condition template @@ -812,7 +820,8 @@ class optional : public optional_detail::optional_base // Requires a valid conversion from U to T. // Can throw if T::T(U const&) does template - explicit optional ( optional const& rhs ) + explicit optional ( optional const& rhs, + typename boost::enable_if< optional_detail::is_optional_constructible >::type* = 0) : base() { @@ -825,7 +834,8 @@ class optional : public optional_detail::optional_base // Requires a valid conversion from U to T. // Can throw if T::T(U&&) does template - explicit optional ( optional && rhs ) + explicit optional ( optional && rhs, + typename boost::enable_if< optional_detail::is_optional_constructible >::type* = 0 ) : base() { diff --git a/test/optional_test_convert_from_T.cpp b/test/optional_test_convert_from_T.cpp index d4ce4bb..2abe7e5 100644 --- a/test/optional_test_convert_from_T.cpp +++ b/test/optional_test_convert_from_T.cpp @@ -23,6 +23,29 @@ using boost::optional; using boost::none; +template +struct superconv +{ + #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template + superconv(T&&) { BOOST_STATIC_ASSERT(sizeof(T) == 0); } + #else + template + superconv(const T&) { BOOST_STATIC_ASSERT(sizeof(T) == 0); } + template + superconv( T&) { BOOST_STATIC_ASSERT(sizeof(T) == 0); } + #endif + + superconv() {} +}; + +void test_optional_of_superconverting_T() // compile-time test +{ + superconv > s; + superconv > & rs = s; + optional > > os = rs; +} + void test_optional_optional_T() { optional oi1 (1), oiN; @@ -39,6 +62,7 @@ void test_optional_optional_T() int main() { test_optional_optional_T(); - + test_optional_of_superconverting_T(); + return boost::report_errors(); } diff --git a/test/optional_test_sfinae_friendly_value_ctor.cpp b/test/optional_test_sfinae_friendly_value_ctor.cpp index d7af15d..6c2abda 100644 --- a/test/optional_test_sfinae_friendly_value_ctor.cpp +++ b/test/optional_test_sfinae_friendly_value_ctor.cpp @@ -27,11 +27,20 @@ struct Resource explicit Resource(const X&) {} }; -BOOST_STATIC_ASSERT(( boost::is_constructible::value)); -BOOST_STATIC_ASSERT((!boost::is_constructible::value)); +BOOST_STATIC_ASSERT(( boost::is_constructible::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible::value )); -BOOST_STATIC_ASSERT(( boost::is_constructible, const X&>::value)); -BOOST_STATIC_ASSERT((!boost::is_constructible, const Y&>::value)); +BOOST_STATIC_ASSERT(( boost::is_constructible, const X&>::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible, const Y&>::value )); + +BOOST_STATIC_ASSERT(( boost::is_constructible< optional< optional >, optional >::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible< optional, optional< optional > >::value )); + +BOOST_STATIC_ASSERT(( boost::is_constructible< optional< optional >, const optional& >::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible< optional, const optional< optional >& >::value )); + +BOOST_STATIC_ASSERT(( boost::is_constructible, const optional&>::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible, const optional&>::value )); #endif