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&:
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.
+