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() { }