From 0755ab7b4eb42460f45a62716eb5c4d0eb57bf15 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Tue, 8 Mar 2016 18:47:48 +0100 Subject: [PATCH 01/19] removed warnings from tests --- test/optional_test_common.cpp | 30 +++++++++---------- ...tional_test_ref_fail_init_from_Trefref.cpp | 2 ++ ...tional_test_ref_fail_init_from_Urefref.cpp | 4 ++- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/test/optional_test_common.cpp b/test/optional_test_common.cpp index ff197bd..acb935c 100644 --- a/test/optional_test_common.cpp +++ b/test/optional_test_common.cpp @@ -152,21 +152,21 @@ bool X::pending_assign = false ; bool X::throw_on_copy = false ; bool X::throw_on_assign = false ; -inline void set_pending_copy ( X const* x ) { X::pending_copy = true ; } -inline void set_pending_dtor ( X const* x ) { X::pending_dtor = true ; } -inline void set_pending_assign ( X const* x ) { X::pending_assign = true ; } -inline void set_throw_on_copy ( X const* x ) { X::throw_on_copy = true ; } -inline void set_throw_on_assign ( X const* x ) { X::throw_on_assign = true ; } -inline void reset_throw_on_copy ( X const* x ) { X::throw_on_copy = false ; } -inline void reset_throw_on_assign ( X const* x ) { X::throw_on_assign = false ; } -inline void check_is_pending_copy ( X const* x ) { BOOST_TEST( X::pending_copy ) ; } -inline void check_is_pending_dtor ( X const* x ) { BOOST_TEST( X::pending_dtor ) ; } -inline void check_is_pending_assign ( X const* x ) { BOOST_TEST( X::pending_assign ) ; } -inline void check_is_not_pending_copy ( X const* x ) { BOOST_TEST( !X::pending_copy ) ; } -inline void check_is_not_pending_dtor ( X const* x ) { BOOST_TEST( !X::pending_dtor ) ; } -inline void check_is_not_pending_assign( X const* x ) { BOOST_TEST( !X::pending_assign ) ; } -inline void check_instance_count ( int c, X const* x ) { BOOST_TEST( X::count == c ) ; } -inline int get_instance_count ( X const* x ) { return X::count ; } +inline void set_pending_copy ( X const* ) { X::pending_copy = true ; } +inline void set_pending_dtor ( X const* ) { X::pending_dtor = true ; } +inline void set_pending_assign ( X const* ) { X::pending_assign = true ; } +inline void set_throw_on_copy ( X const* ) { X::throw_on_copy = true ; } +inline void set_throw_on_assign ( X const* ) { X::throw_on_assign = true ; } +inline void reset_throw_on_copy ( X const* ) { X::throw_on_copy = false ; } +inline void reset_throw_on_assign ( X const* ) { X::throw_on_assign = false ; } +inline void check_is_pending_copy ( X const* ) { BOOST_TEST( X::pending_copy ) ; } +inline void check_is_pending_dtor ( X const* ) { BOOST_TEST( X::pending_dtor ) ; } +inline void check_is_pending_assign ( X const* ) { BOOST_TEST( X::pending_assign ) ; } +inline void check_is_not_pending_copy ( X const* ) { BOOST_TEST( !X::pending_copy ) ; } +inline void check_is_not_pending_dtor ( X const* ) { BOOST_TEST( !X::pending_dtor ) ; } +inline void check_is_not_pending_assign( X const* ) { BOOST_TEST( !X::pending_assign ) ; } +inline void check_instance_count ( int c, X const* ) { BOOST_TEST( X::count == c ) ; } +inline int get_instance_count ( X const* ) { return X::count ; } inline void set_pending_copy (...) {} inline void set_pending_dtor (...) {} diff --git a/test/optional_test_ref_fail_init_from_Trefref.cpp b/test/optional_test_ref_fail_init_from_Trefref.cpp index 05752b8..a08c08a 100644 --- a/test/optional_test_ref_fail_init_from_Trefref.cpp +++ b/test/optional_test_ref_fail_init_from_Trefref.cpp @@ -10,6 +10,7 @@ // akrzemi1@gmail.com // #include "boost/optional.hpp" +#include "boost/core/ignore_unused.hpp" #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES // @@ -18,6 +19,7 @@ void optional_reference__test_no_init_from_Trefref() { boost::optional opt = int(3); + boost::ignore_unused(opt); } #else diff --git a/test/optional_test_ref_fail_init_from_Urefref.cpp b/test/optional_test_ref_fail_init_from_Urefref.cpp index e15192b..af7ca27 100644 --- a/test/optional_test_ref_fail_init_from_Urefref.cpp +++ b/test/optional_test_ref_fail_init_from_Urefref.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014, andrzej Krzemienski. +// Copyright (C) 2014, 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 @@ -10,6 +10,7 @@ // akrzemi1@gmail.com // #include "boost/optional.hpp" +#include "boost/core/ignore_unused.hpp" #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES // @@ -18,6 +19,7 @@ void optional_reference__test_no_init_from_Urefref() { boost::optional opt = long(3); + boost::ignore_unused(opt); } #else From 844ca6a0d506e59daedabb2b94e1117ec4a7e71e Mon Sep 17 00:00:00 2001 From: Daniel Seither Date: Sat, 14 May 2016 10:34:13 +0200 Subject: [PATCH 02/19] Fix build issues when optional_fwd.hpp is used before including boost/config.hpp Fixes https://svn.boost.org/trac/boost/ticket/12179 --- include/boost/optional/optional_fwd.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/optional_fwd.hpp b/include/boost/optional/optional_fwd.hpp index c41a34d..faee253 100644 --- a/include/boost/optional/optional_fwd.hpp +++ b/include/boost/optional/optional_fwd.hpp @@ -16,7 +16,7 @@ #ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP #define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP -#include +#include namespace boost { From 08076e3964a77b025c6caa000d017af141e01932 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Tue, 17 May 2016 00:54:09 +0200 Subject: [PATCH 03/19] fixed optional&> case --- .../detail/optional_reference_spec.hpp | 3 ++ test/Jamfile.v2 | 1 + test/optional_test_convert_from_T.cpp | 44 +++++++++++++++++++ ...ional_test_ref_assign_portable_minimum.cpp | 1 + test/optional_test_ref_converting_ctor.cpp | 1 + test/optional_test_ref_portable_minimum.cpp | 2 + test/testable_classes.hpp | 12 +++++ 7 files changed, 64 insertions(+) create mode 100644 test/optional_test_convert_from_T.cpp diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index ba3951a..4d1552f 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -96,6 +96,7 @@ 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)) {} optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.ptr_; return *this; } @@ -121,6 +122,8 @@ public: #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + optional(T&& rhs) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); } + template optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue(); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7394ce8..180bbab 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -20,6 +20,7 @@ import testing ; [ run optional_test.cpp ] [ run optional_test_swap.cpp ] [ run optional_test_conversions_from_U.cpp ] + [ run optional_test_convert_from_T.cpp ] [ run optional_test_tie.cpp ] [ run optional_test_ref_assign_portable_minimum.cpp ] [ run optional_test_ref_assign_mutable_int.cpp ] diff --git a/test/optional_test_convert_from_T.cpp b/test/optional_test_convert_from_T.cpp new file mode 100644 index 0000000..d4ce4bb --- /dev/null +++ b/test/optional_test_convert_from_T.cpp @@ -0,0 +1,44 @@ +// 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 + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR + +using boost::optional; +using boost::none; + +void test_optional_optional_T() +{ + optional oi1 (1), oiN; + optional< optional > ooi1 (oi1), ooiN(oiN); + + BOOST_TEST(ooi1); + BOOST_TEST(*ooi1); + BOOST_TEST_EQ(**ooi1, 1); + + BOOST_TEST(ooiN); + BOOST_TEST(!*ooiN); +} + +int main() +{ + test_optional_optional_T(); + + return boost::report_errors(); +} diff --git a/test/optional_test_ref_assign_portable_minimum.cpp b/test/optional_test_ref_assign_portable_minimum.cpp index 9ee0a0f..19085d3 100644 --- a/test/optional_test_ref_assign_portable_minimum.cpp +++ b/test/optional_test_ref_assign_portable_minimum.cpp @@ -39,6 +39,7 @@ int main() { test_optional_ref_assignment(); test_optional_ref_assignment(); + test_optional_ref_assignment< optional >(); return boost::report_errors(); } diff --git a/test/optional_test_ref_converting_ctor.cpp b/test/optional_test_ref_converting_ctor.cpp index 735c354..81f3c0f 100644 --- a/test/optional_test_ref_converting_ctor.cpp +++ b/test/optional_test_ref_converting_ctor.cpp @@ -102,6 +102,7 @@ int main() test_all_const_cases(); test_all_const_cases(); test_all_const_cases(); + test_all_const_cases< optional >(); return boost::report_errors(); } diff --git a/test/optional_test_ref_portable_minimum.cpp b/test/optional_test_ref_portable_minimum.cpp index 5bd7d11..303559a 100644 --- a/test/optional_test_ref_portable_minimum.cpp +++ b/test/optional_test_ref_portable_minimum.cpp @@ -465,10 +465,12 @@ int main() test_optional_ref(); test_optional_ref(); test_optional_ref(); + test_optional_ref< optional >(); test_optional_const_ref(); test_optional_const_ref(); test_optional_const_ref(); + test_optional_const_ref< optional >(); return boost::report_errors(); } diff --git a/test/testable_classes.hpp b/test/testable_classes.hpp index e18359f..3b2a436 100644 --- a/test/testable_classes.hpp +++ b/test/testable_classes.hpp @@ -12,6 +12,8 @@ #ifndef BOOST_OPTIONAL_TEST_TESTABKE_CLASSES_AK_07JAN2015_HPP #define BOOST_OPTIONAL_TEST_TESTABKE_CLASSES_AK_07JAN2015_HPP +#include "boost/optional/optional.hpp" + struct ScopeGuard // no copy/move ctor/assign { int val_; @@ -74,13 +76,23 @@ struct has_arrow static const bool value = false; }; +template <> +struct has_arrow< boost::optional > +{ + static const bool value = false; +}; + int& val(int& i) { return i; } int& val(Abstract& a) { return a.val(); } +int& val(Impl& a) { return a.val(); } int& val(ScopeGuard& g) { return g.val(); } +template int& val(T& o) { return *o; } const int& val(const int& i) { return i; } const int& val(const Abstract& a) { return a.val(); } +const int& val(const Impl& a) { return a.val(); } const int& val(const ScopeGuard& g) { return g.val(); } +template const int& val(const T& o) { return *o; } bool operator==(const Abstract& l, const Abstract& r) { return l.val() == r.val(); } bool operator==(const ScopeGuard& l, const ScopeGuard& r) { return l.val() == r.val(); } From 088e2e305113ef0916338036b2acf083aa17279b Mon Sep 17 00:00:00 2001 From: Benjamin Buch Date: Tue, 31 May 2016 01:00:20 +0200 Subject: [PATCH 04/19] Suppress a 'unused parameter' warning in optional_reference_spec.hpp --- include/boost/optional/detail/optional_reference_spec.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 4d1552f..105f790 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -122,7 +122,7 @@ public: #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES - optional(T&& rhs) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); } + optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); } template optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT From f9324a879070f4bc68657c664575dd2f5474cccd Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 2 Sep 2016 01:41:31 +0200 Subject: [PATCH 05/19] 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 From 99efe7205232f96fa2b7d920c87b6879b0a7fa53 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Tue, 6 Sep 2016 21:59:54 +0200 Subject: [PATCH 06/19] is_const_interal -> is_const_integral --- include/boost/optional/detail/optional_reference_spec.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 7beedd4..ad286ff 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -68,7 +68,7 @@ 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(!is_const_interal::value, + BOOST_STATIC_ASSERT_MSG(!is_const_integral::value, "binding const lvalue references to integral types is disabled in this compiler"); #endif #endif From 1c31338da35aed9eb9349c4d3bdb2b575e7e6b44 Mon Sep 17 00:00:00 2001 From: Anthony Date: Fri, 9 Sep 2016 18:16:02 -0500 Subject: [PATCH 07/19] Fix Operator!= none_t Return Statement --- doc/28_ref_optional_semantics.qbk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/28_ref_optional_semantics.qbk b/doc/28_ref_optional_semantics.qbk index 31dc178..78a628c 100644 --- a/doc/28_ref_optional_semantics.qbk +++ b/doc/28_ref_optional_semantics.qbk @@ -1181,7 +1181,7 @@ __SPACE__ [: `bool operator != ( optional const& x, none_t ) noexcept;`] [: `bool operator != ( none_t, optional const& x ) noexcept;`] -* [*Returns: ] `!( x == y );` +* [*Returns: ] `bool(x);` __SPACE__ @@ -1268,4 +1268,4 @@ assert ( !optX ); assert (addressof(*opt0) == addressof(y)); `` -[endsect] \ No newline at end of file +[endsect] From b8da1932f33608e58a34b2d06819ba91502244ce Mon Sep 17 00:00:00 2001 From: Anthony Leedom Date: Fri, 9 Sep 2016 18:33:23 -0500 Subject: [PATCH 08/19] Fix emplace Signature Universal reference moved to the left of template parameter pack elipsis in documentation. --- doc/27_ref_optional_synopsis.qbk | 2 +- doc/28_ref_optional_semantics.qbk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/27_ref_optional_synopsis.qbk b/doc/27_ref_optional_synopsis.qbk index 54523d6..8a9386f 100644 --- a/doc/27_ref_optional_synopsis.qbk +++ b/doc/27_ref_optional_synopsis.qbk @@ -120,7 +120,7 @@ template optional& operator = ( optional&& rhs ) ; ``[link reference_optional_operator_move_equal_other_optional __GO_TO__]`` - template void emplace ( Args...&& args ) ; ``[link reference_optional_emplace __GO_TO__]`` + template void emplace ( Args&&... args ) ; ``[link reference_optional_emplace __GO_TO__]`` template optional& operator = ( InPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]`` diff --git a/doc/28_ref_optional_semantics.qbk b/doc/28_ref_optional_semantics.qbk index 31dc178..52febca 100644 --- a/doc/28_ref_optional_semantics.qbk +++ b/doc/28_ref_optional_semantics.qbk @@ -446,7 +446,7 @@ __SPACE__ [#reference_optional_emplace] -[: `template void optional::emplace( Args...&& args );`] +[: `template void optional::emplace( Args&&... args );`] * [*Requires:] The compiler supports rvalue references and variadic templates. * [*Effect:] If `*this` is initialized calls `*this = none`. From 62acbe169016c422bde8b8fa00126d7b13fad39f Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 17 Sep 2016 01:25:12 +0200 Subject: [PATCH 09/19] docs: updated gotchas section --- doc/00_optional.qbk | 2 +- doc/17_gotchas.qbk | 111 +++++++++++++++++ doc/17_optional_bool.qbk | 52 -------- doc/1A_on_performance.qbk | 2 +- doc/28_ref_optional_semantics.qbk | 1 + doc/90_dependencies.qbk | 2 +- .../optional_reference_binding.html | 25 ++-- .../detailed_semantics___free_functions.html | 4 +- ...ailed_semantics___optional_references.html | 6 + .../detailed_semantics___optional_values.html | 2 +- .../header_optional_optional_values.html | 2 +- .../tutorial/exception_safety_guarantees.html | 6 +- doc/html/boost_optional/tutorial/gotchas.html | 112 ++++++++++++++++++ ...e_positive_with__wmaybe_uninitialized.html | 77 ++++++++++++ .../gotchas/mixed_relational_comparisons.html | 59 +++++++++ .../gotchas/moved_from__optional_.html | 63 ++++++++++ .../tutorial/in_place_factories.html | 6 +- .../tutorial/performance_considerations.html | 2 +- doc/html/index.html | 5 +- doc/html/optional/tutorial.html | 3 +- 20 files changed, 458 insertions(+), 84 deletions(-) create mode 100644 doc/17_gotchas.qbk delete mode 100644 doc/17_optional_bool.qbk create mode 100644 doc/html/boost_optional/tutorial/gotchas.html create mode 100644 doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html create mode 100644 doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html create mode 100644 doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk index 14f4d4a..e6ebc4c 100644 --- a/doc/00_optional.qbk +++ b/doc/00_optional.qbk @@ -83,7 +83,7 @@ This is how you solve it with `boost::optional`: [include 14_io.qbk] [include 15_optional_references.qbk] [include 16_in_place_factories.qbk] -[include 17_optional_bool.qbk] +[include 17_gotchas.qbk] [include 18_exception_safety.qbk] [include 19_type_requirements.qbk] [include 1A_on_performance.qbk] diff --git a/doc/17_gotchas.qbk b/doc/17_gotchas.qbk new file mode 100644 index 0000000..743c5bf --- /dev/null +++ b/doc/17_gotchas.qbk @@ -0,0 +1,111 @@ +[section Gotchas] + +[section A note about optional] + +`optional` should be used with special caution and consideration. + +First, it is functionally similar to a tristate boolean (false, maybe, true) +—such as __BOOST_TRIBOOL__— except that in a tristate boolean, the maybe state +[_represents a valid value], unlike the corresponding state of an uninitialized +`optional`. +It should be carefully considered if an `optional` instead of a `tribool` +is really needed. + +Second, although `optional<>` provides a contextual conversion to `bool` in C++11, + this falls back to an implicit conversion on older compilers. This conversion refers + to the initialization state and not to the contained value. Using `optional` + can lead to subtle errors due to the implicit `bool` conversion: + + void foo ( bool v ) ; + void bar() + { + optional v = try(); + + // The following intended to pass the value of 'v' to foo(): + foo(v); + // But instead, the initialization state is passed + // due to a typo: it should have been foo(*v). + } + +The only implicit conversion is to `bool`, and it is safe in the sense that +typical integral promotions don't apply (i.e. if `foo()` takes an `int` +instead, it won't compile). + +Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you: + + optional oEmpty(none), oTrue(true), oFalse(false); + + if (oEmpty == none); // renders true + if (oEmpty == false); // renders false! + if (oEmpty == true); // renders false! + + if (oFalse == none); // renders false + if (oFalse == false); // renders true! + if (oFalse == true); // renders false + + if (oTrue == none); // renders false + if (oTrue == false); // renders false + if (oTrue == true); // renders true + +In other words, for `optional<>`, the following assertion does not hold: + + assert((opt == false) == (!opt)); +[endsect] + +[section Moved-from `optional`] + +When an optional object that contains a value is moved from (is a source of move constructor or assignment) it still contains a value and its contained value is left in a moved-from state. This can be illustrated with the following example. + + optional> opi {std::make_unique(1)}; + optional> opj = std::move(opi); + assert (opi); + assert (*opi == nullptr); + +Quite a lot of people expect that when an object that contains a value is moved from, its contained value should be destroyed. This is not so, for performance reasons. Current semantics allow the implementation of `boost::opiotnal` to be trivially copyable when `T` is trivial. +[endsect] + +[section Mixed relational comparisons] + +Because `T` is convertible to `optional` and because `opiotnal` is __SGI_LESS_THAN_COMPARABLE__ when `T` is __SGI_LESS_THAN_COMPARABLE__, +you can sometimes get an unexpected runtime result where you would rather expect a compiler error: + + optional Flight_plan::weight(); // sometimes no weight can be returned + + bool is_aircraft_too_heavy(Flight_plan const& p) + { + return p.weight() > p.aircraft().max_weight(); // compiles! + } // returns false when the optional contains no value + +[endsect] + +[section False positive with -Wmaybe-uninitialized] + +Sometimes on GCC compilers below version 5.1 you may get an -Wmaybe-uninitialized warning when copiling with option -02 on a perfectly valid `boost::optional` usage. For instance in this program: + + #include + + boost::optional getitem(); + + int main(int argc, const char *[]) + { + boost::optional a = getitem(); + boost::optional b; + + if (argc > 0) + b = argc; + + if (a != b) + return 1; + + return 0; + } + +This is a bug in the compiler. As a workaround (provided in [@http://stackoverflow.com/questions/21755206/how-to-get-around-gcc-void-b-4-may-be-used-uninitialized-in-this-funct this Stack Overflow question]) use the following way of initializing an optional containing no value: + + boost::optional b = std::make_optional(false, int()); + +This is obviously redundant, but makes the warning disappear. + +[endsect] + +[endsect] \ No newline at end of file diff --git a/doc/17_optional_bool.qbk b/doc/17_optional_bool.qbk deleted file mode 100644 index 6f3664f..0000000 --- a/doc/17_optional_bool.qbk +++ /dev/null @@ -1,52 +0,0 @@ - -[section A note about optional] - -`optional` should be used with special caution and consideration. - -First, it is functionally similar to a tristate boolean (false, maybe, true) -—such as __BOOST_TRIBOOL__— except that in a tristate boolean, the maybe state -[_represents a valid value], unlike the corresponding state of an uninitialized -`optional`. -It should be carefully considered if an `optional` instead of a `tribool` -is really needed. - -Second, although `optional<>` provides a contextual conversion to `bool` in C++11, - this falls back to an implicit conversion on older compilers. This conversion refers - to the initialization state and not to the contained value. Using `optional` - can lead to subtle errors due to the implicit `bool` conversion: - - void foo ( bool v ) ; - void bar() - { - optional v = try(); - - // The following intended to pass the value of 'v' to foo(): - foo(v); - // But instead, the initialization state is passed - // due to a typo: it should have been foo(*v). - } - -The only implicit conversion is to `bool`, and it is safe in the sense that -typical integral promotions don't apply (i.e. if `foo()` takes an `int` -instead, it won't compile). - -Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you: - - optional oEmpty(none), oTrue(true), oFalse(false); - - if (oEmpty == none); // renders true - if (oEmpty == false); // renders false! - if (oEmpty == true); // renders false! - - if (oFalse == none); // renders false - if (oFalse == false); // renders true! - if (oFalse == true); // renders false - - if (oTrue == none); // renders false - if (oTrue == false); // renders false - if (oTrue == true); // renders true - -In other words, for `optional<>`, the following assertion does not hold: - - assert((opt == false) == (!opt)); -[endsect] diff --git a/doc/1A_on_performance.qbk b/doc/1A_on_performance.qbk index 841190f..5fd749a 100644 --- a/doc/1A_on_performance.qbk +++ b/doc/1A_on_performance.qbk @@ -23,7 +23,7 @@ Given type `optional`, and assuming that `sizeof(int) == 4`, we will get `s [$images/opt_align1.png] -This means you can fit twice as many `int`s as `optional`s into the same space of memory. Therefore, if the size of the objects is critical for your application (e.g., because you want to utilize your CPU cache in order to gain performance) and you have determined you are willing to trade the code clarity, it is recommended that you simply go with type `int` and use some 'magic value' to represent ['not-an-int]. +This means you can fit twice as many `int`s as `optional`s into the same space of memory. Therefore, if the size of the objects is critical for your application (e.g., because you want to utilize your CPU cache in order to gain performance) and you have determined you are willing to trade the code clarity, it is recommended that you simply go with type `int` and use some 'magic value' to represent ['not-an-int], or use something like [@https://github.com/akrzemi1/markable `markable`] library. Even if you cannot spare any value of `int` to represent ['not-an-int] (e.g., because every value is useful, or you do want to signal ['not-an-int] explicitly), at least for `Trivial` types you should consider storing the value and the `bool` flag representing the ['null-state] separately. Consider the following class: diff --git a/doc/28_ref_optional_semantics.qbk b/doc/28_ref_optional_semantics.qbk index 803b244..e643a9f 100644 --- a/doc/28_ref_optional_semantics.qbk +++ b/doc/28_ref_optional_semantics.qbk @@ -770,6 +770,7 @@ __SPACE__ [: `template optional::optional(R&& r) noexcept;`] * [*Postconditions:] `bool(*this) == true`; `addressof(**this) == addressof(r)`. * [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This constructor does not participate in overload resolution if `decay` is an instance of `boost::optional`. +* [*Notes:] This constructor is declared `explicit` on compilers that do not correctly suport binding to const lvalues of integral types. For more details [link optional_reference_binding see here]. * [*Example:] `` T v; diff --git a/doc/90_dependencies.qbk b/doc/90_dependencies.qbk index 80e1803..6d0cccc 100644 --- a/doc/90_dependencies.qbk +++ b/doc/90_dependencies.qbk @@ -28,7 +28,7 @@ The implementation uses the following other Boost modules: [endsect] -[section Optional Reference Binding] +[section Optional Reference Binding][#optional_reference_binding] A number of compilers incorrectly treat const lvalues of integral type as rvalues, and create an illegal temporary when binding to an lvalue reference to const in some expressions. This could result in creating an optional lvalue reference that is in fact bound to an unexpected temporary rather than to the intended object. In order to prevent hard to find run-time bugs, this library performs compile-time checks to prevent expressions that would otherwise bind an optional reference to an unexpected temporary. As a consequence, on certain compilers certain pieces of functionality in optional references are missing. In order to maintain a portability of your code across diferent compilers, it is recommended that you only stick to the minimum portable interface of optional references: prefer direct-initialization and copy assignment of optional references to copy-initialization and assignment from `T&`: diff --git a/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html b/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html index fbe4ba8..314bfe6 100644 --- a/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html +++ b/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html @@ -28,18 +28,19 @@ Reference Binding

- A number of compilers incorrectly treat const lvalues of integral type as - rvalues, and create an illegal temporary when binding to an lvalue reference - to const in some expressions. This could result in creating an optional lvalue - reference that is in fact bound to an unexpected temporary rather than to - the intended object. In order to prevent hard to find run-time bugs, this - library performs compile-time checks to prevent expressions that would otherwise - bind an optional reference to an unexpected temporary. As a consequence, - on certain compilers certain pieces of functionality in optional references - are missing. In order to maintain a portability of your code across diferent - compilers, it is recommended that you only stick to the minimum portable - interface of optional references: prefer direct-initialization and copy assignment - of optional references to copy-initialization and assignment from T&: + A number of compilers incorrectly + treat const lvalues of integral type as rvalues, and create an illegal temporary + when binding to an lvalue reference to const in some expressions. This could + result in creating an optional lvalue reference that is in fact bound to + an unexpected temporary rather than to the intended object. In order to prevent + hard to find run-time bugs, this library performs compile-time checks to + prevent expressions that would otherwise bind an optional reference to an + unexpected temporary. As a consequence, on certain compilers certain pieces + of functionality in optional references are missing. In order to maintain + a portability of your code across diferent compilers, it is recommended that + you only stick to the minimum portable interface of optional references: + prefer direct-initialization and copy assignment of optional references to + copy-initialization and assignment from T&:

const int i = 0;
 optional<const int&> or1;
diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html
index f786277..4b33196 100644
--- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html
+++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html
@@ -268,9 +268,7 @@
             optional<T> const& x ) noexcept;
           

  • - Returns: !( - x == - y ); + Returns: bool(x);

space diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html index 0bca093..71b01dd 100644 --- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html @@ -55,6 +55,12 @@ is an lvalue reference, the program is ill-formed. This constructor does not participate in overload resolution if decay<R> is an instance of boost::optional. +

  • + Notes: This constructor is declared + explicit on compilers + that do not correctly suport binding to const lvalues of integral types. + For more details see here. +
  • Example:
    T v;
    diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html
    index a33ad48..bd0877a 100644
    --- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html
    +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html
    @@ -1007,7 +1007,7 @@
             

    template<class... Args> - void optional<T>::emplace( Args...&& args + void optional<T>::emplace( Args&&... args );

      diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html index 56d02de..8b5fd70 100644 --- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html @@ -76,7 +76,7 @@ template<class U> optional& operator = ( optional<U>&& rhs ) ; R - template<class... Args> void emplace ( Args...&& args ) ; R + template<class... Args> void emplace ( Args&&... args ) ; R template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; R diff --git a/doc/html/boost_optional/tutorial/exception_safety_guarantees.html b/doc/html/boost_optional/tutorial/exception_safety_guarantees.html index edce61d..cfabeea 100644 --- a/doc/html/boost_optional/tutorial/exception_safety_guarantees.html +++ b/doc/html/boost_optional/tutorial/exception_safety_guarantees.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
      -PrevUpHomeNext +PrevUpHomeNext

      @@ -169,7 +169,7 @@
      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/boost_optional/tutorial/gotchas.html b/doc/html/boost_optional/tutorial/gotchas.html new file mode 100644 index 0000000..790aa19 --- /dev/null +++ b/doc/html/boost_optional/tutorial/gotchas.html @@ -0,0 +1,112 @@ + + + +Gotchas + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +
      + +

      + optional<bool> + should be used with special caution and consideration. +

      +

      + First, it is functionally similar to a tristate boolean (false, maybe, + true) —such as boost::tribool— + except that in a tristate boolean, the maybe state represents + a valid value, unlike the corresponding state of an uninitialized + optional<bool>. + It should be carefully considered if an optional<bool> instead of a tribool + is really needed. +

      +

      + Second, although optional<> provides a contextual conversion + to bool in C++11, this falls + back to an implicit conversion on older compilers. This conversion refers + to the initialization state and not to the contained value. Using optional<bool> + can lead to subtle errors due to the implicit bool + conversion: +

      +
      void foo ( bool v ) ;
      +void bar()
      +{
      +    optional<bool> v = try();
      +
      +    // The following intended to pass the value of 'v' to foo():
      +    foo(v);
      +    // But instead, the initialization state is passed
      +    // due to a typo: it should have been foo(*v).
      +}
      +
      +

      + The only implicit conversion is to bool, + and it is safe in the sense that typical integral promotions don't apply + (i.e. if foo() + takes an int instead, it won't + compile). +

      +

      + Third, mixed comparisons with bool + work differently than similar mixed comparisons between pointers and bool, so the results might surprise you: +

      +
      optional<bool> oEmpty(none), oTrue(true), oFalse(false);
      +
      +if (oEmpty == none);  // renders true
      +if (oEmpty == false); // renders false!
      +if (oEmpty == true);  // renders false!
      +
      +if (oFalse == none);  // renders false
      +if (oFalse == false); // renders true!
      +if (oFalse == true);  // renders false
      +
      +if (oTrue == none);   // renders false
      +if (oTrue == false);  // renders false
      +if (oTrue == true);   // renders true
      +
      +

      + In other words, for optional<>, the following assertion does not + hold: +

      +
      assert((opt == false) == (!opt));
      +
      +
      +
      + + + +
      +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html b/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html new file mode 100644 index 0000000..1ecc562 --- /dev/null +++ b/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html @@ -0,0 +1,77 @@ + + + +False positive with -Wmaybe-uninitialized + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +

      + Sometimes on GCC compilers below version 5.1 you may get an -Wmaybe-uninitialized + warning when copiling with option -02 on a perfectly valid boost::optional usage. For instance in this + program: +

      +
      #include <boost/optional.hpp>
      +
      +boost::optional<int> getitem();
      +
      +int main(int argc, const char *[])
      +{
      +  boost::optional<int> a = getitem();
      +  boost::optional<int> b;
      +
      +  if (argc > 0)
      +    b = argc;
      +
      +  if (a != b)
      +    return 1;
      +
      +  return 0;
      +}
      +
      +

      + This is a bug in the compiler. As a workaround (provided in this + Stack Overflow question) use the following way of initializing + an optional containing no value: +

      +
      boost::optional<int> b = std::make_optional(false, int());
      +
      +

      + This is obviously redundant, but makes the warning disappear. +

      +
      + + + +
      +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html b/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html new file mode 100644 index 0000000..b4391f7 --- /dev/null +++ b/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html @@ -0,0 +1,59 @@ + + + +Mixed relational comparisons + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +

      + Because T is convertible + to optional<T> + and because opiotnal<T> + is LessThanComparable when T is LessThanComparable, you can sometimes + get an unexpected runtime result where you would rather expect a compiler + error: +

      +
      optional<double> Flight_plan::weight(); // sometimes no weight can be returned
      +
      +bool is_aircraft_too_heavy(Flight_plan const& p)
      +{
      +   return p.weight() > p.aircraft().max_weight(); // compiles!
      +}                                                 // returns false when the optional contains no value 
      +
      +
      + + + +
      +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html b/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html new file mode 100644 index 0000000..faecd74 --- /dev/null +++ b/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html @@ -0,0 +1,63 @@ + + + +Moved-from optional + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +

      + When an optional object that contains a value is moved from (is a source + of move constructor or assignment) it still contains a value and its contained + value is left in a moved-from state. This can be illustrated with the following + example. +

      +
      optional<std::unique_ptr<int>> opi {std::make_unique<int>(1)};
      +optional<std::unique_ptr<int>> opj = std::move(opi);
      +assert (opi);
      +assert (*opi == nullptr);
      +
      +

      + Quite a lot of people expect that when an object that contains a value + is moved from, its contained value should be destroyed. This is not so, + for performance reasons. Current semantics allow the implementation of + boost::opiotnal<T> + to be trivially copyable when T + is trivial. +

      +
      + + + +
      +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/boost_optional/tutorial/in_place_factories.html b/doc/html/boost_optional/tutorial/in_place_factories.html index 3b72041..3895f2e 100644 --- a/doc/html/boost_optional/tutorial/in_place_factories.html +++ b/doc/html/boost_optional/tutorial/in_place_factories.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

      -PrevUpHomeNext +PrevUpHomeNext

      @@ -191,7 +191,7 @@
      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/boost_optional/tutorial/performance_considerations.html b/doc/html/boost_optional/tutorial/performance_considerations.html index db70539..0f999e9 100644 --- a/doc/html/boost_optional/tutorial/performance_considerations.html +++ b/doc/html/boost_optional/tutorial/performance_considerations.html @@ -67,7 +67,7 @@ for your application (e.g., because you want to utilize your CPU cache in order to gain performance) and you have determined you are willing to trade the code clarity, it is recommended that you simply go with type int and use some 'magic value' to represent - not-an-int. + not-an-int, or use something like markable library.

      Even if you cannot spare any value of int diff --git a/doc/html/index.html b/doc/html/index.html index 98a5364..15eaf93 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -64,8 +64,7 @@ references

      In-Place Factories
      -
      A - note about optional<bool>
      +
      Gotchas
      Exception Safety Guarantees
      Type requirements
      @@ -144,7 +143,7 @@

      - +

      Last revised: March 06, 2016 at 18:30:08 GMT

      Last revised: September 16, 2016 at 23:23:39 GMT


      diff --git a/doc/html/optional/tutorial.html b/doc/html/optional/tutorial.html index 556944d..9ae3774 100644 --- a/doc/html/optional/tutorial.html +++ b/doc/html/optional/tutorial.html @@ -38,8 +38,7 @@ references
      In-Place Factories
      -
      A - note about optional<bool>
      +
      Gotchas
      Exception Safety Guarantees
      Type requirements
      From 9f8823aebfeff42ba33a6bb9b8248993a3963feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tolga=20HO=C5=9EG=C3=96R?= Date: Tue, 27 Sep 2016 09:51:09 +0300 Subject: [PATCH 10/19] Fixed #24 --- include/boost/optional/detail/optional_reference_spec.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index ad286ff..ce55875 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -127,8 +127,8 @@ public: optional(none_t) BOOST_NOEXCEPT : ptr_() {} template - explicit optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.ptr_) {} - optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.ptr_) {} + explicit optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {} + optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {} // the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with srewed conversion construction from const int template @@ -139,9 +139,9 @@ public: 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; } + optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; } template - optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.ptr_; return *this; } + optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; } optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; } From 63454c11aa909eafabe5b91233017da599b40d01 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 6 Oct 2016 23:17:20 +0200 Subject: [PATCH 11/19] unit-tests for optional ref conversion fix --- test/optional_test_ref_portable_minimum.cpp | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/optional_test_ref_portable_minimum.cpp b/test/optional_test_ref_portable_minimum.cpp index 303559a..c929c3a 100644 --- a/test/optional_test_ref_portable_minimum.cpp +++ b/test/optional_test_ref_portable_minimum.cpp @@ -430,6 +430,23 @@ void test_swap() BOOST_TEST(boost::addressof(*o2_) == boost::addressof(v1)); } +template +void test_convertability_of_compatible_reference_types() +{ + typename concrete_type_of::type v1(1); + optional oN, o1(v1); + optional uN(oN), u1(o1); + BOOST_TEST(!uN); + BOOST_TEST(u1); + BOOST_TEST(boost::addressof(*u1) == boost::addressof(*o1)); + + uN = o1; + u1 = oN; + BOOST_TEST(!u1); + BOOST_TEST(uN); + BOOST_TEST(boost::addressof(*uN) == boost::addressof(*o1)); +} + template void test_optional_ref() { @@ -472,5 +489,11 @@ int main() test_optional_const_ref(); test_optional_const_ref< optional >(); + test_convertability_of_compatible_reference_types(); + test_convertability_of_compatible_reference_types(); + test_convertability_of_compatible_reference_types(); + test_convertability_of_compatible_reference_types(); + test_convertability_of_compatible_reference_types, const optional >(); + return boost::report_errors(); } From d556ccedb25a24a5a87939d4039e229f00d99574 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Fri, 7 Oct 2016 23:07:35 -0500 Subject: [PATCH 12/19] Add, and update, documentation build targets. --- doc/Jamfile.v2 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index fc30664..2fc6463 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -46,4 +46,8 @@ boostbook standalone docbook:on ; - +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : standalone ; +explicit boostrelease ; From eb9ea1f72d53cfb82363543f25a014cf1af35faf Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 27 Oct 2016 01:08:17 +0200 Subject: [PATCH 13/19] added in_place constructors --- include/boost/optional/optional.hpp | 246 +++++++++++++++++++++++++--- test/optional_test_emplace.cpp | 185 ++++++++++++++++++++- 2 files changed, 406 insertions(+), 25 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index ff1a16c..6a843b2 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -56,6 +56,21 @@ #include #else namespace boost { + +namespace optional_ns { + +class in_place_init_t {}; // a tag for in-place initialization +const in_place_init_t in_place_init; // of contained value + +class in_place_init_if_t {}; // a tag for conditional in-place +const in_place_init_if_t in_place_init_if; // init of contained value + +} // namespace optional_ns + +using optional_ns::in_place_init_t; +using optional_ns::in_place_init; +using optional_ns::in_place_init_if_t; +using optional_ns::in_place_init_if; namespace optional_detail { @@ -338,51 +353,177 @@ class optional_base : public optional_tag #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) // Constructs in-place // upon exception *this is always uninitialized + template + void construct ( in_place_init_t, Args&&... args ) + { + ::new (m_storage.address()) value_type( boost::forward(args)... ) ; + m_initialized = true ; + } + template void emplace_assign ( Args&&... args ) - { - destroy(); - ::new (m_storage.address()) value_type( boost::forward(args)... ); - m_initialized = true ; - } + { + destroy(); + construct(in_place_init, boost::forward(args)...); + } + + template + explicit optional_base ( in_place_init_t, Args&&... args ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward(args)...); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, Args&&... args ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward(args)...); + } #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) template - void emplace_assign ( Arg&& arg ) + void construct ( in_place_init_t, Arg&& arg ) { - destroy(); ::new (m_storage.address()) value_type( boost::forward(arg) ); m_initialized = true ; } - void emplace_assign () + void construct ( in_place_init_t ) { - destroy(); ::new (m_storage.address()) value_type(); m_initialized = true ; } -#else + template - void emplace_assign ( const Arg& arg ) + void emplace_assign ( Arg&& arg ) { destroy(); + construct(in_place_init, boost::forward(arg)) ; + } + + void emplace_assign () + { + destroy(); + construct(in_place_init) ; + } + + explicit optional_base ( in_place_init_t, Arg&& args ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward(arg)); + } + + explicit optional_base ( in_place_init_t ) + : + m_initialized(false) + { + construct(in_place_init); + } + + explicit optional_base ( in_place_init_if_t, bool cond, Arg&& args ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward(arg)); + } + + explicit optional_base ( in_place_init_if_t, bool cond ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } + +#else + + template + void construct ( in_place_init_t, const Arg& arg ) + { ::new (m_storage.address()) value_type( arg ); m_initialized = true ; } + template + void construct ( in_place_init_t, Arg& arg ) + { + ::new (m_storage.address()) value_type( arg ); + m_initialized = true ; + } + + void construct ( in_place_init_t ) + { + ::new (m_storage.address()) value_type(); + m_initialized = true ; + } + + template + void emplace_assign ( const Arg& arg ) + { + destroy(); + construct(in_place_init, arg); + } + template void emplace_assign ( Arg& arg ) - { - destroy(); - ::new (m_storage.address()) value_type( arg ); - m_initialized = true ; - } + { + destroy(); + construct(in_place_init, arg); + } void emplace_assign () - { - destroy(); - ::new (m_storage.address()) value_type(); - m_initialized = true ; - } + { + destroy(); + construct(in_place_init); + } + + template + explicit optional_base ( in_place_init_t, const Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + template + explicit optional_base ( in_place_init_t, Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + explicit optional_base ( in_place_init_t ) + : m_initialized(false) + { + construct(in_place_init); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, const Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + explicit optional_base ( in_place_init_if_t, bool cond ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } #endif #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT @@ -820,9 +961,20 @@ class optional : public optional_detail::optional_base // upon exception *this is always uninitialized template void emplace ( Args&&... args ) - { - this->emplace_assign( boost::forward(args)... ); - } + { + this->emplace_assign( boost::forward(args)... ); + } + + template + explicit optional ( in_place_init_t, Args&&... args ) + : base( in_place_init, boost::forward(args)... ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, Args&&... args ) + : base( in_place_init_if, cond, boost::forward(args)... ) + {} + #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) template void emplace ( Arg&& arg ) @@ -834,6 +986,24 @@ class optional : public optional_detail::optional_base { this->emplace_assign(); } + + template + explicit optional ( in_place_init_t, Args&& args ) + : base( in_place_init, boost::forward(args) ) + {} + + explicit optional ( in_place_init_t ) + : base( in_place_init ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, Args&& args ) + : base( in_place_init_if, cond, boost::forward(args) ) + {} + + explicit optional ( in_place_init_if_t, bool cond ) + : base( in_place_init_if, cond ) + {} #else template void emplace ( const Arg& arg ) @@ -851,6 +1021,34 @@ class optional : public optional_detail::optional_base { this->emplace_assign(); } + + template + explicit optional ( in_place_init_t, const Arg& arg ) + : base( in_place_init, arg ) + {} + + template + explicit optional ( in_place_init_t, Arg& arg ) + : base( in_place_init, arg ) + {} + + explicit optional ( in_place_init_t ) + : base( in_place_init ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, const Arg& arg ) + : base( in_place_init_if, cond, arg ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, Arg& arg ) + : base( in_place_init_if, cond, arg ) + {} + + explicit optional ( in_place_init_if_t, bool cond ) + : base( in_place_init_if, cond ) + {} #endif void swap( optional & arg ) diff --git a/test/optional_test_emplace.cpp b/test/optional_test_emplace.cpp index 1877a54..36972d3 100644 --- a/test/optional_test_emplace.cpp +++ b/test/optional_test_emplace.cpp @@ -23,6 +23,8 @@ using boost::optional; using boost::none; +using boost::in_place_init; +using boost::in_place_init_if; #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) @@ -87,6 +89,109 @@ void test_emplace() BOOST_TEST(7 == o->which_ctor); } +void test_in_place_ctor() +{ + int i = 0; + double d = 0.0; + const std::string cs; + std::string ms; + + { + optional o (in_place_init); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional o (in_place_init, i, 2.0); + BOOST_TEST(o); + BOOST_TEST(1 == o->which_ctor); + } + { + optional o (in_place_init, 1, d); + BOOST_TEST(o); + BOOST_TEST(2 == o->which_ctor); + } + { + optional o (in_place_init, 1, 2.0); + BOOST_TEST(o); + BOOST_TEST(3 == o->which_ctor); + } + { + optional o (in_place_init, i, d); + BOOST_TEST(o); + BOOST_TEST(4 == o->which_ctor); + } + { + optional o (in_place_init, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional o (in_place_init, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } + { + optional o (in_place_init, std::string()); + BOOST_TEST(o); + BOOST_TEST(7 == o->which_ctor); + } +} + +void test_in_place_if_ctor() +{ + int i = 0; + double d = 0.0; + const std::string cs; + std::string ms; + + { + optional o (in_place_init_if, true); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional o (in_place_init_if, true, i, 2.0); + BOOST_TEST(o); + BOOST_TEST(1 == o->which_ctor); + } + { + optional o (in_place_init_if, true, 1, d); + BOOST_TEST(o); + BOOST_TEST(2 == o->which_ctor); + } + { + optional o (in_place_init_if, true, 1, 2.0); + BOOST_TEST(o); + BOOST_TEST(3 == o->which_ctor); + } + { + optional o (in_place_init_if, true, i, d); + BOOST_TEST(o); + BOOST_TEST(4 == o->which_ctor); + } + { + optional o (in_place_init_if, true, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional o (in_place_init_if, true, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } + { + optional o (in_place_init_if, true, std::string()); + BOOST_TEST(o); + BOOST_TEST(7 == o->which_ctor); + } + + { + optional o (in_place_init_if, false, 1, 2.0); + BOOST_TEST(!o); + } +} + #endif @@ -112,6 +217,24 @@ void test_no_moves_on_emplacement() BOOST_TEST(false); } } + +void test_no_moves_on_in_place_ctor() +{ + try { + optional o (in_place_init, 1); + BOOST_TEST(o); + + optional p (in_place_init_if, true, 1); + BOOST_TEST(p); + + optional q (in_place_init_if, false, 1); + BOOST_TEST(!q); + } + catch (...) { + BOOST_TEST(false); + } +} + #endif struct Thrower @@ -158,6 +281,7 @@ void test_no_assignment_on_emplacement() } namespace no_rvalue_refs { + class Guard { public: @@ -188,19 +312,78 @@ void test_emplace() BOOST_TEST(o); BOOST_TEST(6 == o->which_ctor); } -} + +void test_in_place_ctor() +{ + const std::string cs; + std::string ms; + + { + optional o (in_place_init); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional o (in_place_init, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional o (in_place_init, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } +} + +void test_in_place_if_ctor() +{ + const std::string cs; + std::string ms; + + { + optional n (in_place_init_if, false); + BOOST_TEST(!n); + + optional o (in_place_init_if, true); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional n (in_place_init_if, false, cs); + BOOST_TEST(!n); + + optional o (in_place_init_if, true, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional n (in_place_init_if, false, ms); + BOOST_TEST(!n); + + optional o (in_place_init_if, true, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } +} + +} // namespace no_rvalue_ref int main() { #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) test_emplace(); + test_in_place_ctor(); + test_in_place_if_ctor(); #endif #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) test_no_moves_on_emplacement(); + test_no_moves_on_in_place_ctor(); #endif test_clear_on_throw(); test_no_assignment_on_emplacement(); no_rvalue_refs::test_emplace(); + no_rvalue_refs::test_in_place_ctor(); + no_rvalue_refs::test_in_place_if_ctor(); return boost::report_errors(); } From 92d40c71086a83bc294e52f957ebc310cd49b7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Thu, 27 Oct 2016 09:21:24 +0200 Subject: [PATCH 14/19] Fixed in_place_init tags --- include/boost/optional/optional.hpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 6a843b2..75b7af9 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -59,11 +59,21 @@ namespace boost { namespace optional_ns { -class in_place_init_t {}; // a tag for in-place initialization -const in_place_init_t in_place_init; // of contained value +// a tag for in-place initialization of contained value +class in_place_init_t +{ + struct init_tag{}; + explicit in_place_init_t(init_tag){} +}; +const in_place_init_t in_place_init ((in_place_init_t::init_tag())); -class in_place_init_if_t {}; // a tag for conditional in-place -const in_place_init_if_t in_place_init_if; // init of contained value +// a tag for conditional in-place initialization of contained value +class in_place_init_if_t +{ + struct init_tag{}; + explicit in_place_init_if_t(init_tag){} +}; +const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag())); } // namespace optional_ns From 9af24038bc275c9e4b18d6be75472473a78eddbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Thu, 27 Oct 2016 11:40:23 +0200 Subject: [PATCH 15/19] fixed initialization of in_place tags --- include/boost/optional/optional.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 75b7af9..fef7bb8 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -60,7 +60,7 @@ namespace boost { namespace optional_ns { // a tag for in-place initialization of contained value -class in_place_init_t +struct in_place_init_t { struct init_tag{}; explicit in_place_init_t(init_tag){} @@ -68,7 +68,7 @@ class in_place_init_t const in_place_init_t in_place_init ((in_place_init_t::init_tag())); // a tag for conditional in-place initialization of contained value -class in_place_init_if_t +struct in_place_init_if_t { struct init_tag{}; explicit in_place_init_if_t(init_tag){} From 4a9d53539cfe2a3e013a94b14e25f653f06c1513 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 28 Oct 2016 00:01:13 +0200 Subject: [PATCH 16/19] documented in-place constructors --- doc/27_ref_optional_synopsis.qbk | 31 +++++- doc/28_ref_optional_semantics.qbk | 51 +++++++++- doc/90_dependencies.qbk | 35 +++++++ doc/91_relnotes.qbk | 4 + .../dependencies_and_portability.html | 8 +- ...emplace_operations_in_older_compilers.html | 90 +++++++++++++++++ .../optional_reference_binding.html | 6 +- .../detailed_semantics___optional_values.html | 99 +++++++++++++++++-- .../header_optional_in_place_init.html | 61 ++++++++++++ .../header_optional_optional_values.html | 11 ++- doc/html/boost_optional/relnotes.html | 28 ++++-- doc/html/index.html | 4 +- .../header__boost_optional_optional_hpp_.html | 12 ++- 13 files changed, 407 insertions(+), 33 deletions(-) create mode 100644 doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html create mode 100644 doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html diff --git a/doc/27_ref_optional_synopsis.qbk b/doc/27_ref_optional_synopsis.qbk index 8a9386f..2da3b8f 100644 --- a/doc/27_ref_optional_synopsis.qbk +++ b/doc/27_ref_optional_synopsis.qbk @@ -15,6 +15,12 @@ namespace boost { + class in_place_init_t { /* see below */ } ; ``[link reference_in_place_init __GO_TO__]`` + const in_place_init_t in_place_init ( /* see below */ ) ; + + class in_place_init_if_t { /*see below*/ } ; ``[link reference_in_place_init_if __GO_TO__]`` + const in_place_init_if_t in_place_init_if ( /*see below*/ ) ; + template class optional ; ``[link reference_operator_template __GO_TO__]`` @@ -67,6 +73,26 @@ [endsect] +[section:header_optional_in_place_init Initialization tags] + +[#reference_in_place_init] +[#reference_in_place_init_if] + + namespace boost { + + class in_place_init_t { /* see below */ } ; + const in_place_init_t in_place_init ( /* see below */ ) ; + + class in_place_init_if_t { /*see below*/ } ; + const in_place_init_if_t in_place_init_if ( /*see below*/ ) ; + + } + +Classes `in_place_init_t` and `in_place_init_if_t` are empty clsses. Their purpose is to control overload resolution in the initialization of optional objects. +They are empty, trivially copyable classes with disabled default constructor. + +[endsect] + [section:header_optional_optional_values Optional Values] [#reference_operator_template] @@ -91,7 +117,6 @@ optional ( T&& v ) ; ``[link reference_optional_constructor_move_value __GO_TO__]`` - // [new in 1.34] optional ( bool condition, T const& v ) ; ``[link reference_optional_constructor_bool_value __GO_TO__]`` optional ( optional const& rhs ) ; ``[link reference_optional_constructor_optional __GO_TO__]`` @@ -101,6 +126,10 @@ template explicit optional ( optional const& rhs ) ; ``[link reference_optional_constructor_other_optional __GO_TO__]`` template explicit optional ( optional&& rhs ) ; ``[link reference_optional_move_constructor_other_optional __GO_TO__]`` + + template explicit optional ( in_place_init_t, Args&&... args ) ; ``[link reference_optional_in_place_init __GO_TO__]`` + + template explicit optional ( in_place_init_if_t, bool condition, Args&&... args ) ; ``[link reference_optional_in_place_init_if __GO_TO__]`` template explicit optional ( InPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]`` diff --git a/doc/28_ref_optional_semantics.qbk b/doc/28_ref_optional_semantics.qbk index e643a9f..1288c56 100644 --- a/doc/28_ref_optional_semantics.qbk +++ b/doc/28_ref_optional_semantics.qbk @@ -224,6 +224,53 @@ assert( *y == 123 ) ; __SPACE__ +[#reference_optional_in_place_init] + +[: `template explicit optional::optional( in_place_init_t, Args&&... ars );`] + +* [*Requires:] `is_constructible_v` is `true`. +* [*Effect:] Initializes the contained value as if direct-non-list-initializing an object of type `T` with the +arguments `std::forward(args)...`. +* [*Postconditions:] `*this` is initialized. +* [*Throws:] Any exception thrown by the selected constructor of `T`. +* [*Notes: ] `T` need not be __MOVE_CONSTRUCTIBLE__. On compilers that do not suppor variadic templates or rvalue references, this constuctor is available in limited functionality. For details [link optional_emplace_workaround see here]. + +* [*Example:] +`` +// creates an std::mutex using its default constructor +optional om {in_place_init}; +assert (om); + +// creates a unique_lock by calling unique_lock(*om, std::defer_lock) +optional> ol {in_place_init, *om, std::defer_lock}; +assert (ol); +assert (!ol->owns_lock()); +`` + +__SPACE__ + +[#reference_optional_in_place_init_if] + +[: `template explicit optional::optional( in_place_init_if_t, bool condition, Args&&... ars );`] + +* [*Requires:] `is_constructible_v` is `true`. +* [*Effect:] If `condition` is `true`, initializes the contained value as if direct-non-list-initializing an object of type `T` with the arguments `std::forward(args)...`. +* [*Postconditions:] `bool(*this) == condition`. +* [*Throws:] Any exception thrown by the selected constructor of `T`. +* [*Notes: ] `T` need not be __MOVE_CONSTRUCTIBLE__. On compilers that do not suppor variadic templates or rvalue references, this constuctor is available in limited functionality. For details [link optional_emplace_workaround see here]. + +* [*Example:] +`` +optional> ov1 {in_place_init_if, false, 3, "A"}; +assert (!ov1); + +optional> ov2 {in_place_init_if, true, 3, "A"}; +assert (ov2); +assert (ov2->size() == 3); +`` + +__SPACE__ + [#reference_optional_constructor_factory] [: `template explicit optional::optional( InPlaceFactory const& f );`] @@ -455,9 +502,7 @@ __SPACE__ * [*Postconditions: ] `*this` is [_initialized]. * [*Throws:] Whatever the selected `T`'s constructor throws. * [*Exception Safety:] If an exception is thrown during the initialization of `T`, `*this` is ['uninitialized]. -* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`. - On compilers that do not support variadic templates, the signature falls back to two overloads:`template void emplace(Arg&& arg)` and `void emplace()`. - On compilers that do not support rvalue references, the signature falls back to three overloads: taking `const` and non-`const` lvalue reference, and third with empty function argument list. +* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`. On compilers that do not suppor variadic templates or rvalue references, this function is available in limited functionality. For details [link optional_emplace_workaround see here]. * [*Example:] `` T v; diff --git a/doc/90_dependencies.qbk b/doc/90_dependencies.qbk index 6d0cccc..b5fa97c 100644 --- a/doc/90_dependencies.qbk +++ b/doc/90_dependencies.qbk @@ -27,6 +27,41 @@ The implementation uses the following other Boost modules: [endsect] +[section Emplace operations in older compilers][#optional_emplace_workaround] + +Certain constructors and functions in the interface of `optional` perform a 'perfect forwarding' of arguments: + + template optional(in_place_init_t, Args&&... args); + template optional(in_place_init_if_t, bool condition, Args&&... args); + template void emplace(Args&&... args); + +On compilers that do not support variadic templates, each of these functions is substituted with two overloads, one forwarding a single argument, the other forwarding zero arguments. This forms the following set: + + template optional(in_place_init_t, Arg&& arg); + optional(in_place_init_t); + + template optional(in_place_init_if_t, bool condition, Arg&& arg); + optional(in_place_init_if_t, bool condition); + + template void emplace(Arg&& arg); + void emplace(); + +On compilers that do not support rvalue references, each of these functions is substituted with three overloadss: taking `const` and non-`const` lvalue reference, and third forwarding zero arguments. This forms the following set: + + template optional(in_place_init_t, const Arg& arg); + template optional(in_place_init_t, Arg& arg); + optional(in_place_init_t); + + template optional(in_place_init_if_t, bool condition, const Arg& arg); + template optional(in_place_init_if_t, bool condition, Arg& arg); + optional(in_place_init_if_t, bool condition); + + template void emplace(const Arg& arg); + template void emplace(Arg& arg); + void emplace(); + +This workaround addressess about 40% of all use cases. If this is insufficient, you need to resort to using [link boost_optional.tutorial.in_place_factories In-Place Factories]. +[endsect] [section Optional Reference Binding][#optional_reference_binding] diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index ef38e5c..a026a8b 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -11,6 +11,10 @@ [section:relnotes Release Notes] +[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. +* Fixed [@https://svn.boost.org/trac/boost/ticket/12203 Trac #12203]. + [heading Boost Release 1.62] diff --git a/doc/html/boost_optional/dependencies_and_portability.html b/doc/html/boost_optional/dependencies_and_portability.html index b24c517..ac2309c 100644 --- a/doc/html/boost_optional/dependencies_and_portability.html +++ b/doc/html/boost_optional/dependencies_and_portability.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

      -PrevUpHomeNext +PrevUpHomeNext

      @@ -29,6 +29,8 @@

      @@ -83,7 +85,7 @@
      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html b/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html new file mode 100644 index 0000000..4aedcf7 --- /dev/null +++ b/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html @@ -0,0 +1,90 @@ + + + +Emplace operations in older compilers + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +

      + Certain constructors and functions + in the interface of optional + perform a 'perfect forwarding' of arguments: +

      +
      template<class... Args> optional(in_place_init_t, Args&&... args);
      +template<class... Args> optional(in_place_init_if_t, bool condition, Args&&... args);
      +template<class... Args> void emplace(Args&&... args);
      +
      +

      + On compilers that do not support variadic templates, each of these functions + is substituted with two overloads, one forwarding a single argument, the + other forwarding zero arguments. This forms the following set: +

      +
      template<class Arg> optional(in_place_init_t, Arg&& arg);
      +optional(in_place_init_t);
      +
      +template<class Arg> optional(in_place_init_if_t, bool condition, Arg&& arg);
      +optional(in_place_init_if_t, bool condition);
      +
      +template<class Arg> void emplace(Arg&& arg);
      +void emplace();
      +
      +

      + On compilers that do not support rvalue references, each of these functions + is substituted with three overloadss: taking const + and non-const lvalue reference, + and third forwarding zero arguments. This forms the following set: +

      +
      template<class Arg> optional(in_place_init_t, const Arg& arg);
      +template<class Arg> optional(in_place_init_t, Arg& arg);
      +optional(in_place_init_t);
      +
      +template<class Arg> optional(in_place_init_if_t, bool condition, const Arg& arg);
      +template<class Arg> optional(in_place_init_if_t, bool condition, Arg& arg);
      +optional(in_place_init_if_t, bool condition);
      +
      +template<class Arg> void emplace(const Arg& arg);
      +template<class Arg> void emplace(Arg& arg);
      +void emplace();
      +
      +

      + This workaround addressess about 40% of all use cases. If this is insufficient, + you need to resort to using In-Place + Factories. +

      +
      + + + +
      +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html b/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html index 314bfe6..f38dc20 100644 --- a/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html +++ b/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
      -PrevUpHomeNext +PrevUpHomeNext

      @@ -101,7 +101,7 @@
      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html index bd0877a..0d323b5 100644 --- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html @@ -403,6 +403,94 @@

  • +

    + space +

    +

    + template<class... Args> + explicit optional<T>::optional( in_place_init_t, Args&&... ars + ); +

    +
      +
    • + Requires: is_constructible_v<T, Args&&...> is true. +
    • +
    • + Effect: Initializes the contained + value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args).... +
    • +
    • + Postconditions: *this is initialized. +
    • +
    • + Throws: Any exception thrown by the + selected constructor of T. +
    • +
    • + Notes: T + need not be MoveConstructible. + On compilers that do not suppor variadic templates or rvalue references, + this constuctor is available in limited functionality. For details + see here. +
    • +
    • + Example: +
      // creates an std::mutex using its default constructor
      +optional<std::mutex> om {in_place_init};
      +assert (om);
      +
      +// creates a unique_lock by calling unique_lock(*om, std::defer_lock)
      +optional<std::unique_lock<std::mutex>> ol {in_place_init, *om, std::defer_lock};
      +assert (ol);
      +assert (!ol->owns_lock());
      +
      +
    • +
    +

    + space +

    +

    + template<class... Args> + explicit optional<T>::optional( in_place_init_if_t, bool condition, + Args&&... + ars ); +

    +
      +
    • + Requires: is_constructible_v<T, Args&&...> is true. +
    • +
    • + Effect: If condition + is true, initializes the + contained value as if direct-non-list-initializing an object of type + T with the arguments + std::forward<Args>(args).... +
    • +
    • + Postconditions: bool(*this) == condition. +
    • +
    • + Throws: Any exception thrown by the + selected constructor of T. +
    • +
    • + Notes: T + need not be MoveConstructible. + On compilers that do not suppor variadic templates or rvalue references, + this constuctor is available in limited functionality. For details + see here. +
    • +
    • + Example: +
      optional<std::vector<std::string>> ov1 {in_place_init_if, false, 3, "A"};
      +assert (!ov1);
      +
      +optional<std::vector<std::string>> ov2 {in_place_init_if, true, 3, "A"};
      +assert (ov2);
      +assert (ov2->size() == 3);
      +
      +
    • +

    space

    @@ -1037,15 +1125,8 @@ Notes: T need not be MoveConstructible or MoveAssignable. - On compilers that do not support variadic templates, the signature - falls back to two overloads:template<class - Arg> - void emplace(Arg&& arg) and void - emplace(). - On compilers that do not support rvalue references, the signature falls - back to three overloads: taking const - and non-const lvalue reference, - and third with empty function argument list. + On compilers that do not suppor variadic templates or rvalue references, + this function is available in limited functionality. For details see here.
  • Example: diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html new file mode 100644 index 0000000..8c1a467 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html @@ -0,0 +1,61 @@ + + + +Initialization tags + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +
    namespace boost {
    +
    +class in_place_init_t { /* see below */ } ;
    +const in_place_init_t in_place_init ( /* see below */ ) ;
    +
    +class in_place_init_if_t { /*see below*/ } ;
    +const in_place_init_if_t in_place_init_if ( /*see below*/ ) ;
    +
    +}
    +
    +

    + Classes in_place_init_t + and in_place_init_if_t + are empty clsses. Their purpose is to control overload resolution in the + initialization of optional objects. They are empty, trivially copyable + classes with disabled default constructor. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html index 8b5fd70..2d19129 100644 --- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -47,7 +47,6 @@ optional ( T&& v ) ; R - // [new in 1.34] optional ( bool condition, T const& v ) ; R optional ( optional const& rhs ) ; R @@ -58,6 +57,10 @@ template<class U> explicit optional ( optional<U>&& rhs ) ; R + template<class... Args> explicit optional ( in_place_init_t, Args&&... args ) ; R + + template<class... Args> explicit optional ( in_place_init_if_t, bool condition, Args&&... args ) ; R + template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; R template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; R @@ -135,7 +138,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html index 15b6373..6a6db62 100644 --- a/doc/html/boost_optional/relnotes.html +++ b/doc/html/boost_optional/relnotes.html @@ -28,6 +28,22 @@

    + 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. +
    • +
    • + Fixed Trac #12203. +
    • +
    +

    + Boost Release 1.62

    @@ -35,7 +51,7 @@ Fixed Trac #12179.
  • - + Boost Release 1.61

    @@ -78,7 +94,7 @@

    - + Boost Release 1.60

    @@ -89,7 +105,7 @@ #11203.

    - + Boost Release 1.59

    @@ -103,7 +119,7 @@

    - + Boost Release 1.58

    @@ -139,7 +155,7 @@

    - + Boost Release 1.57

    @@ -149,7 +165,7 @@ to fix C++03 compile error on logic_error("...")".

    - + Boost Release 1.56

    diff --git a/doc/html/index.html b/doc/html/index.html index 03e9413..8d507f2 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -89,6 +89,8 @@ and Portability
    Dependencies
    +
    Emplace + operations in older compilers
    Optional Reference Binding
    @@ -143,7 +145,7 @@ - +

    Last revised: September 16, 2016 at 23:43:36 GMT

    Last revised: October 27, 2016 at 21:57:04 GMT


    diff --git a/doc/html/optional/reference/header__boost_optional_optional_hpp_.html b/doc/html/optional/reference/header__boost_optional_optional_hpp_.html index a395d63..c6eec11 100644 --- a/doc/html/optional/reference/header__boost_optional_optional_hpp_.html +++ b/doc/html/optional/reference/header__boost_optional_optional_hpp_.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

    -PrevUpHomeNext +PrevUpHomeNext

    @@ -35,6 +35,12 @@ namespace boost { +class in_place_init_t { /* see below */ } ; R +const in_place_init_t in_place_init ( /* see below */ ) ; + +class in_place_init_if_t { /*see below*/ } ; R +const in_place_init_if_t in_place_init_if ( /*see below*/ ) ; + template <class T> class optional ; R @@ -95,7 +101,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    From 4e08f0dd4100fc83e2cc64f8eba0b8b9b508a7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Fri, 28 Oct 2016 11:49:33 +0200 Subject: [PATCH 17/19] Fixed build in C++03 compiler --- include/boost/optional/optional.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index fef7bb8..871903a 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -420,7 +420,8 @@ class optional_base : public optional_tag construct(in_place_init) ; } - explicit optional_base ( in_place_init_t, Arg&& args ) + template + explicit optional_base ( in_place_init_t, Arg&& arg ) : m_initialized(false) { @@ -434,7 +435,8 @@ class optional_base : public optional_tag construct(in_place_init); } - explicit optional_base ( in_place_init_if_t, bool cond, Arg&& args ) + template + explicit optional_base ( in_place_init_if_t, bool cond, Arg&& arg ) : m_initialized(false) { From 9bc1cc585cf6876846b13a46837ff2a5735590b1 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Wed, 2 Nov 2016 22:28:20 +0100 Subject: [PATCH 18/19] small sfinae fix for in_place constructors --- include/boost/optional/optional.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 871903a..844cb0f 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -727,7 +727,9 @@ class optional_base : public optional_tag template struct is_optional_related : boost::conditional< boost::is_base_of::type>::value - || boost::is_same::type, none_t>::value, + || boost::is_same::type, none_t>::value + || boost::is_same::type, in_place_init_t>::value + || boost::is_same::type, in_place_init_if_t>::value, boost::true_type, boost::false_type>::type {}; From 8d69e99e78b410d7d478c5dc9f1fe8192e8117ee Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sun, 6 Nov 2016 01:49:53 +0100 Subject: [PATCH 19/19] removed hack test, updated copyright --- doc/html/index.html | 2 +- include/boost/optional/optional.hpp | 2 +- test/Jamfile.v2 | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/html/index.html b/doc/html/index.html index 8d507f2..e2a485d 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -145,7 +145,7 @@

    - +

    Last revised: October 27, 2016 at 21:57:04 GMT

    Last revised: November 06, 2016 at 00:39:48 GMT


    diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 844cb0f..021588f 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. -// Copyright (C) 2014, 2015 Andrzej Krzemienski. +// Copyright (C) 2014 - 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 diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a44ea42..ec93e18 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,7 +1,7 @@ # Boost.Optional Library test Jamfile # # Copyright (C) 2003, Fernando Luis Cacciola Carballal. -# Copyright (C) 2014, 2015 Andrzej Krzemienski +# Copyright (C) 2014 - 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 @@ -64,7 +64,6 @@ 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 ]