diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk
index a026a8b..d9ca103 100644
--- a/doc/91_relnotes.qbk
+++ b/doc/91_relnotes.qbk
@@ -13,7 +13,9 @@
[heading Boost Release 1.63]
* Added two new in-place constructors. They work similarly to `emplace()` functions: they initialize the contained value by perfect-forwarding the obtained arguments. One constructor always initializes the contained value, the other based on a boolean condition.
+* Syntax `o = {}` now correctly un-initializes optional, just like in `std::optional`.
* Fixed [@https://svn.boost.org/trac/boost/ticket/12203 Trac #12203].
+* Fixed [@https://svn.boost.org/trac/boost/ticket/12563 Trac #12563].
[heading Boost Release 1.62]
diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html
index 6a6db62..79243a2 100644
--- a/doc/html/boost_optional/relnotes.html
+++ b/doc/html/boost_optional/relnotes.html
@@ -38,9 +38,17 @@
obtained arguments. One constructor always initializes the contained value,
the other based on a boolean condition.
+
+ Syntax o =
+ {}
now correctly un-initializes
+ optional, just like in std::optional
.
+
Fixed Trac #12203.
+
+ Fixed Trac #12563.
+
diff --git a/doc/html/index.html b/doc/html/index.html
index e2a485d..9c087a2 100644
--- a/doc/html/index.html
+++ b/doc/html/index.html
@@ -145,7 +145,7 @@
-Last revised: November 06, 2016 at 00:39:48 GMT |
+Last revised: November 24, 2016 at 22:27:48 GMT |
|
diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp
index 648744e..e26d73c 100644
--- a/include/boost/optional/detail/optional_config.hpp
+++ b/include/boost/optional/detail/optional_config.hpp
@@ -96,4 +96,21 @@
#endif // defined(__GNUC__)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) && !defined(__SUNPRO_CC)
+ // this condition is a copy paste from is_constructible.hpp
+ // I also disable SUNPRO, as it seems not to support type_traits correctly
+#else
+# define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT
+#endif
+
+#if defined __SUNPRO_CC
+# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
+#elif (defined _MSC_FULL_VER) && (_MSC_FULL_VER < 190023026)
+# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
+#elif defined BOOST_GCC && !defined BOOST_GCC_CXX11
+# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
+#elif defined BOOST_GCC_VERSION && BOOST_GCC_VERSION < 40800
+# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
+#endif
+
#endif // header guard
diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp
index 021588f..a465b9e 100644
--- a/include/boost/optional/optional.hpp
+++ b/include/boost/optional/optional.hpp
@@ -733,26 +733,30 @@ struct is_optional_related
boost::true_type, boost::false_type>::type
{};
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) && !defined(__SUNPRO_CC)
- // this condition is a copy paste from is_constructible.hpp
- // I also disable SUNPRO, as it seems not to support type_traits correctly
+#if !defined(BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
template
struct is_convertible_to_T_or_factory
: boost::conditional< boost::is_base_of::type>::value
|| boost::is_base_of::type>::value
- || boost::is_constructible::value
+ || (boost::is_constructible::value && !boost::is_same::type>::value)
, boost::true_type, boost::false_type>::type
{};
+template
+struct is_optional_constructible : boost::is_constructible
+{};
+
#else
-#define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT
-
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 +816,11 @@ 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
+#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
+ ,typename boost::enable_if< optional_detail::is_optional_constructible >::type* = 0
+#endif
+ )
:
base()
{
@@ -825,7 +833,11 @@ 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
+#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
+ ,typename boost::enable_if< optional_detail::is_optional_constructible >::type* = 0
+#endif
+ )
:
base()
{
@@ -944,6 +956,19 @@ class optional : public optional_detail::optional_base
}
#endif
+#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
+
+ // Assigns from a T (deep-moves/copies the rhs value)
+ template
+ BOOST_DEDUCED_TYPENAME boost::enable_if::type>, optional&>::type
+ operator= ( T_&& val )
+ {
+ this->assign( boost::forward(val) ) ;
+ return *this ;
+ }
+
+#else
+
// Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
optional& operator= ( argument_type val )
@@ -951,7 +976,7 @@ class optional : public optional_detail::optional_base
this->assign( val ) ;
return *this ;
}
-
+
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
// Assigns from a T (deep-moves the rhs value)
optional& operator= ( rval_reference_type val )
@@ -960,7 +985,9 @@ class optional : public optional_detail::optional_base
return *this ;
}
#endif
-
+
+#endif // BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
+
// Assigns from a "none"
// Which destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index ec93e18..1820ba4 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -21,6 +21,7 @@ import testing ;
[ run optional_test_swap.cpp ]
[ run optional_test_conversions_from_U.cpp ]
[ run optional_test_convert_from_T.cpp ]
+ [ run optional_test_empty_braces.cpp ]
[ run optional_test_tie.cpp ]
[ run optional_test_ref_assign_portable_minimum.cpp ]
[ run optional_test_ref_assign_mutable_int.cpp ]
@@ -41,7 +42,7 @@ import testing ;
[ run optional_test_emplace.cpp ]
[ run optional_test_minimum_requirements.cpp ]
[ run optional_test_msvc_bug_workaround.cpp ]
- [ compile optional_test_sfinae_friendly_value_ctor.cpp ]
+ [ compile optional_test_sfinae_friendly_ctor.cpp ]
[ compile-fail optional_test_ref_convert_assign_const_int_prevented.cpp ]
[ compile-fail optional_test_fail1.cpp ]
[ compile-fail optional_test_fail3a.cpp ]
diff --git a/test/optional_test_convert_from_T.cpp b/test/optional_test_convert_from_T.cpp
index d4ce4bb..6d4c2ff 100644
--- a/test/optional_test_convert_from_T.cpp
+++ b/test/optional_test_convert_from_T.cpp
@@ -23,6 +23,31 @@
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
+{
+#ifndef BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT
+ superconv > s;
+ superconv > & rs = s;
+ optional > > os = rs;
+#endif
+}
+
void test_optional_optional_T()
{
optional oi1 (1), oiN;
@@ -39,6 +64,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_empty_braces.cpp b/test/optional_test_empty_braces.cpp
new file mode 100644
index 0000000..593a68f
--- /dev/null
+++ b/test/optional_test_empty_braces.cpp
@@ -0,0 +1,57 @@
+// Copyright (C) 2016 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to 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)
+//
+// See http://www.boost.org/lib/optional for documentation.
+//
+// You are welcome to contact the author at:
+// akrzemi1@gmail.com
+
+#include "boost/optional/optional.hpp"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "boost/core/lightweight_test.hpp"
+
+//#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
+//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
+
+using boost::optional;
+
+struct Value
+{
+ explicit Value(int) {}
+};
+
+#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
+template
+void test_brace_init()
+{
+ optional o = {};
+ BOOST_TEST(!o);
+}
+
+template
+void test_brace_assign()
+{
+ optional o;
+ o = {};
+ BOOST_TEST(!o);
+}
+#endif
+
+int main()
+{
+#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
+ test_brace_init();
+ test_brace_init();
+ test_brace_assign();
+ test_brace_assign();
+#endif
+
+ return boost::report_errors();
+}
diff --git a/test/optional_test_sfinae_friendly_ctor.cpp b/test/optional_test_sfinae_friendly_ctor.cpp
new file mode 100644
index 0000000..87539e1
--- /dev/null
+++ b/test/optional_test_sfinae_friendly_ctor.cpp
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to 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)
+//
+// See http://www.boost.org/lib/optional for documentation.
+//
+// You are welcome to contact the author at:
+// akrzemi1@gmail.com
+
+#include "boost/optional/optional.hpp"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+using boost::optional;
+
+#if (!defined BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
+
+struct X {};
+struct Y {};
+
+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, const X&>::value ));
+BOOST_STATIC_ASSERT(( !boost::is_constructible, const Y&>::value ));
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
+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
+
+#endif
+
+int main() { }
diff --git a/test/optional_test_sfinae_friendly_value_ctor.cpp b/test/optional_test_sfinae_friendly_value_ctor.cpp
deleted file mode 100644
index d7af15d..0000000
--- a/test/optional_test_sfinae_friendly_value_ctor.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2014 Andrzej Krzemienski.
-//
-// Use, modification, and distribution is subject to 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)
-//
-// See http://www.boost.org/lib/optional for documentation.
-//
-// You are welcome to contact the author at:
-// akrzemi1@gmail.com
-
-#include "boost/optional/optional.hpp"
-
-#ifdef __BORLANDC__
-#pragma hdrstop
-#endif
-
-using boost::optional;
-
-#if (!defined BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
-
-struct X {};
-struct Y {};
-
-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, const X&>::value));
-BOOST_STATIC_ASSERT((!boost::is_constructible, const Y&>::value));
-
-#endif
-
-int main() { }