From 9f8dd573866a48938d53eab8eade1de41e62a6b1 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 1 Oct 2015 15:26:15 +0200 Subject: [PATCH 01/54] boost::none - simpler and works with MSVC --- doc/21_ref_none.qbk | 8 ++++--- doc/html/index.html | 2 +- doc/html/optional/reference.html | 16 ++++++++----- include/boost/none.hpp | 12 +++++++--- include/boost/none_t.hpp | 18 ++++++++++++--- include/boost/optional/optional_io.hpp | 4 ++-- test/Jamfile.v2 | 1 + .../optional_test_fail_none_io_without_io.cpp | 23 +++++++++++++++++++ 8 files changed, 66 insertions(+), 18 deletions(-) create mode 100644 test/optional_test_fail_none_io_without_io.cpp diff --git a/doc/21_ref_none.qbk b/doc/21_ref_none.qbk index e3b921e..011eff7 100644 --- a/doc/21_ref_none.qbk +++ b/doc/21_ref_none.qbk @@ -15,14 +15,16 @@ ``` namespace boost { -class none_t {}; +class none_t {/* see below */}; -extern const none_t none; // see below +const none_t none (/* see below */); } // namespace boost ``` -Variable `none` has external linkage, however it is not required to link with any library to obtain its definition. Only by including this header file, the definition becomes available, by means of using template instantiation. +Class `none_t` is meant to serve as a tag for selecting appropriate overloads of from `optional`'s interface. It is an empty, trivially copyable class with disabled default constructor. + +Constant `none` is used to indicate an optional object that does not contain a value in initialization, assignment and relational operations of `optional`. [endsect] diff --git a/doc/html/index.html b/doc/html/index.html index 2b0d9fd..833a9f6 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -146,7 +146,7 @@ - +

Last revised: July 08, 2015 at 21:39:55 GMT

Last revised: October 01, 2015 at 13:19:55 GMT


diff --git a/doc/html/optional/reference.html b/doc/html/optional/reference.html index 242e029..0cc575c 100644 --- a/doc/html/optional/reference.html +++ b/doc/html/optional/reference.html @@ -52,19 +52,23 @@

namespace boost {
 
-class none_t {};
+class none_t {/* see below */};
 
-extern const none_t none; // see below
+const none_t none (/* see below */);
 
 } // namespace boost
 

- Variable none has external - linkage, however it is not required to link with any library to obtain - its definition. Only by including this header file, the definition becomes - available, by means of using template instantiation. + Class none_t is meant to + serve as a tag for selecting appropriate overloads of from optional's interface. It is an empty, + trivially copyable class with disabled default constructor. +

+

+ Constant none is used to + indicate an optional object that does not contain a value in initialization, + assignment and relational operations of optional.

diff --git a/include/boost/none.hpp b/include/boost/none.hpp index 87a6c70..db744e5 100644 --- a/include/boost/none.hpp +++ b/include/boost/none.hpp @@ -22,8 +22,10 @@ namespace boost { #ifdef BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE + none_t const none = (static_cast(0)) ; -#else + +#elif defined BOOST_OPTIONAL_USE_SINGLETON_DEFINITION_OF_NONE namespace detail { namespace optional_detail { @@ -45,9 +47,13 @@ namespace { const none_t& none = detail::optional_detail::none_instance::instance; } -#endif +#else + +const none_t none ((none_t::init_tag())); + +#endif // older definitions } // namespace boost -#endif +#endif // header guard diff --git a/include/boost/none_t.hpp b/include/boost/none_t.hpp index 13ce455..608cb0c 100644 --- a/include/boost/none_t.hpp +++ b/include/boost/none_t.hpp @@ -16,13 +16,25 @@ namespace boost { #ifdef BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE + namespace detail { struct none_helper{}; } typedef int detail::none_helper::*none_t ; -#else + +#elif defined BOOST_OPTIONAL_USE_SINGLETON_DEFINITION_OF_NONE + class none_t {}; -#endif + +#else + +struct none_t +{ + struct init_tag{}; + explicit none_t(init_tag){} // to prevent default constructor +}; + +#endif // old implementation workarounds } // namespace boost -#endif +#endif // header guard diff --git a/include/boost/optional/optional_io.hpp b/include/boost/optional/optional_io.hpp index 16dbf95..ce81b68 100644 --- a/include/boost/optional/optional_io.hpp +++ b/include/boost/optional/optional_io.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include "boost/none.hpp" #include "boost/optional/optional.hpp" @@ -25,7 +25,7 @@ namespace boost template inline std::basic_ostream& -operator<<(std::basic_ostream& out, none_t const&) +operator<<(std::basic_ostream& out, none_t) { if (out.good()) { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index ea9e81b..6b4e857 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -58,6 +58,7 @@ import testing ; [ compile-fail optional_test_fail_explicit_convert_in_value_or.cpp ] [ compile-fail optional_test_fail_explicit_convert_in_value_or_call.cpp ] [ 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 ] ; } diff --git a/test/optional_test_fail_none_io_without_io.cpp b/test/optional_test_fail_none_io_without_io.cpp new file mode 100644 index 0000000..7fa19a9 --- /dev/null +++ b/test/optional_test_fail_none_io_without_io.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2015, 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 +#include "boost/none.hpp" +// but no boost/optional/optional_io.hpp + +// THIS TEST SHOULD FAIL TO COMPILE +// Unless one includes header boost/optional/optional_io.hpp, it should not be possible +// to stream out boost::none. + +void test_streaming_out_none() +{ + std::cout << boost::none; +} \ No newline at end of file From a46b0df3d1a8a7c19b739b704677283c81c8e064 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 3 Oct 2015 13:32:48 +0200 Subject: [PATCH 02/54] removed Boost.Test dependency --- test/optional_test.cpp | 228 +++++++++++++++++----------------- test/optional_test_common.cpp | 74 +++++------ 2 files changed, 151 insertions(+), 151 deletions(-) diff --git a/test/optional_test.cpp b/test/optional_test.cpp index 3591867..017d4ff 100644 --- a/test/optional_test.cpp +++ b/test/optional_test.cpp @@ -30,7 +30,7 @@ #include "boost/none.hpp" -#include "boost/test/minimal.hpp" +#include "boost/core/lightweight_test.hpp" #include "optional_test_common.cpp" @@ -46,12 +46,12 @@ void test_implicit_construction ( optional opt, X const& v, X const& z ) void test_default_implicit_construction ( double, optional opt ) { - BOOST_CHECK(!opt); + BOOST_TEST(!opt); } void test_default_implicit_construction ( X const&, optional opt ) { - BOOST_CHECK(!opt); + BOOST_TEST(!opt); } // @@ -188,65 +188,65 @@ void test_conditional_ctor_and_get_valur_or ( T const* ) check_value(o1,a,z); T b = def0.get_value_or(z); - BOOST_CHECK( b == z ) ; + BOOST_TEST( b == z ) ; b = get_optional_value_or(def0,z); - BOOST_CHECK( b == z ) ; + BOOST_TEST( b == z ) ; b = o0.get_value_or(z); - BOOST_CHECK( b == a ) ; + BOOST_TEST( b == a ) ; b = get_optional_value_or(o0,z); - BOOST_CHECK( b == a ) ; + BOOST_TEST( b == a ) ; T const& crz = z ; T& rz = z ; T const& crzz = def0.get_value_or(crz); - BOOST_CHECK( crzz == crz ) ; + BOOST_TEST( crzz == crz ) ; T& rzz = def0.get_value_or(rz); - BOOST_CHECK( rzz == rz ) ; + BOOST_TEST( rzz == rz ) ; T const& crzzz = get_optional_value_or(cdef0,crz); - BOOST_CHECK( crzzz == crz ) ; + BOOST_TEST( crzzz == crz ) ; T& rzzz = get_optional_value_or(def0,rz); - BOOST_CHECK( rzzz == rz ) ; + BOOST_TEST( rzzz == rz ) ; T const& crb = o0.get_value_or(crz); - BOOST_CHECK( crb == a ) ; + BOOST_TEST( crb == a ) ; T& rb = o0.get_value_or(rz); - BOOST_CHECK( rb == b ) ; + BOOST_TEST( rb == b ) ; T const& crbb = get_optional_value_or(co0,crz); - BOOST_CHECK( crbb == b ) ; + BOOST_TEST( crbb == b ) ; T const& crbbb = get_optional_value_or(o0,crz); - BOOST_CHECK( crbbb == b ) ; + BOOST_TEST( crbbb == b ) ; T& rbb = get_optional_value_or(o0,rz); - BOOST_CHECK( rbb == b ) ; + BOOST_TEST( rbb == b ) ; T& ra = a ; optional defref(false,ra); - BOOST_CHECK(!defref); + BOOST_TEST(!defref); optional ref(true,ra); - BOOST_CHECK(!!ref); + BOOST_TEST(!!ref); a = T(432); - BOOST_CHECK( *ref == a ) ; + BOOST_TEST( *ref == a ) ; T& r1 = defref.get_value_or(z); - BOOST_CHECK( r1 == z ) ; + BOOST_TEST( r1 == z ) ; T& r2 = ref.get_value_or(z); - BOOST_CHECK( r2 == a ) ; + BOOST_TEST( r2 == a ) ; } // @@ -262,18 +262,18 @@ void test_direct_value_manip( T const* ) optional const c_opt0(x) ; optional opt0(x); - BOOST_CHECK( c_opt0.get().V() == x.V() ) ; - BOOST_CHECK( opt0.get().V() == x.V() ) ; + BOOST_TEST( c_opt0.get().V() == x.V() ) ; + BOOST_TEST( opt0.get().V() == x.V() ) ; - BOOST_CHECK( c_opt0->V() == x.V() ) ; - BOOST_CHECK( opt0->V() == x.V() ) ; + BOOST_TEST( c_opt0->V() == x.V() ) ; + BOOST_TEST( opt0->V() == x.V() ) ; - BOOST_CHECK( (*c_opt0).V() == x.V() ) ; - BOOST_CHECK( (* opt0).V() == x.V() ) ; + BOOST_TEST( (*c_opt0).V() == x.V() ) ; + BOOST_TEST( (* opt0).V() == x.V() ) ; T y(4); opt0 = y ; - BOOST_CHECK( get(opt0).V() == y.V() ) ; + BOOST_TEST( get(opt0).V() == y.V() ) ; } // @@ -295,7 +295,7 @@ void test_uninitialized_access( T const* ) passed = true ; } catch (...) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); passed = false ; try @@ -306,7 +306,7 @@ void test_uninitialized_access( T const* ) passed = true ; } catch (...) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); passed = false ; try @@ -318,7 +318,7 @@ void test_uninitialized_access( T const* ) passed = true ; } catch (...) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); passed = false ; try @@ -329,7 +329,7 @@ void test_uninitialized_access( T const* ) passed = true ; } catch (...) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); } #if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0 @@ -374,7 +374,7 @@ void test_throwing_direct_init( T const* ) } catch ( ... ){} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); check_is_not_pending_copy( ARG(T) ); check_instance_count(count, ARG(T) ); @@ -410,7 +410,7 @@ void test_throwing_val_assign_on_uninitialized( T const* ) } catch ( ... ) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); check_is_not_pending_copy( ARG(T) ); check_instance_count(count, ARG(T) ); @@ -456,7 +456,7 @@ void test_throwing_val_assign_on_initialized( T const* ) } catch ( ... ) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); check_is_not_pending_assign( ARG(T) ); check_instance_count(count, ARG(T) ); @@ -495,7 +495,7 @@ void test_throwing_copy_initialization( T const* ) } catch ( ... ) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); check_is_not_pending_copy( ARG(T) ); check_instance_count(count, ARG(T) ); @@ -538,7 +538,7 @@ void test_throwing_assign_to_uninitialized( T const* ) } catch ( ... ) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); check_is_not_pending_copy( ARG(T) ); check_instance_count(count, ARG(T) ); @@ -581,7 +581,7 @@ void test_throwing_assign_to_initialized( T const* ) } catch ( ... ) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); // opt0 was left uninitialized check_is_not_pending_assign( ARG(T) ); @@ -661,7 +661,7 @@ void test_throwing_swap( T const* ) } catch ( ... ) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); // optional's swap doesn't affect the initialized states of the arguments. Therefore, // the following must hold: @@ -692,7 +692,7 @@ void test_throwing_swap( T const* ) } catch ( ... ) {} - BOOST_CHECK(!passed); + BOOST_TEST(!passed); check_uninitialized(opt0); check_initialized(opt1); @@ -720,69 +720,69 @@ void test_relops( T const* ) optional opt2(v2); // Check identity - BOOST_CHECK ( def0 == def0 ) ; - BOOST_CHECK ( opt0 == opt0 ) ; - BOOST_CHECK ( !(def0 != def0) ) ; - BOOST_CHECK ( !(opt0 != opt0) ) ; + BOOST_TEST ( def0 == def0 ) ; + BOOST_TEST ( opt0 == opt0 ) ; + BOOST_TEST ( !(def0 != def0) ) ; + BOOST_TEST ( !(opt0 != opt0) ) ; // Check when both are uininitalized. - BOOST_CHECK ( def0 == def1 ) ; // both uninitialized compare equal - BOOST_CHECK ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized - BOOST_CHECK ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized - BOOST_CHECK ( !(def0 != def1) ) ; - BOOST_CHECK ( def0 <= def1 ) ; - BOOST_CHECK ( def0 >= def1 ) ; + BOOST_TEST ( def0 == def1 ) ; // both uninitialized compare equal + BOOST_TEST ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized + BOOST_TEST ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized + BOOST_TEST ( !(def0 != def1) ) ; + BOOST_TEST ( def0 <= def1 ) ; + BOOST_TEST ( def0 >= def1 ) ; // Check when only lhs is uninitialized. - BOOST_CHECK ( def0 != opt0 ) ; // uninitialized is never equal to initialized - BOOST_CHECK ( !(def0 == opt0) ) ; - BOOST_CHECK ( def0 < opt0 ) ; // uninitialized is always less than initialized - BOOST_CHECK ( !(def0 > opt0) ) ; - BOOST_CHECK ( def0 <= opt0 ) ; - BOOST_CHECK ( !(def0 >= opt0) ) ; + BOOST_TEST ( def0 != opt0 ) ; // uninitialized is never equal to initialized + BOOST_TEST ( !(def0 == opt0) ) ; + BOOST_TEST ( def0 < opt0 ) ; // uninitialized is always less than initialized + BOOST_TEST ( !(def0 > opt0) ) ; + BOOST_TEST ( def0 <= opt0 ) ; + BOOST_TEST ( !(def0 >= opt0) ) ; // Check when only rhs is uninitialized. - BOOST_CHECK ( opt0 != def0 ) ; // initialized is never equal to uninitialized - BOOST_CHECK ( !(opt0 == def0) ) ; - BOOST_CHECK ( !(opt0 < def0) ) ; // initialized is never less than uninitialized - BOOST_CHECK ( opt0 > def0 ) ; - BOOST_CHECK ( !(opt0 <= def0) ) ; - BOOST_CHECK ( opt0 >= opt0 ) ; + BOOST_TEST ( opt0 != def0 ) ; // initialized is never equal to uninitialized + BOOST_TEST ( !(opt0 == def0) ) ; + BOOST_TEST ( !(opt0 < def0) ) ; // initialized is never less than uninitialized + BOOST_TEST ( opt0 > def0 ) ; + BOOST_TEST ( !(opt0 <= def0) ) ; + BOOST_TEST ( opt0 >= opt0 ) ; // If both are initialized, values are compared - BOOST_CHECK ( opt0 != opt1 ) ; - BOOST_CHECK ( opt1 == opt2 ) ; - BOOST_CHECK ( opt0 < opt1 ) ; - BOOST_CHECK ( opt1 > opt0 ) ; - BOOST_CHECK ( opt1 <= opt2 ) ; - BOOST_CHECK ( opt1 >= opt0 ) ; + BOOST_TEST ( opt0 != opt1 ) ; + BOOST_TEST ( opt1 == opt2 ) ; + BOOST_TEST ( opt0 < opt1 ) ; + BOOST_TEST ( opt1 > opt0 ) ; + BOOST_TEST ( opt1 <= opt2 ) ; + BOOST_TEST ( opt1 >= opt0 ) ; // Compare against a value directly - BOOST_CHECK ( opt0 == v0 ) ; - BOOST_CHECK ( opt0 != v1 ) ; - BOOST_CHECK ( opt1 == v2 ) ; - BOOST_CHECK ( opt0 < v1 ) ; - BOOST_CHECK ( opt1 > v0 ) ; - BOOST_CHECK ( opt1 <= v2 ) ; - BOOST_CHECK ( opt1 >= v0 ) ; - BOOST_CHECK ( v0 != opt1 ) ; - BOOST_CHECK ( v1 == opt2 ) ; - BOOST_CHECK ( v0 < opt1 ) ; - BOOST_CHECK ( v1 > opt0 ) ; - BOOST_CHECK ( v1 <= opt2 ) ; - BOOST_CHECK ( v1 >= opt0 ) ; - BOOST_CHECK ( def0 != v0 ) ; - BOOST_CHECK ( !(def0 == v0) ) ; - BOOST_CHECK ( def0 < v0 ) ; - BOOST_CHECK ( !(def0 > v0) ) ; - BOOST_CHECK ( def0 <= v0 ) ; - BOOST_CHECK ( !(def0 >= v0) ) ; - BOOST_CHECK ( v0 != def0 ) ; - BOOST_CHECK ( !(v0 == def0) ) ; - BOOST_CHECK ( !(v0 < def0) ) ; - BOOST_CHECK ( v0 > def0 ) ; - BOOST_CHECK ( !(v0 <= def0) ) ; - BOOST_CHECK ( v0 >= opt0 ) ; + BOOST_TEST ( opt0 == v0 ) ; + BOOST_TEST ( opt0 != v1 ) ; + BOOST_TEST ( opt1 == v2 ) ; + BOOST_TEST ( opt0 < v1 ) ; + BOOST_TEST ( opt1 > v0 ) ; + BOOST_TEST ( opt1 <= v2 ) ; + BOOST_TEST ( opt1 >= v0 ) ; + BOOST_TEST ( v0 != opt1 ) ; + BOOST_TEST ( v1 == opt2 ) ; + BOOST_TEST ( v0 < opt1 ) ; + BOOST_TEST ( v1 > opt0 ) ; + BOOST_TEST ( v1 <= opt2 ) ; + BOOST_TEST ( v1 >= opt0 ) ; + BOOST_TEST ( def0 != v0 ) ; + BOOST_TEST ( !(def0 == v0) ) ; + BOOST_TEST ( def0 < v0 ) ; + BOOST_TEST ( !(def0 > v0) ) ; + BOOST_TEST ( def0 <= v0 ) ; + BOOST_TEST ( !(def0 >= v0) ) ; + BOOST_TEST ( v0 != def0 ) ; + BOOST_TEST ( !(v0 == def0) ) ; + BOOST_TEST ( !(v0 < def0) ) ; + BOOST_TEST ( v0 > def0 ) ; + BOOST_TEST ( !(v0 <= def0) ) ; + BOOST_TEST ( v0 >= opt0 ) ; } template @@ -796,16 +796,16 @@ void test_none( T const* ) optional def1(none) ; optional non_def( T(1234) ) ; - BOOST_CHECK ( def0 == none ) ; - BOOST_CHECK ( non_def != none ) ; - BOOST_CHECK ( !def1 ) ; - BOOST_CHECK ( !(non_def < none) ) ; - BOOST_CHECK ( non_def > none ) ; - BOOST_CHECK ( !(non_def <= none) ) ; - BOOST_CHECK ( non_def >= none ) ; + BOOST_TEST ( def0 == none ) ; + BOOST_TEST ( non_def != none ) ; + BOOST_TEST ( !def1 ) ; + BOOST_TEST ( !(non_def < none) ) ; + BOOST_TEST ( non_def > none ) ; + BOOST_TEST ( !(non_def <= none) ) ; + BOOST_TEST ( non_def >= none ) ; non_def = none ; - BOOST_CHECK ( !non_def ) ; + BOOST_TEST ( !non_def ) ; test_default_implicit_construction(T(1),none); } @@ -820,12 +820,12 @@ void test_arrow( T const* ) optional oa(a) ; optional const coa(a) ; - BOOST_CHECK ( coa->V() == 1234 ) ; + BOOST_TEST ( coa->V() == 1234 ) ; oa->V() = 4321 ; - BOOST_CHECK ( a.V() = 1234 ) ; - BOOST_CHECK ( (*oa).V() = 4321 ) ; + BOOST_TEST ( a.V() = 1234 ) ; + BOOST_TEST ( (*oa).V() = 4321 ) ; } void test_with_builtin_types() @@ -869,7 +869,7 @@ void test_with_class_type() test_relops( ARG(X) ) ; test_none( ARG(X) ) ; test_arrow( ARG(X) ) ; - BOOST_CHECK ( X::count == 0 ) ; + BOOST_TEST ( X::count == 0 ) ; } int eat ( bool ) { return 1 ; } @@ -888,7 +888,7 @@ void test_no_implicit_conversions_impl( T const& ) TRACE( std::endl << BOOST_CURRENT_FUNCTION ); optional def ; - BOOST_CHECK ( eat(def) == 0 ) ; + BOOST_TEST ( eat(def) == 0 ) ; } void test_no_implicit_conversions() @@ -908,7 +908,7 @@ void test_no_implicit_conversions() // Test for support for classes with overridden operator& -class CustomAddressOfClass +class CustomAddressOfClass { int n; @@ -923,18 +923,18 @@ public: void test_custom_addressof_operator() { boost::optional< CustomAddressOfClass > o1(CustomAddressOfClass(10)); - BOOST_CHECK(!!o1); - BOOST_CHECK(o1.get() == CustomAddressOfClass(10)); + BOOST_TEST(!!o1); + BOOST_TEST(o1.get() == CustomAddressOfClass(10)); o1 = CustomAddressOfClass(20); - BOOST_CHECK(!!o1); - BOOST_CHECK(o1.get() == CustomAddressOfClass(20)); + BOOST_TEST(!!o1); + BOOST_TEST(o1.get() == CustomAddressOfClass(20)); o1 = boost::none; - BOOST_CHECK(!o1); + BOOST_TEST(!o1); } -int test_main( int, char* [] ) +int main() { try { @@ -948,7 +948,7 @@ int test_main( int, char* [] ) BOOST_ERROR("Unexpected Exception caught!"); } - return 0; + return boost::report_errors(); } diff --git a/test/optional_test_common.cpp b/test/optional_test_common.cpp index a527bd7..ff197bd 100644 --- a/test/optional_test_common.cpp +++ b/test/optional_test_common.cpp @@ -159,13 +159,13 @@ 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_CHECK( X::pending_copy ) ; } -inline void check_is_pending_dtor ( X const* x ) { BOOST_CHECK( X::pending_dtor ) ; } -inline void check_is_pending_assign ( X const* x ) { BOOST_CHECK( X::pending_assign ) ; } -inline void check_is_not_pending_copy ( X const* x ) { BOOST_CHECK( !X::pending_copy ) ; } -inline void check_is_not_pending_dtor ( X const* x ) { BOOST_CHECK( !X::pending_dtor ) ; } -inline void check_is_not_pending_assign( X const* x ) { BOOST_CHECK( !X::pending_assign ) ; } -inline void check_instance_count ( int c, X const* x ) { BOOST_CHECK( X::count == c ) ; } +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 (...) {} @@ -189,21 +189,21 @@ template inline void check_uninitialized_const ( optional const& opt ) { #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE - BOOST_CHECK( opt == 0 ) ; + BOOST_TEST( opt == 0 ) ; #endif - BOOST_CHECK( !opt ) ; - BOOST_CHECK( !get_pointer(opt) ) ; - BOOST_CHECK( !opt.get_ptr() ) ; + BOOST_TEST( !opt ) ; + BOOST_TEST( !get_pointer(opt) ) ; + BOOST_TEST( !opt.get_ptr() ) ; } template inline void check_uninitialized ( optional& opt ) { #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE - BOOST_CHECK( opt == 0 ) ; + BOOST_TEST( opt == 0 ) ; #endif - BOOST_CHECK( !opt ) ; - BOOST_CHECK( !get_pointer(opt) ) ; - BOOST_CHECK( !opt.get_ptr() ) ; + BOOST_TEST( !opt ) ; + BOOST_TEST( !get_pointer(opt) ) ; + BOOST_TEST( !opt.get_ptr() ) ; check_uninitialized_const(opt); } @@ -211,29 +211,29 @@ inline void check_uninitialized ( optional& opt ) template inline void check_initialized_const ( optional const& opt ) { - BOOST_CHECK( opt ) ; + BOOST_TEST( opt ) ; #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE - BOOST_CHECK( opt != 0 ) ; + BOOST_TEST( opt != 0 ) ; #endif - BOOST_CHECK ( !!opt ) ; - BOOST_CHECK ( get_pointer(opt) ) ; - BOOST_CHECK ( opt.get_ptr() ) ; + BOOST_TEST ( !!opt ) ; + BOOST_TEST ( get_pointer(opt) ) ; + BOOST_TEST ( opt.get_ptr() ) ; } template inline void check_initialized ( optional& opt ) { - BOOST_CHECK( opt ) ; + BOOST_TEST( opt ) ; #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE - BOOST_CHECK( opt != 0 ) ; + BOOST_TEST( opt != 0 ) ; #endif - BOOST_CHECK ( !!opt ) ; - BOOST_CHECK ( get_pointer(opt) ) ; - BOOST_CHECK ( opt.get_ptr() ) ; + BOOST_TEST ( !!opt ) ; + BOOST_TEST ( get_pointer(opt) ) ; + BOOST_TEST ( opt.get_ptr() ) ; check_initialized_const(opt); } @@ -241,12 +241,12 @@ inline void check_initialized ( optional& opt ) template inline void check_value_const ( optional const& opt, T const& v, T const& z ) { - BOOST_CHECK( *opt == v ) ; - BOOST_CHECK( *opt != z ) ; - BOOST_CHECK( opt.get() == v ) ; - BOOST_CHECK( opt.get() != z ) ; - BOOST_CHECK( (*(opt.operator->()) == v) ) ; - BOOST_CHECK( *get_pointer(opt) == v ) ; + BOOST_TEST( *opt == v ) ; + BOOST_TEST( *opt != z ) ; + BOOST_TEST( opt.get() == v ) ; + BOOST_TEST( opt.get() != z ) ; + BOOST_TEST( (*(opt.operator->()) == v) ) ; + BOOST_TEST( *get_pointer(opt) == v ) ; } template @@ -258,12 +258,12 @@ inline void check_value ( optional& opt, T const& v, T const& z ) reset_throw_on_copy( ARG(T) ) ; #endif - BOOST_CHECK( *opt == v ) ; - BOOST_CHECK( *opt != z ) ; - BOOST_CHECK( opt.get() == v ) ; - BOOST_CHECK( opt.get() != z ) ; - BOOST_CHECK( (*(opt.operator->()) == v) ) ; - BOOST_CHECK( *get_pointer(opt) == v ) ; + BOOST_TEST( *opt == v ) ; + BOOST_TEST( *opt != z ) ; + BOOST_TEST( opt.get() == v ) ; + BOOST_TEST( opt.get() != z ) ; + BOOST_TEST( (*(opt.operator->()) == v) ) ; + BOOST_TEST( *get_pointer(opt) == v ) ; check_value_const(opt,v,z); } From cf4b2e8b16d158146e7ad2fc36aa755bb953dc55 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Mon, 5 Oct 2015 16:54:05 +0200 Subject: [PATCH 03/54] specialization for optional ref - preliminary --- doc/91_relnotes.qbk | 5 + doc/html/boost_optional/relnotes.html | 23 +- doc/html/index.html | 2 +- .../boost/optional/detail/optional_config.hpp | 55 +++ .../detail/optional_reference_spec.hpp | 164 +++++++++ .../boost/optional/detail/optional_relops.hpp | 195 ++++++++++ .../boost/optional/detail/optional_swap.hpp | 117 ++++++ include/boost/optional/optional.hpp | 339 +----------------- 8 files changed, 571 insertions(+), 329 deletions(-) create mode 100644 include/boost/optional/detail/optional_config.hpp create mode 100644 include/boost/optional/detail/optional_reference_spec.hpp create mode 100644 include/boost/optional/detail/optional_relops.hpp create mode 100644 include/boost/optional/detail/optional_swap.hpp diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index eb2b310..297a360 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -11,6 +11,11 @@ [section:relnotes Release Notes] +[heading Boost Release X.XX] + +* Changed the implementation of `boost::none`: now it is a constant with internal linkage. This addresses [@https://svn.boost.org/trac/boost/ticket/11203 Trac #11203]. +* Now `boost::optional` is specialized for reference parameters. This way the `sizeof` of optional reference is that of a pointer, and a number of bugs is avoided. + [heading Boost Release 1.59] * For C++03 compilers, added 0-argument overload for member function `emplace()`, and therewith removed the dependency on ``. diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html index 445eaa8..bac08cc 100644 --- a/doc/html/boost_optional/relnotes.html +++ b/doc/html/boost_optional/relnotes.html @@ -28,6 +28,23 @@

+ Boost + Release X.XX +

+
    +
  • + Changed the implementation of boost::none: + now it is a constant with internal linkage. This addresses Trac + #11203. +
  • +
  • + Now boost::optional is specialized for reference + parameters. This way the sizeof + of optional reference is that of a pointer, and a number of bugs is avoided. +
  • +
+

+ Boost Release 1.59

@@ -36,7 +53,7 @@ and therewith removed the dependency on <boost/utility/in_place_factory.hpp>.

- + Boost Release 1.58

@@ -72,7 +89,7 @@

- + Boost Release 1.57

@@ -82,7 +99,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 833a9f6..558d7e2 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -146,7 +146,7 @@ - +

Last revised: October 01, 2015 at 13:19:55 GMT

Last revised: October 05, 2015 at 14:34:49 GMT


diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp new file mode 100644 index 0000000..c069c0d --- /dev/null +++ b/include/boost/optional/detail/optional_config.hpp @@ -0,0 +1,55 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 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/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP +#define BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP + +#include +#include + +#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES) +# define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#endif + +#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700) +// AFAICT only Intel 7 correctly resolves the overload set +// that includes the in-place factory taking functions, +// so for the other icc versions, in-place factory support +// is disabled +# define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#endif + +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551) +// BCB (5.5.1) cannot parse the nested template struct in an inplace factory. +# define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#endif + +#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \ + && defined BOOST_BCB_PARTIAL_SPECIALIZATION_BUG +// BCB (up to 5.64) has the following bug: +// If there is a member function/operator template of the form +// template mfunc( Expr expr ) ; +// some calls are resolved to this even if there are other better matches. +// The effect of this bug is that calls to converting ctors and assignments +// are incorrectly sink to this general catch-all member function template as shown above. +# define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION +#endif + +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) +// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with +// regard to violation of the strict aliasing rules. The optional< T > storage type is marked +// with this attribute in order to let the compiler know that it will alias objects of type T +// and silence compilation warnings. +# define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS +#endif + +#endif // header guard diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp new file mode 100644 index 0000000..5a76a68 --- /dev/null +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -0,0 +1,164 @@ +// Copyright (C) 2015 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/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP +#define BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP + +# if 1 + +namespace boost { + +namespace detail { + +template +void prevent_binding_rvalue() +{ +#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES + BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference::value, + "binding rvalue references to optional lvalue references is disallowed"); +#endif +} + +template +typename boost::remove_reference::type& forward_reference(T&& r) +{ + BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference::value, + "binding rvalue references to optional lvalue references is disallowed"); + return boost::forward(r); +} + +template +struct is_optional_ +{ + static const bool value = false; +}; + +template +struct is_optional_<::boost::optional> +{ + static const bool value = true; +}; + +template +struct is_no_optional +{ + static const bool value = !is_optional_::type>::value; +}; + +} // namespace detail + +template +class optional : public optional_detail::optional_tag +{ + T* ptr_; + +public: + typedef T& value_type; + typedef T& reference_type; + typedef T& reference_const_type; + typedef T* pointer_type; + typedef T* pointer_const_type; + + optional() BOOST_NOEXCEPT : ptr_() {} + 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_) {} + + + optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.ptr_; return *this; } + template + optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.ptr_; return *this; } + optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; } + + + void swap(optional& rhs) BOOST_NOEXCEPT { std::swap(ptr_, rhs.ptr_); } + T& get() const { BOOST_ASSERT(ptr_); return *ptr_; } + + T* get_ptr() const BOOST_NOEXCEPT { return ptr_; } + T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; } + T& operator*() const { BOOST_ASSERT(ptr_); return *ptr_; } + T& value() const { return ptr_ ? *ptr_ : (throw_exception(bad_optional_access()), *ptr_); } + + + template + T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); } + + bool operator!() const BOOST_NOEXCEPT { return ptr_ == 0; } + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + void reset() BOOST_NOEXCEPT { ptr_ = 0; } + + bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + template + optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT + : ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue(); } + + template + optional(bool cond, R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT + : ptr_(cond ? boost::addressof(r) : 0) { detail::prevent_binding_rvalue(); } + + template + BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type + operator=(R&& r) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); return *this; } + + template + void emplace(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT + { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); } + + template + T& get_value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) const BOOST_NOEXCEPT + { detail::prevent_binding_rvalue(); return ptr_ ? *ptr_ : r; } + + template + T& value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) const BOOST_NOEXCEPT + { detail::prevent_binding_rvalue(); return ptr_ ? *ptr_ : r; } + + template + void reset(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT + { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); } + +#else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + template + optional(const U& v) BOOST_NOEXCEPT : ptr_(boost::addressof(v)) { } + + template + optional(bool cond, const U& v) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {} + + template + optional operator=(const U& v) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); return *this; } + + template + void emplace(const U& v) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); } + + template + T& get_value_or(const U& v) const BOOST_NOEXCEPT { return ptr_ ? *ptr_ : v; } + + template + T& value_or(const U& v) const BOOST_NOEXCEPT { return ptr_ ? *ptr_ : v; } + + template + void reset(const U& v) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); } + +#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +}; + +// TODO: what if no rvalue refs +} // namespace boost + +#endif // 0 + +#endif // header guard diff --git a/include/boost/optional/detail/optional_relops.hpp b/include/boost/optional/detail/optional_relops.hpp new file mode 100644 index 0000000..f3ebae0 --- /dev/null +++ b/include/boost/optional/detail/optional_relops.hpp @@ -0,0 +1,195 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 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/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_RELOPS_AJK_03OCT2015_HPP +#define BOOST_OPTIONAL_DETAIL_OPTIONAL_RELOPS_AJK_03OCT2015_HPP + +namespace boost { + +// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values). +// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead. + + +// +// optional vs optional cases +// + +template +inline +bool operator == ( optional const& x, optional const& y ) +{ return equal_pointees(x,y); } + +template +inline +bool operator < ( optional const& x, optional const& y ) +{ return less_pointees(x,y); } + +template +inline +bool operator != ( optional const& x, optional const& y ) +{ return !( x == y ) ; } + +template +inline +bool operator > ( optional const& x, optional const& y ) +{ return y < x ; } + +template +inline +bool operator <= ( optional const& x, optional const& y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( optional const& x, optional const& y ) +{ return !( x < y ) ; } + + +// +// optional vs T cases +// +template +inline +bool operator == ( optional const& x, T const& y ) +{ return equal_pointees(x, optional(y)); } + +template +inline +bool operator < ( optional const& x, T const& y ) +{ return less_pointees(x, optional(y)); } + +template +inline +bool operator != ( optional const& x, T const& y ) +{ return !( x == y ) ; } + +template +inline +bool operator > ( optional const& x, T const& y ) +{ return y < x ; } + +template +inline +bool operator <= ( optional const& x, T const& y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( optional const& x, T const& y ) +{ return !( x < y ) ; } + +// +// T vs optional cases +// + +template +inline +bool operator == ( T const& x, optional const& y ) +{ return equal_pointees( optional(x), y ); } + +template +inline +bool operator < ( T const& x, optional const& y ) +{ return less_pointees( optional(x), y ); } + +template +inline +bool operator != ( T const& x, optional const& y ) +{ return !( x == y ) ; } + +template +inline +bool operator > ( T const& x, optional const& y ) +{ return y < x ; } + +template +inline +bool operator <= ( T const& x, optional const& y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( T const& x, optional const& y ) +{ return !( x < y ) ; } + + +// +// optional vs none cases +// + +template +inline +bool operator == ( optional const& x, none_t ) BOOST_NOEXCEPT +{ return !x; } + +template +inline +bool operator < ( optional const& x, none_t ) +{ return less_pointees(x,optional() ); } + +template +inline +bool operator != ( optional const& x, none_t ) BOOST_NOEXCEPT +{ return bool(x); } + +template +inline +bool operator > ( optional const& x, none_t y ) +{ return y < x ; } + +template +inline +bool operator <= ( optional const& x, none_t y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( optional const& x, none_t y ) +{ return !( x < y ) ; } + +// +// none vs optional cases +// + +template +inline +bool operator == ( none_t , optional const& y ) BOOST_NOEXCEPT +{ return !y; } + +template +inline +bool operator < ( none_t , optional const& y ) +{ return less_pointees(optional() ,y); } + +template +inline +bool operator != ( none_t, optional const& y ) BOOST_NOEXCEPT +{ return bool(y); } + +template +inline +bool operator > ( none_t x, optional const& y ) +{ return y < x ; } + +template +inline +bool operator <= ( none_t x, optional const& y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( none_t x, optional const& y ) +{ return !( x < y ) ; } + +} // namespace boost + +#endif // header guard \ No newline at end of file diff --git a/include/boost/optional/detail/optional_swap.hpp b/include/boost/optional/detail/optional_swap.hpp new file mode 100644 index 0000000..2a7059e --- /dev/null +++ b/include/boost/optional/detail/optional_swap.hpp @@ -0,0 +1,117 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 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/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP +#define BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP + +#include +#include + +namespace boost { + +namespace optional_detail { + +template struct swap_selector; + +template <> +struct swap_selector +{ + template + static void optional_swap ( optional& x, optional& y ) + { + const bool hasX = !!x; + const bool hasY = !!y; + + if ( !hasX && !hasY ) + return; + + if( !hasX ) + x.emplace(); + else if ( !hasY ) + y.emplace(); + + // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers + boost::swap(x.get(), y.get()); + + if( !hasX ) + y = boost::none ; + else if( !hasY ) + x = boost::none ; + } +}; + +#ifdef BOOST_OPTIONAL_DETAIL_MOVE +# undef BOOST_OPTIONAL_DETAIL_MOVE +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) boost::move(EXPR_) +#else +# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) EXPR_ +#endif + +template <> +struct swap_selector +{ + template + static void optional_swap ( optional& x, optional& y ) + //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y))) + { + if (x) + { + if (y) + { + boost::swap(*x, *y); + } + else + { + y = BOOST_OPTIONAL_DETAIL_MOVE(*x); + x = boost::none; + } + } + else + { + if (y) + { + x = BOOST_OPTIONAL_DETAIL_MOVE(*y); + y = boost::none; + } + } + } +}; + +} // namespace optional_detail + +#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_CONFIG_RESTORE_OBSOLETE_SWAP_IMPLEMENTATION) + +template +struct optional_swap_should_use_default_constructor : boost::false_type {} ; + +#else + +template +struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor {} ; + +#endif + +template +inline void swap ( optional& x, optional& y ) +//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y))) +{ + optional_detail::swap_selector::value>::optional_swap(x, y); +} + +} // namespace boost + +#undef BOOST_OPTIONAL_DETAIL_MOVE + +#endif // header guard diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 9def94e..9cdc7ea 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -52,42 +51,7 @@ #include #include - -#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES) -#define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES -#endif - -#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700) -// AFAICT only Intel 7 correctly resolves the overload set -// that includes the in-place factory taking functions, -// so for the other icc versions, in-place factory support -// is disabled -#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT -#endif - -#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551) -// BCB (5.5.1) cannot parse the nested template struct in an inplace factory. -#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT -#endif - -#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \ - && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581) ) -// BCB (up to 5.64) has the following bug: -// If there is a member function/operator template of the form -// template mfunc( Expr expr ) ; -// some calls are resolved to this even if there are other better matches. -// The effect of this bug is that calls to converting ctors and assignments -// are incrorrectly sink to this general catch-all member function template as shown above. -#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION -#endif - -#if defined(__GNUC__) && !defined(__INTEL_COMPILER) -// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with -// regard to violation of the strict aliasing rules. The optional< T > storage type is marked -// with this attribute in order to let the compiler know that it will alias objects of type T -// and silence compilation warnings. -#define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS -#endif +#include // Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<> // member template of a factory as used in the optional<> implementation. @@ -102,7 +66,6 @@ namespace boost_optional_detail } } - namespace boost { class in_place_factory_base ; @@ -252,7 +215,7 @@ class optional_base : public optional_tag : m_initialized(false) { - construct(val); + construct(val); } #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES @@ -1180,6 +1143,14 @@ class optional } ; #endif +} // namespace boost + +#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS +# include +#endif + +namespace boost { + // Returns optional(v) template inline @@ -1277,291 +1248,9 @@ operator<<(std::basic_ostream& os, optional_detail::optiona return os; } -// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values). -// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead. - - -// -// optional vs optional cases -// - -template -inline -bool operator == ( optional const& x, optional const& y ) -{ return equal_pointees(x,y); } - -template -inline -bool operator < ( optional const& x, optional const& y ) -{ return less_pointees(x,y); } - -template -inline -bool operator != ( optional const& x, optional const& y ) -{ return !( x == y ) ; } - -template -inline -bool operator > ( optional const& x, optional const& y ) -{ return y < x ; } - -template -inline -bool operator <= ( optional const& x, optional const& y ) -{ return !( y < x ) ; } - -template -inline -bool operator >= ( optional const& x, optional const& y ) -{ return !( x < y ) ; } - - -// -// optional vs T cases -// -template -inline -bool operator == ( optional const& x, T const& y ) -{ return equal_pointees(x, optional(y)); } - -template -inline -bool operator < ( optional const& x, T const& y ) -{ return less_pointees(x, optional(y)); } - -template -inline -bool operator != ( optional const& x, T const& y ) -{ return !( x == y ) ; } - -template -inline -bool operator > ( optional const& x, T const& y ) -{ return y < x ; } - -template -inline -bool operator <= ( optional const& x, T const& y ) -{ return !( y < x ) ; } - -template -inline -bool operator >= ( optional const& x, T const& y ) -{ return !( x < y ) ; } - -// -// T vs optional cases -// - -template -inline -bool operator == ( T const& x, optional const& y ) -{ return equal_pointees( optional(x), y ); } - -template -inline -bool operator < ( T const& x, optional const& y ) -{ return less_pointees( optional(x), y ); } - -template -inline -bool operator != ( T const& x, optional const& y ) -{ return !( x == y ) ; } - -template -inline -bool operator > ( T const& x, optional const& y ) -{ return y < x ; } - -template -inline -bool operator <= ( T const& x, optional const& y ) -{ return !( y < x ) ; } - -template -inline -bool operator >= ( T const& x, optional const& y ) -{ return !( x < y ) ; } - - -// -// optional vs none cases -// - -template -inline -bool operator == ( optional const& x, none_t ) BOOST_NOEXCEPT -{ return !x; } - -template -inline -bool operator < ( optional const& x, none_t ) -{ return less_pointees(x,optional() ); } - -template -inline -bool operator != ( optional const& x, none_t ) BOOST_NOEXCEPT -{ return bool(x); } - -template -inline -bool operator > ( optional const& x, none_t y ) -{ return y < x ; } - -template -inline -bool operator <= ( optional const& x, none_t y ) -{ return !( y < x ) ; } - -template -inline -bool operator >= ( optional const& x, none_t y ) -{ return !( x < y ) ; } - -// -// none vs optional cases -// - -template -inline -bool operator == ( none_t , optional const& y ) BOOST_NOEXCEPT -{ return !y; } - -template -inline -bool operator < ( none_t , optional const& y ) -{ return less_pointees(optional() ,y); } - -template -inline -bool operator != ( none_t, optional const& y ) BOOST_NOEXCEPT -{ return bool(y); } - -template -inline -bool operator > ( none_t x, optional const& y ) -{ return y < x ; } - -template -inline -bool operator <= ( none_t x, optional const& y ) -{ return !( y < x ) ; } - -template -inline -bool operator >= ( none_t x, optional const& y ) -{ return !( x < y ) ; } - -namespace optional_detail { - -template struct swap_selector; - -template<> -struct swap_selector -{ - template - static void optional_swap ( optional& x, optional& y ) - { - const bool hasX = !!x; - const bool hasY = !!y; - - if ( !hasX && !hasY ) - return; - - if( !hasX ) - x.emplace(); - else if ( !hasY ) - y.emplace(); - - // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers - boost::swap(x.get(),y.get()); - - if( !hasX ) - y = boost::none ; - else if( !hasY ) - x = boost::none ; - } -}; - -#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES -template<> -struct swap_selector -{ - template - static void optional_swap ( optional& x, optional& y ) - //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y))) - { - if(x) - { - if (y) - { - boost::swap(*x, *y); - } - else - { - y = boost::move(*x); - x = boost::none; - } - } - else - { - if (y) - { - x = boost::move(*y); - y = boost::none; - } - } - } -}; -#else -template<> -struct swap_selector -{ - template - static void optional_swap ( optional& x, optional& y ) - { - const bool hasX = !!x; - const bool hasY = !!y; - - if ( !hasX && hasY ) - { - x = y.get(); - y = boost::none ; - } - else if ( hasX && !hasY ) - { - y = x.get(); - x = boost::none ; - } - else if ( hasX && hasY ) - { - // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers - boost::swap(x.get(),y.get()); - } - } -}; -#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES - -} // namespace optional_detail - -#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_CONFIG_RESTORE_OBSOLETE_SWAP_IMPLEMENTATION) - -template -struct optional_swap_should_use_default_constructor : boost::false_type {} ; - -#else - -template -struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor {} ; - -#endif //BOOST_NO_CXX11_RVALUE_REFERENCES - -template inline void swap ( optional& x, optional& y ) - //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y))) -{ - optional_detail::swap_selector::value>::optional_swap(x, y); -} - } // namespace boost -#endif +#include +#include + +#endif // header guard From e7cab0e2334b2cc9a402fbe58a2251c8c47c7337 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Mon, 5 Oct 2015 23:50:11 +0200 Subject: [PATCH 04/54] fixed digraphs in optional refs --- .../optional/detail/optional_reference_spec.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 5a76a68..35319cc 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -28,29 +28,29 @@ void prevent_binding_rvalue() } template -typename boost::remove_reference::type& forward_reference(T&& r) +BOOST_DEDUCED_TYPENAME boost::remove_reference::type& forward_reference(T&& r) { BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference::value, "binding rvalue references to optional lvalue references is disallowed"); return boost::forward(r); } -template +template struct is_optional_ { static const bool value = false; }; -template -struct is_optional_<::boost::optional> +template +struct is_optional_< ::boost::optional > { static const bool value = true; }; -template +template struct is_no_optional { - static const bool value = !is_optional_::type>::value; + static const bool value = !is_optional_::type>::value; }; } // namespace detail @@ -90,7 +90,7 @@ public: T& value() const { return ptr_ ? *ptr_ : (throw_exception(bad_optional_access()), *ptr_); } - template + template T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); } bool operator!() const BOOST_NOEXCEPT { return ptr_ == 0; } From b0d7786e143b31e155856d00cb1eb09a30b64f83 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Tue, 6 Oct 2015 00:33:14 +0200 Subject: [PATCH 05/54] bug fixes --- .../detail/optional_reference_spec.hpp | 21 ++++++++++++------- test/optional_test_emplace.cpp | 10 ++++----- test/optional_test_move.cpp | 4 ++-- test/optional_test_noexcept_move.cpp | 4 ++-- test/optional_test_value_access.cpp | 2 +- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 35319cc..f64e581 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -82,7 +82,7 @@ public: void swap(optional& rhs) BOOST_NOEXCEPT { std::swap(ptr_, rhs.ptr_); } - T& get() const { BOOST_ASSERT(ptr_); return *ptr_; } + T& get() const { BOOST_ASSERT(ptr_); return *ptr_; } T* get_ptr() const BOOST_NOEXCEPT { return ptr_; } T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; } @@ -133,25 +133,30 @@ public: #else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template - optional(const U& v) BOOST_NOEXCEPT : ptr_(boost::addressof(v)) { } + optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(boost::addressof(v)) { } template - optional(bool cond, const U& v) 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 - optional operator=(const U& v) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); return *this; } + BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type + operator=(U& v) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); return *this; } template - void emplace(const U& v) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); } + void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT + { ptr_ = boost::addressof(v); } template - T& get_value_or(const U& v) const BOOST_NOEXCEPT { return ptr_ ? *ptr_ : v; } + T& get_value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) const BOOST_NOEXCEPT + { return ptr_ ? *ptr_ : v; } template - T& value_or(const U& v) const BOOST_NOEXCEPT { return ptr_ ? *ptr_ : v; } + T& value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) const BOOST_NOEXCEPT + { return ptr_ ? *ptr_ : v; } template - void reset(const U& v) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); } + void reset(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT + { ptr_ = boost::addressof(v); } #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES }; diff --git a/test/optional_test_emplace.cpp b/test/optional_test_emplace.cpp index 0aa6674..1877a54 100644 --- a/test/optional_test_emplace.cpp +++ b/test/optional_test_emplace.cpp @@ -24,7 +24,7 @@ using boost::optional; using boost::none; -#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) class Guard { @@ -90,7 +90,7 @@ void test_emplace() #endif -#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) struct ThrowOnMove @@ -120,7 +120,7 @@ struct Thrower private: Thrower(Thrower const&); -#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) Thrower(Thrower&&); #endif }; @@ -192,10 +192,10 @@ void test_emplace() int main() { -#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) test_emplace(); #endif -#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) test_no_moves_on_emplacement(); #endif test_clear_on_throw(); diff --git a/test/optional_test_move.cpp b/test/optional_test_move.cpp index 51aa970..1558c34 100644 --- a/test/optional_test_move.cpp +++ b/test/optional_test_move.cpp @@ -24,7 +24,7 @@ using boost::none; //#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT //#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES enum State { @@ -334,7 +334,7 @@ void test_optional_ref_to_movables() int main() { -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES test_move_ctor_from_U(); test_move_ctor_form_T(); test_move_ctor_from_optional_T(); diff --git a/test/optional_test_noexcept_move.cpp b/test/optional_test_noexcept_move.cpp index 9ce927f..0675844 100644 --- a/test/optional_test_noexcept_move.cpp +++ b/test/optional_test_noexcept_move.cpp @@ -20,7 +20,7 @@ using boost::optional; -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES #ifndef BOOST_NO_CXX11_NOEXCEPT // these 4 classes have different noexcept signatures in move operations @@ -106,7 +106,7 @@ void test_noexcept_optional_with_operator() // compile-time test } #endif // !defned BOOST_NO_CXX11_NOEXCEPT -#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES int main() { diff --git a/test/optional_test_value_access.cpp b/test/optional_test_value_access.cpp index 1759588..47ec5cc 100644 --- a/test/optional_test_value_access.cpp +++ b/test/optional_test_value_access.cpp @@ -175,7 +175,7 @@ void test_const_move() } -#ifndef BOOST_NO_CXX11_REF_QUALIFIERS +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) struct MoveOnly { explicit MoveOnly(int){} From 493961307089ec474a94271605e2905a46227f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Tue, 6 Oct 2015 09:17:14 +0200 Subject: [PATCH 06/54] added missing ifdef --- include/boost/optional/detail/optional_reference_spec.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index f64e581..61e7eee 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -18,6 +18,8 @@ namespace boost { namespace detail { +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template void prevent_binding_rvalue() { @@ -35,6 +37,8 @@ BOOST_DEDUCED_TYPENAME boost::remove_reference::type& forward_reference(T&& r return boost::forward(r); } +#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template struct is_optional_ { From fb1edf51e8cd519e309713de15fd8ca863b31371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Tue, 6 Oct 2015 12:39:02 +0200 Subject: [PATCH 07/54] value_or_eval fix --- .../boost/optional/detail/optional_reference_spec.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 61e7eee..79d1869 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -92,10 +92,6 @@ public: T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; } T& operator*() const { BOOST_ASSERT(ptr_); return *ptr_; } T& value() const { return ptr_ ? *ptr_ : (throw_exception(bad_optional_access()), *ptr_); } - - - template - T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); } bool operator!() const BOOST_NOEXCEPT { return ptr_ == 0; } BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() @@ -134,6 +130,9 @@ public: void reset(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); } + template + T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); } + #else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template @@ -162,6 +161,9 @@ public: void reset(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); } + template + T& value_or_eval(F f) const { return ptr_ ? *ptr_ : f(); } + #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES }; From bc91cac244e43770b4a30d171afca5f1e7973b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Hunold?= Date: Wed, 7 Oct 2015 09:02:13 +0200 Subject: [PATCH 08/54] Add newline at EOF --- include/boost/optional/detail/optional_relops.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/optional/detail/optional_relops.hpp b/include/boost/optional/detail/optional_relops.hpp index f3ebae0..3f96117 100644 --- a/include/boost/optional/detail/optional_relops.hpp +++ b/include/boost/optional/detail/optional_relops.hpp @@ -192,4 +192,5 @@ bool operator >= ( none_t x, optional const& y ) } // namespace boost -#endif // header guard \ No newline at end of file +#endif // header guard + From 0d5061aebe7b139e4dd80262e56dcaa84b18eacb Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 8 Oct 2015 18:53:28 +0200 Subject: [PATCH 09/54] experimental optional config test --- .../boost/optional/detail/optional_config.hpp | 7 ++++ test/Jamfile.v2 | 2 + ...g_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp | 42 +++++++++++++++++++ ...g_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp | 41 ++++++++++++++++++ ..._NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp | 41 ++++++++++++++++++ ..._NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp | 40 ++++++++++++++++++ 6 files changed, 173 insertions(+) create mode 100644 test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp create mode 100644 test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp create mode 100644 test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp create mode 100644 test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index c069c0d..4c1e539 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -52,4 +52,11 @@ # define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS #endif +#if (defined(_MSC_VER) && _MSC_VER <= 1800) +// on MSCV 2013 and earlier an unwanted temporary is created when you assign from +// a const lvalue of integral type. Thus we bind not to the original address but +// to a temporary. +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT +#endif + #endif // header guard diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6b4e857..f526563 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -60,5 +60,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_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp ] + [ run-fail optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp ] ; } diff --git a/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp b/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp new file mode 100644 index 0000000..7bf6d92 --- /dev/null +++ b/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 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/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + +int main() +{ + BOOST_ERROR("failed as requested"); + return boost::report_errors(); +} + +#else + +const int global_i = 0; + +struct Binder +{ + void operator=(const int& i) + { + BOOST_TEST(&i == &global_i); + } +}; + +int main() +{ + Binder s; + s = global_i; + return boost::report_errors(); +} + +#endif diff --git a/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp b/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp new file mode 100644 index 0000000..942b856 --- /dev/null +++ b/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2015 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/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + +const int global_i = 0; + +struct Binder +{ + void operator=(const int& i) + { + BOOST_TEST(&i == &global_i); + } +}; + +int main() +{ + Binder s; + s = global_i; + return boost::report_errors(); +} + +#else + +int main() +{ + return boost::report_errors(); +} + +#endif diff --git a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp new file mode 100644 index 0000000..ae16261 --- /dev/null +++ b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2015 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/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + +int main() +{ + BOOST_ERROR("failed as requested"); + return boost::report_errors(); +} + +#else + +const int global_i = 0; + +struct Binder +{ + Binder(const int& i) + { + BOOST_TEST(&i == &global_i); + } +}; + +int main() +{ + Binder b = global_i; + return boost::report_errors(); +} + +#endif diff --git a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp new file mode 100644 index 0000000..ea1f3ce --- /dev/null +++ b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2015 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/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + +const int global_i = 0; + +struct Binder +{ + Binder(const int& i) + { + BOOST_TEST(&i == &global_i); + } +}; + +int main() +{ + Binder b = global_i; + return boost::report_errors(); +} + +#else + +int main() +{ + return boost::report_errors(); +} + +#endif From 6375fccf278571aad2af5c696a43c7d7bd9f213c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Sat, 10 Oct 2015 15:23:38 +0200 Subject: [PATCH 10/54] NO_PROPER_CONVERT_FROM_CONST_INT macro --- include/boost/optional/detail/optional_config.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index 4c1e539..bab9236 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -59,4 +59,13 @@ # define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT #endif +#if defined(__GNUC__) +# if (__GNUC__ == 5 && __GNUC_MINOR__ <= 2) || (__GNUC__ == 6 && __GNUC_MINOR__ < 1) +// On GCC 5.1, 5.2 and 6.0 an unwanted temporary is created when you copy-initialize +// from a const lvalue of integral type. Thus we bind not to the original address but +// to a temporary. +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif +#endif + #endif // header guard From 80a245c8deeaab195be7707d4aeae8e29a3ffb88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Sat, 10 Oct 2015 15:25:14 +0200 Subject: [PATCH 11/54] ASSIGN -> CONVERT --- test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp index ea1f3ce..a534f43 100644 --- a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp +++ b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp @@ -12,7 +12,7 @@ #include "boost/core/lightweight_test.hpp" #include "boost/optional/detail/optional_config.hpp" -#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT const int global_i = 0; From ffa64ccea259be9bd616b2b815dffc7c1fb9f2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Sat, 10 Oct 2015 15:26:32 +0200 Subject: [PATCH 12/54] ASSIGN -> CONVERT --- ...onal_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp index ae16261..42b3606 100644 --- a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp +++ b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp @@ -12,7 +12,7 @@ #include "boost/core/lightweight_test.hpp" #include "boost/optional/detail/optional_config.hpp" -#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT int main() { @@ -26,9 +26,9 @@ const int global_i = 0; struct Binder { - Binder(const int& i) - { - BOOST_TEST(&i == &global_i); + Binder(const int& i) + { + BOOST_TEST(&i == &global_i); } }; From 7490a62a005850c054fc390bcf0bf0f6d3ed299e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Sat, 10 Oct 2015 15:27:46 +0200 Subject: [PATCH 13/54] added NO-CONVERT tests --- test/Jamfile.v2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f526563..fcb1e49 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -62,5 +62,7 @@ import testing ; [ compile-fail optional_test_fail_convert_assign_of_enums.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 ] + [ run-fail optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp ] ; } From c71e860a06b0163fe89d7850ed3e4a8c1fe94dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Mon, 12 Oct 2015 11:14:10 +0200 Subject: [PATCH 14/54] fake test for checking build versions --- ...xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp diff --git a/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp new file mode 100644 index 0000000..561c843 --- /dev/null +++ b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2015 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/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +int main() +{ +#if defined(__GNUC__) + int empty = 0; + BOOST_TEST_EQ(empty, __GNUC__); + BOOST_TEST_EQ(empty, __GNUC_MINOR__); + BOOST_TEST_EQ(empty, __GNUC_PATCHLEVEL__); + BOOST_TEST_EQ(empty, __cplusplus); +#endif + return boost::report_errors(); +} From 2eaf2230859f8221d1399e57f0a8cc3f17b81c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Mon, 12 Oct 2015 11:14:59 +0200 Subject: [PATCH 15/54] fake test for checking build versions --- test/Jamfile.v2 | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fcb1e49..29faeba 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -64,5 +64,6 @@ import testing ; [ run-fail optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp ] [ run optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp ] [ run-fail optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp ] + [ run optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp ] ; } From 24fbacb037afc6e48926d9737136d0aff082aaa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Mon, 12 Oct 2015 12:29:24 +0200 Subject: [PATCH 16/54] Fixed unused warning --- test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp index 42b3606..07bb1b6 100644 --- a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp +++ b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp @@ -9,6 +9,7 @@ // You are welcome to contact the author at: // akrzemi1@gmail.com +#include "boost/core/ignore_unused.hpp" #include "boost/core/lightweight_test.hpp" #include "boost/optional/detail/optional_config.hpp" @@ -35,6 +36,7 @@ struct Binder int main() { Binder b = global_i; + boost::ignore_unused(b); return boost::report_errors(); } From 78fe81e3ed66905333a17bce8f48417b43a05d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Mon, 12 Oct 2015 12:30:57 +0200 Subject: [PATCH 17/54] Fixed unused warning --- ...onal_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp index a534f43..b71554e 100644 --- a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp +++ b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp @@ -9,6 +9,7 @@ // You are welcome to contact the author at: // akrzemi1@gmail.com +#include "boost/core/ignore_unused.hpp" #include "boost/core/lightweight_test.hpp" #include "boost/optional/detail/optional_config.hpp" @@ -18,15 +19,16 @@ const int global_i = 0; struct Binder { - Binder(const int& i) - { - BOOST_TEST(&i == &global_i); + Binder(const int& i) + { + BOOST_TEST(&i == &global_i); } }; int main() { Binder b = global_i; + boost::ignore_unused(b); return boost::report_errors(); } From 29975d61928bb4ca368dfc65cac4055bbcd6ffba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Tue, 13 Oct 2015 10:47:26 +0200 Subject: [PATCH 18/54] Config: improved NO_PROPER_CONVERT --- .../boost/optional/detail/optional_config.hpp | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index bab9236..45caff9 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -60,12 +60,26 @@ #endif #if defined(__GNUC__) -# if (__GNUC__ == 5 && __GNUC_MINOR__ <= 2) || (__GNUC__ == 6 && __GNUC_MINOR__ < 1) -// On GCC 5.1, 5.2 and 6.0 an unwanted temporary is created when you copy-initialize +// On some GCC versions an unwanted temporary is created when you copy-initialize // from a const lvalue of integral type. Thus we bind not to the original address but // to a temporary. + +# if (__GNUC__ == 4 && __GNUC_MINOR__ == 4) # define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT # endif -#endif + +# if (__GNUC__ == 4 && __GNUC_MINOR__ == 5) +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif + +# if (__GNUC__ == 5 && __GNUC_MINOR__ < 2) +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif + +# if (__GNUC__ == 5 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ == 0) +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif + +#endif // defined(__GNUC__) #endif // header guard From fb1cf2581eb93e88adf2077301eb9b6ebce61776 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Wed, 14 Oct 2015 23:11:33 +0200 Subject: [PATCH 19/54] Config: detect ref convert bug in gcc 4.4 and 4.5 --- include/boost/none.hpp | 2 +- include/boost/none_t.hpp | 2 +- .../boost/optional/detail/optional_config.hpp | 14 +++++++ test/Jamfile.v2 | 2 + ...xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp | 2 +- ...xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp | 37 +++++++++++++++++ ...xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp | 41 +++++++++++++++++++ 7 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp create mode 100644 test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp diff --git a/include/boost/none.hpp b/include/boost/none.hpp index db744e5..a37c45c 100644 --- a/include/boost/none.hpp +++ b/include/boost/none.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2003, Fernando Luis Cacciola Carballal. -// Copyright (C) 2014 Andrzej Krzemienski. +// Copyright (C) 2014, 2015 Andrzej Krzemienski. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/none_t.hpp b/include/boost/none_t.hpp index 608cb0c..fa73654 100644 --- a/include/boost/none_t.hpp +++ b/include/boost/none_t.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2003, Fernando Luis Cacciola Carballal. -// Copyright (C) 2014 Andrzej Krzemienski. +// Copyright (C) 2014, 2015 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/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index 45caff9..6e1fa8b 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -82,4 +82,18 @@ #endif // defined(__GNUC__) +#if defined(__GNUC__) +// On some initial rvalue reference implementations GCC does it in a strange way, +// preferring perfect-forwarding constructor to implicit copy constructor. + +# if (__GNUC__ == 4 && __GNUC_MINOR__ == 4) +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif + +# if (__GNUC__ == 4 && __GNUC_MINOR__ == 5) +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif + +#endif // defined(__GNUC__) + #endif // header guard diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 29faeba..765fe53 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -64,6 +64,8 @@ import testing ; [ run-fail optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp ] [ run optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp ] [ run-fail optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp ] + [ run optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp ] + [ compile-fail optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp ] [ run optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp ] ; } diff --git a/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp index 561c843..f733bac 100644 --- a/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp +++ b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp @@ -15,7 +15,7 @@ int main() { #if defined(__GNUC__) - int empty = 0; + int empty = -1; BOOST_TEST_EQ(empty, __GNUC__); BOOST_TEST_EQ(empty, __GNUC_MINOR__); BOOST_TEST_EQ(empty, __GNUC_PATCHLEVEL__); diff --git a/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp new file mode 100644 index 0000000..18d6c87 --- /dev/null +++ b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2015 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/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF + +static_assert(false, "failed as requested"); + +#else + +struct S {}; + +struct Binder +{ + S& ref_; + template Binder (R&&r) : ref_(r) {} +}; + +int main() +{ + S s ; + Binder b = s; + boost::ignore_unused(b); +} + +#endif diff --git a/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp new file mode 100644 index 0000000..be7d47c --- /dev/null +++ b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2015 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/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF + +struct S {}; + +struct Binder +{ + S& ref_; + template Binder (R&&r) : ref_(r) {} +}; + +int main() +{ + S s ; + Binder b = s; + boost::ignore_unused(b); + return 0; +} + +#else + +int main() +{ + return 0; +} + +#endif From ade05cdffa85a4836c2090d2e94de5d61f82a62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Thu, 15 Oct 2015 08:42:36 +0200 Subject: [PATCH 20/54] CFG: handling C++03 compilers --- ...ional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp index be7d47c..a6edbc6 100644 --- a/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp +++ b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp @@ -13,7 +13,11 @@ #include "boost/core/lightweight_test.hpp" #include "boost/optional/detail/optional_config.hpp" -#ifndef BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF +#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF) + +int main() { return 0; } + +#else struct S {}; @@ -31,11 +35,4 @@ int main() return 0; } -#else - -int main() -{ - return 0; -} - #endif From 184816ad4d736ac3d8d13d03da20e8a78d2bf46f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Thu, 15 Oct 2015 08:46:52 +0200 Subject: [PATCH 21/54] CFG: handling C++03 compilers --- test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 18d6c87..8cc1e70 100644 --- a/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp +++ b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp @@ -13,7 +13,7 @@ #include "boost/core/lightweight_test.hpp" #include "boost/optional/detail/optional_config.hpp" -#ifndef BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF +#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (!defined BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF) static_assert(false, "failed as requested"); From 472a94d371cc612e344ea57247c1517f8c1b4736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Thu, 15 Oct 2015 08:48:34 +0200 Subject: [PATCH 22/54] CFG: handling C++03 compilers --- include/boost/optional/detail/optional_config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index 6e1fa8b..5f88f3f 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -82,7 +82,7 @@ #endif // defined(__GNUC__) -#if defined(__GNUC__) +#if (defined __GNUC__) && (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) // On some initial rvalue reference implementations GCC does it in a strange way, // preferring perfect-forwarding constructor to implicit copy constructor. From 74bd6444db31d8ff38bd8de51ea1308c3fa26679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Mon, 19 Oct 2015 10:21:54 +0200 Subject: [PATCH 23/54] config: excluding intel --- include/boost/optional/detail/optional_config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index 5f88f3f..00220ae 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -82,7 +82,7 @@ #endif // defined(__GNUC__) -#if (defined __GNUC__) && (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) +#if (defined __GNUC__) && (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_INTEL_CXX_VERSION) // On some initial rvalue reference implementations GCC does it in a strange way, // preferring perfect-forwarding constructor to implicit copy constructor. From 9ea065edf1de033e61ba81f065518b7d57a71bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Mon, 19 Oct 2015 10:33:17 +0200 Subject: [PATCH 24/54] hack: check rrefs --- ...ptional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp index f733bac..1cd2c2b 100644 --- a/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp +++ b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp @@ -11,10 +11,21 @@ #include "boost/core/lightweight_test.hpp" #include "boost/optional/detail/optional_config.hpp" +#include int main() { #if defined(__GNUC__) + + std::string rrefs_y = "HAS RVALUE REFS"; + std::string rrefs_n = "NO RVALUE REFS"; + +#if !defined BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_TEST_EQ("", rrefs_y); +#else + BOOST_TEST_EQ("", rrefs_n); +#endif + int empty = -1; BOOST_TEST_EQ(empty, __GNUC__); BOOST_TEST_EQ(empty, __GNUC_MINOR__); From 3ae18175b566f5a4ae8c86e960bf4c7f1d8f27e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Tue, 20 Oct 2015 09:15:40 +0200 Subject: [PATCH 25/54] hack: detect intel --- ...ional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp index 1cd2c2b..e6b6ba0 100644 --- a/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp +++ b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp @@ -17,13 +17,18 @@ int main() { #if defined(__GNUC__) - std::string rrefs_y = "HAS RVALUE REFS"; - std::string rrefs_n = "NO RVALUE REFS"; + std::string emptys; + +#ifdef BOOST_INTEL_CXX_VERSION + BOOST_TEST_EQ(emptys, "HAS INTEL INSIDE"); +#else + BOOST_TEST_EQ(emptys, "NO INTEL INSIDE"); +#endif #if !defined BOOST_NO_CXX11_RVALUE_REFERENCES - BOOST_TEST_EQ("", rrefs_y); + BOOST_TEST_EQ(emptys, "HAS RVALUE REFS"); #else - BOOST_TEST_EQ("", rrefs_n); + BOOST_TEST_EQ(emptys, "NO RVALUE REFS"); #endif int empty = -1; From b96337a6d78b435c550fdb473693f816f1151c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Tue, 20 Oct 2015 09:21:02 +0200 Subject: [PATCH 26/54] no intel detection --- include/boost/optional/detail/optional_config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index 00220ae..5f88f3f 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -82,7 +82,7 @@ #endif // defined(__GNUC__) -#if (defined __GNUC__) && (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_INTEL_CXX_VERSION) +#if (defined __GNUC__) && (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) // On some initial rvalue reference implementations GCC does it in a strange way, // preferring perfect-forwarding constructor to implicit copy constructor. From c6abecb89f4fa95994c0ab30a0a9e5f7af8bec0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Tue, 20 Oct 2015 09:21:52 +0200 Subject: [PATCH 27/54] config: fixed fail test --- test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp index 07bb1b6..c152c69 100644 --- a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp +++ b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp @@ -17,7 +17,7 @@ int main() { - BOOST_ERROR("failed as requested"); + static_assert(false, "failed as requested"); return boost::report_errors(); } From 7138a166807b59dcd507b32d67e836410e97dd8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Tue, 20 Oct 2015 15:45:30 +0200 Subject: [PATCH 28/54] config: reverted fix --- test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp index c152c69..07bb1b6 100644 --- a/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp +++ b/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp @@ -17,7 +17,7 @@ int main() { - static_assert(false, "failed as requested"); + BOOST_ERROR("failed as requested"); return boost::report_errors(); } From 7396e4051b3497e035c284cc27912d0318f85e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Tue, 20 Oct 2015 16:02:04 +0200 Subject: [PATCH 29/54] config: fixed bad name --- include/boost/optional/detail/optional_config.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index 5f88f3f..92a362f 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -87,11 +87,11 @@ // preferring perfect-forwarding constructor to implicit copy constructor. # if (__GNUC__ == 4 && __GNUC_MINOR__ == 4) -# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# define BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF # endif # if (__GNUC__ == 4 && __GNUC_MINOR__ == 5) -# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# define BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF # endif #endif // defined(__GNUC__) From 4b3077dea3f5b5cc5bc15d3e017e84ddabc5aee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Tue, 20 Oct 2015 23:42:03 +0200 Subject: [PATCH 30/54] config: if for intel --- include/boost/optional/detail/optional_config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index 92a362f..78eadf0 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -59,7 +59,7 @@ # define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT #endif -#if defined(__GNUC__) +#if (defined __GNUC__) && (!defined BOOST_INTEL_CXX_VERSION) // On some GCC versions an unwanted temporary is created when you copy-initialize // from a const lvalue of integral type. Thus we bind not to the original address but // to a temporary. From 0a228e74fe17ca203a8be84f6feee37dccaec3fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Sat, 24 Oct 2015 22:45:00 +0200 Subject: [PATCH 31/54] Config: NO_PROPER_CONVERT in older GCC --- include/boost/optional/detail/optional_config.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index 78eadf0..648744e 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -59,16 +59,16 @@ # define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT #endif -#if (defined __GNUC__) && (!defined BOOST_INTEL_CXX_VERSION) +#if (defined __GNUC__) && (!defined BOOST_INTEL_CXX_VERSION) && (!defined __clang__) // On some GCC versions an unwanted temporary is created when you copy-initialize // from a const lvalue of integral type. Thus we bind not to the original address but // to a temporary. -# if (__GNUC__ == 4 && __GNUC_MINOR__ == 4) +# if (__GNUC__ < 4) # define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT # endif -# if (__GNUC__ == 4 && __GNUC_MINOR__ == 5) +# if (__GNUC__ == 4 && __GNUC_MINOR__ <= 5) # define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT # endif From 2ae5c255fdd5212dd563436dcd4cb1f5733ff2ca Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 10 Jan 2016 15:15:44 +0000 Subject: [PATCH 32/54] Fix the category. --- meta/libraries.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/libraries.json b/meta/libraries.json index 4bdac31..2c60271 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -7,7 +7,7 @@ ], "description": "A value-semantic, type-safe wrapper for representing 'optional' (or 'nullable') objects of a given type. An optional object may or may not contain a value of the underlying type.", "category": [ - "Data structures" + "Data" ], "maintainers": [ "Fernando Cacciola ", From 4b91299d10c0c45fb0e2821ffd9fc5f106b20c34 Mon Sep 17 00:00:00 2001 From: akumta Date: Wed, 20 Jan 2016 11:15:40 -0800 Subject: [PATCH 33/54] update for ticket #11927 std::swap for C++ 03 is located under and for C++11 under --- test/optional_test_swap.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/optional_test_swap.cpp b/test/optional_test_swap.cpp index dac7ae1..1bb679c 100644 --- a/test/optional_test_swap.cpp +++ b/test/optional_test_swap.cpp @@ -23,6 +23,13 @@ #include "boost/core/lightweight_test.hpp" +#if __cplusplus < 201103L +#include +#define SWAP_EX_SPEC +#else +#include +#define SWAP_EX_SPEC noexcept +#endif using boost::optional; using boost::none; @@ -237,12 +244,14 @@ void swap(optional_swap_test::class_whose_default_ctor_should_be_used & x, optio template <> void swap(optional_swap_test::class_whose_default_ctor_should_not_be_used & x, optional_swap_test::class_whose_default_ctor_should_not_be_used & y) +SWAP_EX_SPEC { optional_swap_test::swap(x, y); } template <> void swap(optional_swap_test::class_without_default_ctor & x, optional_swap_test::class_without_default_ctor & y) +SWAP_EX_SPEC { optional_swap_test::swap(x, y); } From e24ab26874bfe850071a27dabf1951dfe576918f Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 12 Feb 2016 20:17:44 +0100 Subject: [PATCH 34/54] release notes sync from master --- doc/91_relnotes.qbk | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index 297a360..81449dc 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -1,7 +1,7 @@ [/ Boost.Optional - Copyright (c) 2015 Andrzej Krzemienski + Copyright (c) 2015, 2016 Andrzej Krzemienski Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -13,12 +13,16 @@ [heading Boost Release X.XX] -* Changed the implementation of `boost::none`: now it is a constant with internal linkage. This addresses [@https://svn.boost.org/trac/boost/ticket/11203 Trac #11203]. * Now `boost::optional` is specialized for reference parameters. This way the `sizeof` of optional reference is that of a pointer, and a number of bugs is avoided. +[heading Boost Release 1.60] + +* Changed the implementation of `boost::none` again. Now it is a const object with internal linkage (as any other tag). This fixes [@https://svn.boost.org/trac/boost/ticket/11203 Trac #11203]. + [heading Boost Release 1.59] * For C++03 compilers, added 0-argument overload for member function `emplace()`, and therewith removed the dependency on ``. +* Fixed [@https://svn.boost.org/trac/boost/ticket/11241 Trac #11241]. [heading Boost Release 1.58] From b5b8414c069a2c5f16cc1f9813d069c8b36e2c35 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 13 Feb 2016 00:46:41 +0100 Subject: [PATCH 35/54] Primary template optional<> does not handle references --- doc/html/boost_optional/relnotes.html | 39 +- doc/html/index.html | 2 +- include/boost/none_t.hpp | 2 +- .../detail/old_optional_implementation.hpp | 1059 +++++++++++++++++ .../detail/optional_aligned_storage.hpp | 54 + .../detail/optional_factory_support.hpp | 36 + .../detail/optional_reference_spec.hpp | 5 +- include/boost/optional/optional.hpp | 224 +--- include/boost/optional/optional_fwd.hpp | 1 + test/optional_test_swap.cpp | 6 +- 10 files changed, 1235 insertions(+), 193 deletions(-) create mode 100644 include/boost/optional/detail/old_optional_implementation.hpp create mode 100644 include/boost/optional/detail/optional_aligned_storage.hpp create mode 100644 include/boost/optional/detail/optional_factory_support.hpp diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html index bac08cc..fa36621 100644 --- a/doc/html/boost_optional/relnotes.html +++ b/doc/html/boost_optional/relnotes.html @@ -31,29 +31,38 @@ Boost Release X.XX -
    -
  • - Changed the implementation of boost::none: - now it is a constant with internal linkage. This addresses Trac - #11203. -
  • -
  • +
    • Now boost::optional is specialized for reference parameters. This way the sizeof of optional reference is that of a pointer, and a number of bugs is avoided. -
    • -
    +

- Boost - Release 1.59 + Boost + Release 1.60

  • - For C++03 compilers, added 0-argument overload for member function emplace(), - and therewith removed the dependency on <boost/utility/in_place_factory.hpp>. + Changed the implementation of boost::none + again. Now it is a const object with internal linkage (as any other tag). + This fixes Trac + #11203.

+ Boost + Release 1.59 +

+
    +
  • + For C++03 compilers, added 0-argument overload for member function emplace(), + and therewith removed the dependency on <boost/utility/in_place_factory.hpp>. +
  • +
  • + Fixed Trac #11241. +
  • +
+

+ Boost Release 1.58

@@ -89,7 +98,7 @@

- + Boost Release 1.57

@@ -99,7 +108,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 558d7e2..3939641 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -146,7 +146,7 @@ - +

Last revised: October 05, 2015 at 14:34:49 GMT

Last revised: February 12, 2016 at 21:19:23 GMT


diff --git a/include/boost/none_t.hpp b/include/boost/none_t.hpp index fa73654..a05d303 100644 --- a/include/boost/none_t.hpp +++ b/include/boost/none_t.hpp @@ -29,7 +29,7 @@ class none_t {}; struct none_t { struct init_tag{}; - explicit none_t(init_tag){} // to prevent default constructor + explicit none_t(init_tag){} // to disable default constructor }; #endif // old implementation workarounds diff --git a/include/boost/optional/detail/old_optional_implementation.hpp b/include/boost/optional/detail/old_optional_implementation.hpp new file mode 100644 index 0000000..f2e6718 --- /dev/null +++ b/include/boost/optional/detail/old_optional_implementation.hpp @@ -0,0 +1,1059 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// 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 +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the maintainer at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP +#define BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP + +#include +#include +#include +#include +#include + +namespace boost { + +namespace optional_detail { + + +template +struct types_when_isnt_ref +{ + typedef T const& reference_const_type ; + typedef T & reference_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef T && rval_reference_type ; + typedef T && reference_type_of_temporary_wrapper; +#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + // GCC 4.4 has support for an early draft of rvalue references. The conforming version below + // causes warnings about returning references to a temporary. + static T&& move(T&& r) { return r; } +#else + static rval_reference_type move(reference_type r) { return boost::move(r); } +#endif +#endif + typedef T const* pointer_const_type ; + typedef T * pointer_type ; + typedef T const& argument_type ; +} ; + +template +struct types_when_is_ref +{ + typedef BOOST_DEDUCED_TYPENAME remove_reference::type raw_type ; + + typedef raw_type& reference_const_type ; + typedef raw_type& reference_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef BOOST_DEDUCED_TYPENAME remove_const::type&& rval_reference_type ; + typedef raw_type& reference_type_of_temporary_wrapper; + static reference_type move(reference_type r) { return r; } +#endif + typedef raw_type* pointer_const_type ; + typedef raw_type* pointer_type ; + typedef raw_type& argument_type ; +} ; + +template +void prevent_binding_rvalue_ref_to_optional_lvalue_ref() +{ +#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES + BOOST_STATIC_ASSERT_MSG( + !boost::is_lvalue_reference::value || !boost::is_rvalue_reference::value, + "binding rvalue references to optional lvalue references is disallowed"); +#endif +} + +struct optional_tag {} ; + +template +class optional_base : public optional_tag +{ + private : + + typedef +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + BOOST_DEDUCED_TYPENAME +#endif + ::boost::detail::make_reference_content::type internal_type ; + + typedef aligned_storage storage_type ; + + typedef types_when_isnt_ref types_when_not_ref ; + typedef types_when_is_ref types_when_ref ; + + typedef optional_base this_type ; + + protected : + + typedef T value_type ; + + typedef mpl::true_ is_reference_tag ; + typedef mpl::false_ is_not_reference_tag ; + + typedef BOOST_DEDUCED_TYPENAME is_reference::type is_reference_predicate ; + + public: + typedef BOOST_DEDUCED_TYPENAME mpl::if_::type types ; + + protected: + typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ; + typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ; + typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; +#endif + typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ; + typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ; + typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ; + + // Creates an optional uninitialized. + // No-throw + optional_base() + : + m_initialized(false) {} + + // Creates an optional uninitialized. + // No-throw + optional_base ( none_t ) + : + m_initialized(false) {} + + // Creates an optional initialized with 'val'. + // Can throw if T::T(T const&) does + optional_base ( argument_type val ) + : + m_initialized(false) + { + construct(val); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // move-construct an optional initialized from an rvalue-ref to 'val'. + // Can throw if T::T(T&&) does + optional_base ( rval_reference_type val ) + : + m_initialized(false) + { + construct( boost::move(val) ); + } +#endif + + // Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional. + // Can throw if T::T(T const&) does + optional_base ( bool cond, argument_type val ) + : + m_initialized(false) + { + if ( cond ) + construct(val); + } + + // Creates a deep copy of another optional + // Can throw if T::T(T const&) does + optional_base ( optional_base const& rhs ) + : + m_initialized(false) + { + if ( rhs.is_initialized() ) + construct(rhs.get_impl()); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates a deep move of another optional + // Can throw if T::T(T&&) does + optional_base ( optional_base&& rhs ) + : + m_initialized(false) + { + if ( rhs.is_initialized() ) + construct( boost::move(rhs.get_impl()) ); + } +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + template + explicit optional_base ( Expr&& expr, PtrExpr const* tag ) + : + m_initialized(false) + { + construct(boost::forward(expr),tag); + } + +#else + // This is used for both converting and in-place constructions. + // Derived classes use the 'tag' to select the appropriate + // implementation (the correct 'construct()' overload) + template + explicit optional_base ( Expr const& expr, Expr const* tag ) + : + m_initialized(false) + { + construct(expr,tag); + } + +#endif + + + // No-throw (assuming T::~T() doesn't) + ~optional_base() { destroy() ; } + + // Assigns from another optional (deep-copies the rhs value) + void assign ( optional_base const& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value(rhs.get_impl(), is_reference_predicate() ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(rhs.get_impl()); + } + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from another optional (deep-moves the rhs value) + void assign ( optional_base&& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value(boost::move(rhs.get_impl()), is_reference_predicate() ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(boost::move(rhs.get_impl())); + } + } +#endif + + // Assigns from another _convertible_ optional (deep-copies the rhs value) + template + void assign ( optional const& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) +#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES + assign_value(rhs.get(), is_reference_predicate() ); +#else + assign_value(static_cast(rhs.get()), is_reference_predicate() ); +#endif + + else destroy(); + } + else + { + if ( rhs.is_initialized() ) +#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES + construct(rhs.get()); +#else + construct(static_cast(rhs.get())); +#endif + } + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // move-assigns from another _convertible_ optional (deep-moves from the rhs value) + template + void assign ( optional&& rhs ) + { + typedef BOOST_DEDUCED_TYPENAME optional::rval_reference_type ref_type; + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value(static_cast(rhs.get()), is_reference_predicate() ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(static_cast(rhs.get())); + } + } +#endif + + // Assigns from a T (deep-copies the rhs value) + void assign ( argument_type val ) + { + if (is_initialized()) + assign_value(val, is_reference_predicate() ); + else construct(val); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from a T (deep-moves the rhs value) + void assign ( rval_reference_type val ) + { + if (is_initialized()) + assign_value( boost::move(val), is_reference_predicate() ); + else construct( boost::move(val) ); + } +#endif + + // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + void assign ( none_t ) BOOST_NOEXCEPT { destroy(); } + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template + void assign_expr ( Expr&& expr, ExprPtr const* tag ) + { + if (is_initialized()) + assign_expr_to_initialized(boost::forward(expr),tag); + else construct(boost::forward(expr),tag); + } +#else + template + void assign_expr ( Expr const& expr, Expr const* tag ) + { + if (is_initialized()) + assign_expr_to_initialized(expr,tag); + else construct(expr,tag); + } +#endif + +#endif + + public : + + // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + void reset() BOOST_NOEXCEPT { destroy(); } + + // **DEPPRECATED** Replaces the current value -if any- with 'val' + void reset ( argument_type val ) { assign(val); } + + // Returns a pointer to the value if this is initialized, otherwise, + // returns NULL. + // No-throw + pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; } + pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; } + + bool is_initialized() const { return m_initialized ; } + + protected : + + void construct ( argument_type val ) + { + ::new (m_storage.address()) internal_type(val) ; + m_initialized = true ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + void construct ( rval_reference_type val ) + { + ::new (m_storage.address()) internal_type( types::move(val) ) ; + m_initialized = true ; + } +#endif + + +#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 emplace_assign ( Args&&... args ) + { + destroy(); + ::new (m_storage.address()) internal_type( boost::forward(args)... ); + m_initialized = true ; + } +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + template + void emplace_assign ( Arg&& arg ) + { + destroy(); + ::new (m_storage.address()) internal_type( boost::forward(arg) ); + m_initialized = true ; + } + + void emplace_assign () + { + destroy(); + ::new (m_storage.address()) internal_type(); + m_initialized = true ; + } +#else + template + void emplace_assign ( const Arg& arg ) + { + destroy(); + ::new (m_storage.address()) internal_type( arg ); + m_initialized = true ; + } + + template + void emplace_assign ( Arg& arg ) + { + destroy(); + ::new (m_storage.address()) internal_type( arg ); + m_initialized = true ; + } + + void emplace_assign () + { + destroy(); + ::new (m_storage.address()) internal_type(); + m_initialized = true ; + } +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Constructs in-place using the given factory + template + void construct ( Expr&& factory, in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ; + boost_optional_detail::construct(factory, m_storage.address()); + m_initialized = true ; + } + + // Constructs in-place using the given typed factory + template + void construct ( Expr&& factory, typed_in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ; + factory.apply(m_storage.address()) ; + m_initialized = true ; + } + + template + void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + + // Constructs in-place using the given typed factory + template + void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + +#else + // Constructs in-place using the given factory + template + void construct ( Expr const& factory, in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ; + boost_optional_detail::construct(factory, m_storage.address()); + m_initialized = true ; + } + + // Constructs in-place using the given typed factory + template + void construct ( Expr const& factory, typed_in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ; + factory.apply(m_storage.address()) ; + m_initialized = true ; + } + + template + void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + + // Constructs in-place using the given typed factory + template + void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } +#endif + +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Constructs using any expression implicitly convertible to the single argument + // of a one-argument T constructor. + // Converting constructions of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting constructor of T from U. + template + void construct ( Expr&& expr, void const* ) + { + new (m_storage.address()) internal_type(boost::forward(expr)) ; + m_initialized = true ; + } + + // Assigns using a form any expression implicitly convertible to the single argument + // of a T's assignment operator. + // Converting assignments of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting assignment of T from U. + template + void assign_expr_to_initialized ( Expr&& expr, void const* ) + { + assign_value(boost::forward(expr), is_reference_predicate()); + } +#else + // Constructs using any expression implicitly convertible to the single argument + // of a one-argument T constructor. + // Converting constructions of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting constructor of T from U. + template + void construct ( Expr const& expr, void const* ) + { + new (m_storage.address()) internal_type(expr) ; + m_initialized = true ; + } + + // Assigns using a form any expression implicitly convertible to the single argument + // of a T's assignment operator. + // Converting assignments of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting assignment of T from U. + template + void assign_expr_to_initialized ( Expr const& expr, void const* ) + { + assign_value(expr, is_reference_predicate()); + } + +#endif + +#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + // BCB5.64 (and probably lower versions) workaround. + // The in-place factories are supported by means of catch-all constructors + // and assignment operators (the functions are parameterized in terms of + // an arbitrary 'Expr' type) + // This compiler incorrectly resolves the overload set and sinks optional and optional + // to the 'Expr'-taking functions even though explicit overloads are present for them. + // Thus, the following overload is needed to properly handle the case when the 'lhs' + // is another optional. + // + // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error + // instead of choosing the wrong overload + // +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Notice that 'Expr' will be optional or optional (but not optional_base<..>) + template + void construct ( Expr&& expr, optional_tag const* ) + { + if ( expr.is_initialized() ) + { + // An exception can be thrown here. + // It it happens, THIS will be left uninitialized. + new (m_storage.address()) internal_type(types::move(expr.get())) ; + m_initialized = true ; + } + } +#else + // Notice that 'Expr' will be optional or optional (but not optional_base<..>) + template + void construct ( Expr const& expr, optional_tag const* ) + { + if ( expr.is_initialized() ) + { + // An exception can be thrown here. + // It it happens, THIS will be left uninitialized. + new (m_storage.address()) internal_type(expr.get()) ; + m_initialized = true ; + } + } +#endif +#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + + void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; } + void assign_value ( argument_type val, is_reference_tag ) { construct(val); } +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast(val); } + void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast(val) ); } +#endif + + void destroy() + { + if ( m_initialized ) + destroy_impl(is_reference_predicate()) ; + } + + reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; } + reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; } + + pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; } + pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; } + + private : + + // internal_type can be either T or reference_content +#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) + // This workaround is supposed to silence GCC warnings about broken strict aliasing rules + internal_type const* get_object() const + { + union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() }; + return caster.as_ptype; + } + internal_type * get_object() + { + union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() }; + return caster.as_ptype; + } +#else + internal_type const* get_object() const { return static_cast(m_storage.address()); } + internal_type * get_object() { return static_cast (m_storage.address()); } +#endif + + // reference_content lacks an implicit conversion to T&, so the following is needed to obtain a proper reference. + reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; } + reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; } + reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; } + reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) + void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; } +#else + void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; } +#endif + + void destroy_impl ( is_reference_tag ) { m_initialized = false ; } + + // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error. + // Decent compilers should disallow conversions from reference_content* to T*, but just in case, + // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference. + pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; } + pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; } + pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; } + pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; } + + bool m_initialized ; + storage_type m_storage ; +} ; + +} // namespace optional_detail + +template +class optional : public optional_detail::optional_base +{ + typedef optional_detail::optional_base base ; + + public : + + typedef optional this_type ; + + typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; +#endif + typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ; + typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ; + typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; + + // Creates an optional uninitialized. + // No-throw + optional() BOOST_NOEXCEPT : base() {} + + // Creates an optional uninitialized. + // No-throw + optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {} + + // Creates an optional initialized with 'val'. + // Can throw if T::T(T const&) does + optional ( argument_type val ) : base(val) {} + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates an optional initialized with 'move(val)'. + // Can throw if T::T(T &&) does + optional ( rval_reference_type val ) : base( boost::forward(val) ) + {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref();} +#endif + + // Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. + // Can throw if T::T(T const&) does + optional ( bool cond, argument_type val ) : base(cond,val) {} + + // NOTE: MSVC needs templated versions first + + // Creates a deep copy of another convertible optional + // Requires a valid conversion from U to T. + // Can throw if T::T(U const&) does + template + explicit optional ( optional const& rhs ) + : + base() + { + if ( rhs.is_initialized() ) + this->construct(rhs.get()); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates a deep move of another convertible optional + // Requires a valid conversion from U to T. + // Can throw if T::T(U&&) does + template + explicit optional ( optional && rhs ) + : + base() + { + if ( rhs.is_initialized() ) + this->construct( boost::move(rhs.get()) ); + } +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + // Creates an optional with an expression which can be either + // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n); + // (b) An instance of TypedInPlaceFactory ( i.e. in_place(a,b,...,n); + // (c) Any expression implicitly convertible to the single type + // of a one-argument T's constructor. + // (d*) Weak compilers (BCB) might also resolved Expr as optional and optional + // even though explicit overloads are present for these. + // Depending on the above some T ctor is called. + // Can throw if the resolved T ctor throws. +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + + template + explicit optional ( Expr&& expr, + BOOST_DEDUCED_TYPENAME boost::disable_if_c< + (boost::is_base_of::type>::value) || + boost::is_same::type, none_t>::value >::type* = 0 + ) + : base(boost::forward(expr),boost::addressof(expr)) + {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref();} + +#else + template + explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {} +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + + // Creates a deep copy of another optional + // Can throw if T::T(T const&) does + optional ( optional const& rhs ) : base( static_cast(rhs) ) {} + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates a deep move of another optional + // Can throw if T::T(T&&) does + optional ( optional && rhs ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value) + : base( boost::move(rhs) ) + {} + +#endif + // No-throw (assuming T::~T() doesn't) + ~optional() {} + +#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) + // Assigns from an expression. See corresponding constructor. + // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + template + BOOST_DEDUCED_TYPENAME boost::disable_if_c< + boost::is_base_of::type>::value || + boost::is_same::type, none_t>::value, + optional& + >::type + operator= ( Expr&& expr ) + { + optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref(); + this->assign_expr(boost::forward(expr),boost::addressof(expr)); + return *this ; + } + +#else + template + optional& operator= ( Expr const& expr ) + { + this->assign_expr(expr,boost::addressof(expr)); + return *this ; + } +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) + + // Copy-assigns from another convertible optional (converts && deep-copies the rhs value) + // Requires a valid conversion from U to T. + // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED + template + optional& operator= ( optional const& rhs ) + { + this->assign(rhs); + return *this ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Move-assigns from another convertible optional (converts && deep-moves the rhs value) + // Requires a valid conversion from U to T. + // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED + template + optional& operator= ( optional && rhs ) + { + this->assign(boost::move(rhs)); + return *this ; + } +#endif + + // Assigns from another optional (deep-copies the rhs value) + // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED + // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw) + optional& operator= ( optional const& rhs ) + { + this->assign( static_cast(rhs) ) ; + return *this ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from another optional (deep-moves the rhs value) + optional& operator= ( optional && rhs ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value) + { + this->assign( static_cast(rhs) ) ; + return *this ; + } +#endif + + // Assigns from a T (deep-copies the rhs value) + // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED + optional& operator= ( argument_type val ) + { + this->assign( val ) ; + return *this ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from a T (deep-moves the rhs value) + optional& operator= ( rval_reference_type val ) + { + optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref(); + this->assign( boost::move(val) ) ; + return *this ; + } +#endif + + // Assigns from a "none" + // Which destroys the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + optional& operator= ( none_t none_ ) BOOST_NOEXCEPT + { + this->assign( none_ ) ; + return *this ; + } + +#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 emplace ( Args&&... args ) + { + this->emplace_assign( boost::forward(args)... ); + } +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + template + void emplace ( Arg&& arg ) + { + this->emplace_assign( boost::forward(arg) ); + } + + void emplace () + { + this->emplace_assign(); + } +#else + template + void emplace ( const Arg& arg ) + { + this->emplace_assign( arg ); + } + + template + void emplace ( Arg& arg ) + { + this->emplace_assign( arg ); + } + + void emplace () + { + this->emplace_assign(); + } +#endif + + void swap( optional & arg ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value) + { + // allow for Koenig lookup + boost::swap(*this, arg); + } + + + // Returns a reference to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw + reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } + reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } + + // Returns a copy of the value if this is initialized, 'v' otherwise + reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; } + reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; } + + // Returns a pointer to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw + pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } + pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } + + // Returns a reference to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + reference_const_type operator *() const& { return this->get() ; } + reference_type operator *() & { return this->get() ; } + reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; } +#else + reference_const_type operator *() const { return this->get() ; } + reference_type operator *() { return this->get() ; } +#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS + +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + reference_const_type value() const& + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } + + reference_type value() & + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } + + reference_type_of_temporary_wrapper value() && + { + if (this->is_initialized()) + return base::types::move(this->get()) ; + else + throw_exception(bad_optional_access()); + } + +#else + reference_const_type value() const + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } + + reference_type value() + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } +#endif + + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + template + value_type value_or ( U&& v ) const& + { + if (this->is_initialized()) + return get(); + else + return boost::forward(v); + } + + template + value_type value_or ( U&& v ) && + { + if (this->is_initialized()) + return base::types::move(get()); + else + return boost::forward(v); + } +#elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template + value_type value_or ( U&& v ) const + { + if (this->is_initialized()) + return get(); + else + return boost::forward(v); + } +#else + template + value_type value_or ( U const& v ) const + { + if (this->is_initialized()) + return get(); + else + return v; + } + + template + value_type value_or ( U& v ) const + { + if (this->is_initialized()) + return get(); + else + return v; + } +#endif + + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + template + value_type value_or_eval ( F f ) const& + { + if (this->is_initialized()) + return get(); + else + return f(); + } + + template + value_type value_or_eval ( F f ) && + { + if (this->is_initialized()) + return base::types::move(get()); + else + return f(); + } +#else + template + value_type value_or_eval ( F f ) const + { + if (this->is_initialized()) + return get(); + else + return f(); + } +#endif + + bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() +} ; + +} // namespace boost + + +#endif // header guard diff --git a/include/boost/optional/detail/optional_aligned_storage.hpp b/include/boost/optional/detail/optional_aligned_storage.hpp new file mode 100644 index 0000000..c0ad272 --- /dev/null +++ b/include/boost/optional/detail/optional_aligned_storage.hpp @@ -0,0 +1,54 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2016 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_ALIGNED_STORAGE_AJK_12FEB2016_HPP +#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_ALIGNED_STORAGE_AJK_12FEB2016_HPP + +namespace boost { + +namespace optional_detail { +// This local class is used instead of that in "aligned_storage.hpp" +// because I've found the 'official' class to ICE BCB5.5 +// when some types are used with optional<> +// (due to sizeof() passed down as a non-type template parameter) +template +class aligned_storage +{ + // Borland ICEs if unnamed unions are used for this! + union + // This works around GCC warnings about breaking strict aliasing rules when casting storage address to T* +#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) + __attribute__((__may_alias__)) +#endif + dummy_u + { + char data[ sizeof(T) ]; + BOOST_DEDUCED_TYPENAME type_with_alignment< + ::boost::alignment_of::value >::type aligner_; + } dummy_ ; + + public: + +#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) + void const* address() const { return &dummy_; } + void * address() { return &dummy_; } +#else + void const* address() const { return dummy_.data; } + void * address() { return dummy_.data; } +#endif +} ; + +} // namespace optional_detail +} // namespace boost + +#endif // header guard diff --git a/include/boost/optional/detail/optional_factory_support.hpp b/include/boost/optional/detail/optional_factory_support.hpp new file mode 100644 index 0000000..efff92a --- /dev/null +++ b/include/boost/optional/detail/optional_factory_support.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2016 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_FACTORY_SUPPORT_AJK_12FEB2016_HPP +#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_FACTORY_SUPPORT_AJK_12FEB2016_HPP + +// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<> +// member template of a factory as used in the optional<> implementation. +// He proposed this simple fix which is to move the call to apply<> outside +// namespace boost. +namespace boost_optional_detail +{ + template + inline void construct(Factory const& factory, void* address) + { + factory.BOOST_NESTED_TEMPLATE apply(address); + } +} + +namespace boost +{ + class in_place_factory_base ; + class typed_in_place_factory_base ; +} + +#endif // header guard diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 79d1869..ecf9869 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Andrzej Krzemienski. +// Copyright (C) 2015-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 @@ -167,9 +167,8 @@ public: #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES }; -// TODO: what if no rvalue refs } // namespace boost -#endif // 0 +#endif // 1/0 #endif // header guard diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 9cdc7ea..d73bd62 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -39,163 +39,50 @@ #include #include #include -#include #include #include -#include -#include -#include -#include #include #include #include #include #include +#include +#include -// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<> -// member template of a factory as used in the optional<> implementation. -// He proposed this simple fix which is to move the call to apply<> outside -// namespace boost. -namespace boost_optional_detail -{ - template - inline void construct(Factory const& factory, void* address) - { - factory.BOOST_NESTED_TEMPLATE apply(address); - } -} - +#ifdef BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL +#include +#else namespace boost { -class in_place_factory_base ; -class typed_in_place_factory_base ; - -// This forward is needed to refer to namespace scope swap from the member swap -template void swap ( optional& x, optional& y ); - namespace optional_detail { -// This local class is used instead of that in "aligned_storage.hpp" -// because I've found the 'official' class to ICE BCB5.5 -// when some types are used with optional<> -// (due to sizeof() passed down as a non-type template parameter) -template -class aligned_storage -{ - // Borland ICEs if unnamed unions are used for this! - union - // This works around GCC warnings about breaking strict aliasing rules when casting storage address to T* -#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) - __attribute__((__may_alias__)) -#endif - dummy_u - { - char data[ sizeof(T) ]; - BOOST_DEDUCED_TYPENAME type_with_alignment< - ::boost::alignment_of::value >::type aligner_; - } dummy_ ; - - public: - -#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) - void const* address() const { return &dummy_; } - void * address() { return &dummy_; } -#else - void const* address() const { return dummy_.data; } - void * address() { return dummy_.data; } -#endif -} ; - -template -struct types_when_isnt_ref -{ - typedef T const& reference_const_type ; - typedef T & reference_type ; -#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES - typedef T && rval_reference_type ; - typedef T && reference_type_of_temporary_wrapper; -#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES - // GCC 4.4 has support for an early draft of rvalue references. The conforming version below - // causes warnings about returning references to a temporary. - static T&& move(T&& r) { return r; } -#else - static rval_reference_type move(reference_type r) { return boost::move(r); } -#endif -#endif - typedef T const* pointer_const_type ; - typedef T * pointer_type ; - typedef T const& argument_type ; -} ; - -template -struct types_when_is_ref -{ - typedef BOOST_DEDUCED_TYPENAME remove_reference::type raw_type ; - - typedef raw_type& reference_const_type ; - typedef raw_type& reference_type ; -#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES - typedef BOOST_DEDUCED_TYPENAME remove_const::type&& rval_reference_type ; - typedef raw_type& reference_type_of_temporary_wrapper; - static reference_type move(reference_type r) { return r; } -#endif - typedef raw_type* pointer_const_type ; - typedef raw_type* pointer_type ; - typedef raw_type& argument_type ; -} ; - -template -void prevent_binding_rvalue_ref_to_optional_lvalue_ref() -{ -#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES - BOOST_STATIC_ASSERT_MSG( - !boost::is_lvalue_reference::value || !boost::is_rvalue_reference::value, - "binding rvalue references to optional lvalue references is disallowed"); -#endif -} struct optional_tag {} ; + template class optional_base : public optional_tag { private : - typedef -#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - BOOST_DEDUCED_TYPENAME -#endif - ::boost::detail::make_reference_content::type internal_type ; - + typedef T internal_type ; typedef aligned_storage storage_type ; - - typedef types_when_isnt_ref types_when_not_ref ; - typedef types_when_is_ref types_when_ref ; - typedef optional_base this_type ; protected : typedef T value_type ; - typedef mpl::true_ is_reference_tag ; - typedef mpl::false_ is_not_reference_tag ; - - typedef BOOST_DEDUCED_TYPENAME is_reference::type is_reference_predicate ; - - public: - typedef BOOST_DEDUCED_TYPENAME mpl::if_::type types ; - protected: - typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ; - typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ; + typedef T & reference_type ; + typedef T const& reference_const_type ; #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES - typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ; - typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; + typedef T && rval_reference_type ; + typedef T && reference_type_of_temporary_wrapper ; #endif - typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ; - typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ; - typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ; + typedef T * pointer_type ; + typedef T const* pointer_const_type ; + typedef T const& argument_type ; // Creates an optional uninitialized. // No-throw @@ -295,7 +182,7 @@ class optional_base : public optional_tag if (is_initialized()) { if ( rhs.is_initialized() ) - assign_value(rhs.get_impl(), is_reference_predicate() ); + assign_value(rhs.get_impl()); else destroy(); } else @@ -312,7 +199,7 @@ class optional_base : public optional_tag if (is_initialized()) { if ( rhs.is_initialized() ) - assign_value(boost::move(rhs.get_impl()), is_reference_predicate() ); + assign_value( boost::move(rhs.get_impl()) ); else destroy(); } else @@ -331,9 +218,9 @@ class optional_base : public optional_tag { if ( rhs.is_initialized() ) #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES - assign_value(rhs.get(), is_reference_predicate() ); + assign_value( rhs.get() ); #else - assign_value(static_cast(rhs.get()), is_reference_predicate() ); + assign_value( static_cast(rhs.get()) ); #endif else destroy(); @@ -358,7 +245,7 @@ class optional_base : public optional_tag if (is_initialized()) { if ( rhs.is_initialized() ) - assign_value(static_cast(rhs.get()), is_reference_predicate() ); + assign_value( static_cast(rhs.get()) ); else destroy(); } else @@ -373,7 +260,7 @@ class optional_base : public optional_tag void assign ( argument_type val ) { if (is_initialized()) - assign_value(val, is_reference_predicate() ); + assign_value(val); else construct(val); } @@ -382,7 +269,7 @@ class optional_base : public optional_tag void assign ( rval_reference_type val ) { if (is_initialized()) - assign_value( boost::move(val), is_reference_predicate() ); + assign_value( boost::move(val) ); else construct( boost::move(val) ); } #endif @@ -441,7 +328,7 @@ class optional_base : public optional_tag #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES void construct ( rval_reference_type val ) { - ::new (m_storage.address()) internal_type( types::move(val) ) ; + ::new (m_storage.address()) internal_type( boost::move(val) ) ; m_initialized = true ; } #endif @@ -504,7 +391,6 @@ class optional_base : public optional_tag template void construct ( Expr&& factory, in_place_factory_base const* ) { - BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ; boost_optional_detail::construct(factory, m_storage.address()); m_initialized = true ; } @@ -513,7 +399,6 @@ class optional_base : public optional_tag template void construct ( Expr&& factory, typed_in_place_factory_base const* ) { - BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ; factory.apply(m_storage.address()) ; m_initialized = true ; } @@ -538,7 +423,6 @@ class optional_base : public optional_tag template void construct ( Expr const& factory, in_place_factory_base const* ) { - BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ; boost_optional_detail::construct(factory, m_storage.address()); m_initialized = true ; } @@ -547,7 +431,6 @@ class optional_base : public optional_tag template void construct ( Expr const& factory, typed_in_place_factory_base const* ) { - BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ; factory.apply(m_storage.address()) ; m_initialized = true ; } @@ -589,7 +472,7 @@ class optional_base : public optional_tag template void assign_expr_to_initialized ( Expr&& expr, void const* ) { - assign_value(boost::forward(expr), is_reference_predicate()); + assign_value( boost::forward(expr) ); } #else // Constructs using any expression implicitly convertible to the single argument @@ -610,7 +493,7 @@ class optional_base : public optional_tag template void assign_expr_to_initialized ( Expr const& expr, void const* ) { - assign_value(expr, is_reference_predicate()); + assign_value(expr); } #endif @@ -637,7 +520,7 @@ class optional_base : public optional_tag { // An exception can be thrown here. // It it happens, THIS will be left uninitialized. - new (m_storage.address()) internal_type(types::move(expr.get())) ; + new (m_storage.address()) internal_type(boost::move(expr.get())) ; m_initialized = true ; } } @@ -657,24 +540,22 @@ class optional_base : public optional_tag #endif #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION - void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; } - void assign_value ( argument_type val, is_reference_tag ) { construct(val); } + void assign_value ( argument_type val ) { get_impl() = val; } #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES - void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast(val); } - void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast(val) ); } + void assign_value ( rval_reference_type val ) { get_impl() = static_cast(val); } #endif void destroy() { if ( m_initialized ) - destroy_impl(is_reference_predicate()) ; + destroy_impl() ; } - reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; } - reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; } + reference_const_type get_impl() const { return dereference(get_object()) ; } + reference_type get_impl() { return dereference(get_object()) ; } - pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; } - pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; } + pointer_const_type get_ptr_impl() const { return cast_ptr(get_object()) ; } + pointer_type get_ptr_impl() { return cast_ptr(get_object()) ; } private : @@ -697,26 +578,21 @@ class optional_base : public optional_tag #endif // reference_content lacks an implicit conversion to T&, so the following is needed to obtain a proper reference. - reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; } - reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; } - reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; } - reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; } + reference_const_type dereference( internal_type const* p ) const { return *p ; } + reference_type dereference( internal_type* p ) { return *p ; } #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) - void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; } + void destroy_impl ( ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; } #else - void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; } + void destroy_impl ( ) { get_ptr_impl()->~T() ; m_initialized = false ; } #endif - void destroy_impl ( is_reference_tag ) { m_initialized = false ; } // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error. // Decent compilers should disallow conversions from reference_content* to T*, but just in case, // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference. - pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; } - pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; } - pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; } - pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; } + pointer_const_type cast_ptr( internal_type const* p ) const { return p ; } + pointer_type cast_ptr( internal_type * p ) { return p ; } bool m_initialized ; storage_type m_storage ; @@ -760,7 +636,7 @@ class optional : public optional_detail::optional_base // Creates an optional initialized with 'move(val)'. // Can throw if T::T(T &&) does optional ( rval_reference_type val ) : base( boost::forward(val) ) - {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref();} + {} #endif // Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. @@ -815,7 +691,7 @@ class optional : public optional_detail::optional_base boost::is_same::type, none_t>::value >::type* = 0 ) : base(boost::forward(expr),boost::addressof(expr)) - {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref();} + {} #else template @@ -852,7 +728,6 @@ class optional : public optional_detail::optional_base >::type operator= ( Expr&& expr ) { - optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref(); this->assign_expr(boost::forward(expr),boost::addressof(expr)); return *this ; } @@ -920,7 +795,6 @@ class optional : public optional_detail::optional_base // Assigns from a T (deep-moves the rhs value) optional& operator= ( rval_reference_type val ) { - optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref(); this->assign( boost::move(val) ) ; return *this ; } @@ -1003,7 +877,7 @@ class optional : public optional_detail::optional_base #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) reference_const_type operator *() const& { return this->get() ; } reference_type operator *() & { return this->get() ; } - reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; } + reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; } #else reference_const_type operator *() const { return this->get() ; } reference_type operator *() { return this->get() ; } @@ -1029,7 +903,7 @@ class optional : public optional_detail::optional_base reference_type_of_temporary_wrapper value() && { if (this->is_initialized()) - return base::types::move(this->get()) ; + return boost::move(this->get()) ; else throw_exception(bad_optional_access()); } @@ -1067,7 +941,7 @@ class optional : public optional_detail::optional_base value_type value_or ( U&& v ) && { if (this->is_initialized()) - return base::types::move(get()); + return boost::move(get()); else return boost::forward(v); } @@ -1115,7 +989,7 @@ class optional : public optional_detail::optional_base value_type value_or_eval ( F f ) && { if (this->is_initialized()) - return base::types::move(get()); + return boost::move(get()); else return f(); } @@ -1135,6 +1009,12 @@ class optional : public optional_detail::optional_base BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() } ; +} // namespace boost + +#endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL + +namespace boost { + #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template class optional @@ -1239,6 +1119,10 @@ get_pointer ( optional& opt ) return opt.get_ptr() ; } +} // namespace boost + +namespace boost { + // The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header. template std::basic_ostream& diff --git a/include/boost/optional/optional_fwd.hpp b/include/boost/optional/optional_fwd.hpp index fb59682..d5f9851 100644 --- a/include/boost/optional/optional_fwd.hpp +++ b/include/boost/optional/optional_fwd.hpp @@ -20,6 +20,7 @@ namespace boost { template class optional ; +// This forward is needed to refer to namespace scope swap from the member swap template void swap ( optional& , optional& ); template struct optional_swap_should_use_default_constructor ; diff --git a/test/optional_test_swap.cpp b/test/optional_test_swap.cpp index 1bb679c..757b616 100644 --- a/test/optional_test_swap.cpp +++ b/test/optional_test_swap.cpp @@ -209,13 +209,13 @@ namespace boost { // template <> struct optional_swap_should_use_default_constructor< - optional_swap_test::class_whose_default_ctor_should_be_used> : mpl::true_ {} ; + optional_swap_test::class_whose_default_ctor_should_be_used> : true_type {} ; template <> struct optional_swap_should_use_default_constructor< - optional_swap_test::class_whose_default_ctor_should_not_be_used> : mpl::false_ {} ; + optional_swap_test::class_whose_default_ctor_should_not_be_used> : false_type {} ; template struct optional_swap_should_use_default_constructor< - optional_swap_test::template_whose_default_ctor_should_be_used > : mpl::true_ {} ; + optional_swap_test::template_whose_default_ctor_should_be_used > : true_type {} ; // From 94c735af2dccbeb7969e216bb8d34f1eb6091e9b Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 13 Feb 2016 15:33:07 +0100 Subject: [PATCH 36/54] added optional ref swap and also chaned the copyright year in docs --- doc/00_optional.qbk | 2 +- doc/html/boost_optional/acknowledgements.html | 2 +- .../dependencies_and_portability.html | 2 +- .../optional_reference_binding.html | 2 +- doc/html/boost_optional/quick_start.html | 2 +- ...sing_unnecessary_default_construction.html | 2 +- .../optional_automatic_variables.html | 2 +- .../quick_start/optional_data_members.html | 2 +- .../quick_start/storage_in_containers.html | 2 +- ...ost_optional_bad_optional_access_hpp_.html | 2 +- .../detailed_semantics.html | 2 +- .../header__boost_optional_hpp_.html | 2 +- ...der__boost_optional_optional_fwd_hpp_.html | 2 +- .../detailed_semantics.html | 2 +- .../boost_optional/reference/io_header.html | 2 +- .../reference/io_header/io_semantics.html | 2 +- doc/html/boost_optional/relnotes.html | 2 +- .../tutorial/a_note_about_optional_bool_.html | 2 +- .../tutorial/design_overview.html | 2 +- .../design_overview/the_interface.html | 2 +- .../design_overview/the_semantics.html | 2 +- .../tutorial/exception_safety_guarantees.html | 2 +- .../tutorial/in_place_factories.html | 2 +- .../boost_optional/tutorial/io_operators.html | 2 +- .../tutorial/optional_references.html | 2 +- .../tutorial/performance_considerations.html | 2 +- ...for_assignment_of_optional_references.html | 2 +- .../tutorial/relational_operators.html | 2 +- .../tutorial/type_requirements.html | 2 +- .../tutorial/when_to_use_optional.html | 2 +- doc/html/index.html | 4 +- doc/html/optional/reference.html | 2 +- .../header__boost_optional_optional_hpp_.html | 2 +- doc/html/optional/tutorial.html | 2 +- include/boost/none_t.hpp | 1 - .../detail/optional_reference_spec.hpp | 6 + include/boost/optional/optional_fwd.hpp | 12 +- test/Jamfile.v2 | 1 + test/optional_test_ref_swap.cpp | 106 ++++++++++++++++++ 39 files changed, 159 insertions(+), 37 deletions(-) create mode 100644 test/optional_test_ref_swap.cpp diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk index d1a2275..14f4d4a 100644 --- a/doc/00_optional.qbk +++ b/doc/00_optional.qbk @@ -2,7 +2,7 @@ [quickbook 1.4] [authors [Cacciola Carballal, Fernando Luis]] [copyright 2003-2007 Fernando Luis Cacciola Carballal] - [copyright 2014-2015 Andrzej Krzemieński] + [copyright 2014-2016 Andrzej Krzemieński] [category miscellaneous] [id optional] [dirname optional] diff --git a/doc/html/boost_optional/acknowledgements.html b/doc/html/boost_optional/acknowledgements.html index d025d50..2cd116c 100644 --- a/doc/html/boost_optional/acknowledgements.html +++ b/doc/html/boost_optional/acknowledgements.html @@ -116,7 +116,7 @@ -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -146,7 +146,7 @@

- +

Last revised: February 12, 2016 at 21:19:23 GMT

Last revised: February 13, 2016 at 13:50:14 GMT


diff --git a/doc/html/optional/reference.html b/doc/html/optional/reference.html index 0cc575c..1c9b792 100644 --- a/doc/html/optional/reference.html +++ b/doc/html/optional/reference.html @@ -75,7 +75,7 @@ -
-
-

-PrevUpHomeNext +PrevUpHomeNext

@@ -41,7 +41,7 @@


-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics.html index 041b651..b7d25f5 100644 --- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics.html +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics.html @@ -6,8 +6,8 @@ - - + + @@ -20,7 +20,7 @@

-PrevUpHomeNext +PrevUpHomeNext

@@ -2368,6 +2368,44 @@

+

+ space +

+

+ void swap + ( optional<T&>& x, optional<T&>& y + ) noexcept + ; +

+
    +
  • + Postconditions: x + refers to what y refererred + to before the swap (if anything). y + refers to whatever x + referred to before the swap. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +
    +optional<T&> opt0;
    +optional<T&> optX (x);
    +optional<T&> optY (y);
    +
    +boost::swap(optX, optY);
    +assert (addressof(*optX) == addressof(y));
    +assert (addressof(*optY) == addressof(x));
    +
    +boost::swap(opt0, optX);
    +assert ( opt0 );
    +assert ( !optX );
    +assert (addressof(*opt0) == addressof(y));
    +
    + [endsect] +
  • +
@@ -2379,7 +2417,7 @@

-PrevUpHomeNext +PrevUpHomeNext
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 new file mode 100644 index 0000000..462f109 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____free_functions.html @@ -0,0 +1,447 @@ + + + +Detailed Semantics -- Free Functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ space +

+

+ optional<T> make_optional( + T const& v ) +

+
    +
  • + Returns: optional<T>(v) for the deduced + type T of v. +
  • +
  • + Example: +
    template<class T> void foo ( optional<T> const& opt ) ;
    +
    +foo ( make_optional(1+1) ) ; // Creates an optional<int>
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)> make_optional( bool condition, + T const& v ) +

+
    +
  • + Returns: optional<T>(condition,v) for the deduced + type T of v. +
  • +
  • + Example: +
    optional<double> calculate_foo()
    +{
    +  double val = compute_foo();
    +  return make_optional(is_not_nan_and_finite(val),val);
    +}
    +
    +optional<double> v = calculate_foo();
    +if ( !v )
    +  error("foo wasn't computed");
    +
    +
  • +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: T + shall meet requirements of EqualityComparable. +
  • +
  • + Returns: If both x + and y are initialized, + (*x + == *y). + If only x or y is initialized, false. + If both are uninitialized, true. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is compared unequal to any optional<T> containing any value, and equal + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator== directly in generic code which expect + to be given either an optional<T> or a pointer; use equal_pointees() + instead +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o1(T(1)), o1_(T(1));
    +optional<T> o2(T(2));
    +
    +assert ( oN == oN );  // Identity implies equality
    +assert ( o1 == o1 );  //
    +
    +assert ( oN == oN_ ); // Both uninitialized compare equal
    +
    +assert ( oN != o1 );  // Initialized unequal to initialized.
    +
    +assert ( o1 == o1_ ); // Both initialized compare as (*lhs == *rhs)
    +assert ( o1 != o2 );  //
    +
    +
  • +
+

+ space +

+

+ bool operator + < ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: Expression *x < *y shall be well-formed and its result + shall be convertible to bool. +
  • +
  • + Returns: (!y) ? false : (!x) ? true : *x < + *y. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is ordered as less than any optional<T> containing any value, and equivalent + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator< directly in generic code which + expect to be given either an optional<T> or a pointer; use less_pointees() + instead. T need not + be LessThanComparable. Only + single operator< + is required. Other relational operations are defined in terms of this + one. If T's operator< + satisfies the axioms of LessThanComparable (transitivity, + antisymmetry and irreflexivity), optinal<T> is LessThanComparable. +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o0(T(0));
    +optional<T> o1(T(1));
    +
    +assert ( !(oN < oN) );  // Identity implies equivalence
    +assert ( !(o1 < o1) );
    +
    +assert ( !(oN < oN_) ); // Two uninitialized are equivalent
    +assert ( !(oN_ < oN) );
    +
    +assert ( oN < o0 );     // Uninitialized is less than initialized
    +assert ( !(o0 < oN) );
    +
    +assert ( o1 < o2 ) ;    // Two initialized compare as (*lhs < *rhs)
    +assert ( !(o2 < o1) ) ;
    +assert ( !(o2 < o2) ) ;
    +
    +
  • +
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, optional<T> const& y ); +

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

+ space +

+

+ bool operator + > ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: ( + y < + x ); +
+

+ space +

+

+ bool operator + <= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + y < + x ); +
+

+ space +

+

+ bool operator + >= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + x < + y ); +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + == ( + none_t, + optional<T> const& x ) noexcept; +

+
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + != ( + none_t, + optional<T> const& x ) noexcept; +

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

+ space +

+

+ void swap + ( optional<T>& x, optional<T>& y + ) ; +

+
    +
  • + Requires: Lvalues of type T shall be swappable and T shall be MoveConstructible. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + calls swap(*(*this), *rhs) +

    +
    +

    + initializes the contained value of *this as if direct-initializing + an object of type T + with the expression std::move(*rhs), followed by rhs.val->T::~T(), + *this + contains a value and rhs + does not contain a value +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + initializes the contained value of rhs + as if direct-initializing an object of type T with the expression + std::move(*(*this)), + followed by val->T::~T(), *this does not contain a value + and rhs contains + a value +

    +
    +

    + no effect +

    +
    +
  • +
  • + Postconditions: The states of x and y + interchanged. +
  • +
  • + Throws: If both are initialized, whatever + swap(T&,T&) + throws. If only one is initialized, whatever T::T ( T&& ) + throws. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +optional<T> def0 ;
    +optional<T> def1 ;
    +optional<T> optX(x);
    +optional<T> optY(y);
    +
    +boost::swap(def0,def1); // no-op
    +
    +boost::swap(def0,optX);
    +assert ( *def0 == x );
    +assert ( !optX );
    +
    +boost::swap(def0,optX); // Get back to original values
    +
    +boost::swap(optX,optY);
    +assert ( *optX == y );
    +assert ( *optY == x );
    +
    +
  • +
+

+ space +

+

+ void swap + ( optional<T&>& x, optional<T&>& y + ) noexcept + ; +

+
    +
  • + Postconditions: x + refers to what y refererred + to before the swap (if anything). y + refers to whatever x + referred to before the swap. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +
    +optional<T&> opt0;
    +optional<T&> optX (x);
    +optional<T&> optY (y);
    +
    +boost::swap(optX, optY);
    +assert (addressof(*optX) == addressof(y));
    +assert (addressof(*optY) == addressof(x));
    +
    +boost::swap(opt0, optX);
    +assert ( opt0 );
    +assert ( !optX );
    +assert (addressof(*opt0) == addressof(y));
    +
    + [endsect] +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + 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 new file mode 100644 index 0000000..7eedfab --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_references.html @@ -0,0 +1,57 @@ + + + +Detailed Semantics -- Optional References + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ space +

+

+ optional<&>::optional() + noexcept; +

+

+ optional<&>::optional(none_t) noexcept; +

+
  • + Postconditions: *this refers to nothing. +
+
+ + + +
+
+
+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 new file mode 100644 index 0000000..5fd6391 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_values.html @@ -0,0 +1,1983 @@ + + + +Detailed Semantics -- Optional Values + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ + + + + +
[Note]Note

+ The following section contains various assert() which are used only to show the postconditions + as sample code. It is not implied that the type T + must support each particular expression but that if the expression is + supported, the implied condition holds. +

+

+ space +

+

+ optional<T>::optional() + noexcept; +

+
    +
  • + Effect: Default-Constructs an optional. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's default constructor is not called. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( !def ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + none_t ) + noexcept; +

+
    +
  • + Effect: Constructs an optional uninitialized. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's + default constructor is not called. + The expression boost::none + denotes an instance of boost::none_t + that can be used as the parameter. +
  • +
  • + Example: +
    #include <boost/none.hpp>
    +optional<T> n(none) ;
    +assert ( !n ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( T const& v ) +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is a copy of v. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: T::T( T const& + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + T& + ref ) +

+
    +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is an instance of an internal type wrapping the reference + ref. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v;
    +T& vref = v ;
    +optional<T&> opt(vref);
    +assert ( *opt == v ) ;
    +++ v ; // mutate referee
    +assert (*opt == v);
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( T&& v + ) +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Move-Constructs an + optional. +
  • +
  • + Postconditions: *this is initialized + and its value is move-constructed from v. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Notes: T::T( T&& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, the state of v + is determined by exception safety guarantees for T::T(T&&). +
  • +
  • + Example: +
    T v1, v2;
    +optional<T> opt(std::move(v1));
    +assert ( *opt == v2 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + T&& + ref ) + = delete +

+
  • + Notes: This constructor is deleted +
+

+ space +

+

+ optional<T (not a ref)>::optional( bool condition, + T const& v ) ; +

+

+ optional<T&> + ::optional( bool condition, + T& + v ) + ; +

+
  • + If condition is true, same as: +
+

+ optional<T (not a ref)>::optional( T const& v ) +

+

+ optional<T&> + ::optional( T& v ) +

+
  • + otherwise, same as: +
+

+ optional<T (not a ref)>::optional() +

+

+ optional<T&> + ::optional() +

+

+ space +

+

+ optional<T (not a ref)>::optional( optional + const& + rhs ); +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs is initialized, + *this + is initialized and its value is a copy of the + value of rhs; else + *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: If rhs is initialized, T::T(T const& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<T> uninit ;
    +assert (!uninit);
    +
    +optional<T> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<T> init( T(2) );
    +assert ( *init == T(2) ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( init2 == init ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + optional const& rhs + ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is another reference to the same object + referenced by *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: If rhs + is initialized, both *this and *rhs will refer to the same object + (they alias). +
  • +
  • + Example: +
    optional<T&> uninit ;
    +assert (!uninit);
    +
    +optional<T&> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +T v = 2 ; T& ref = v ;
    +optional<T> init(ref);
    +assert ( *init == v ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( *init2 == v ) ;
    +
    +v = 3 ;
    +
    +assert ( *init  == 3 ) ;
    +assert ( *init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move constructed from rhs; else *this is uninitialized. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value. +
  • +
  • + Notes: If rhs + is initialized, T::T( T && + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + of T::T(T&&). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<std::unique_ptr<T>> init( std::uniqye_ptr<T>(new T(2)) );
    +assert ( **init == T(2) ) ;
    +
    +optional<std::unique_ptr<T>> init2 ( std::move(init) ) ;
    +assert ( init );
    +assert ( *init == nullptr );
    +assert ( init2 );
    +assert ( **init2 == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + optional && + rhs ); +

+
    +
  • + Effect: Move-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is another reference to the same object + referenced by *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: If rhs + is initialized, both *this and *rhs will refer to the same object + (they alias). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>&> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>&> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +std::unique_ptr<T> v(new T(2)) ;
    +optional<std::unique_ptr<T>&> init(v);
    +assert ( *init == v ) ;
    +
    +optional<std::unique_ptr<T>&> init2 ( std::move(init) ) ;
    +assert ( *init2 == v ) ;
    +
    +*v = 3 ;
    +
    +assert ( **init  == 3 ) ;
    +assert ( **init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T + (not a ref)>::optional( + optional<U> const& rhs ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is a copy of the + value of rhs converted to type T; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U const& + ) throws. +
  • +
  • + Notes: T::T( U const& + ) is called if rhs is initialized, which requires + a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(x) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T + (not a ref)>::optional( + optional<U>&& + rhs ); +

+
    +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move-constructed from *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U&& ) + throws. +
  • +
  • + Notes: T::T( U&& ) + is called if rhs is + initialized, which requires a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + guarantee of T::T( U&& + ). +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(std::move(x)) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + explicit optional<T + (not a ref)>::optional( + InPlaceFactory const& f ); +

+

+ template<TypedInPlaceFactory> + explicit optional<T + (not a ref)>::optional( + TypedInPlaceFactory const& f ); +

+
    +
  • + Effect: Constructs an optional with a value of T obtained from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, this constructor has + no effect. +
  • +
  • + Example: +
    class C { C ( char, double, std::string ) ; } ;
    +
    +C v('A',123.4,"hello");
    +
    +optional<C> x( in_place   ('A', 123.4, "hello") ); // InPlaceFactory used
    +optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used
    +
    +assert ( *x == v ) ;
    +assert ( *y == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( none_t + ) noexcept; +

+
    +
  • + Effect: If *this is initialized destroys its contained + value. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( T + const& + rhs ) + ; +

+
    +
  • + Effect: Assigns the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + a copy of rhs. +
  • +
  • + Throws: Whatever T::operator=( T const& + ) or T::T(T const&) + throws. +
  • +
  • + Notes: If *this was initialized, T's assignment operator is used, + otherwise, its copy-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + copy constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y;
    +def = y ;
    +assert ( *def == y ) ;
    +opt = y ;
    +assert ( *opt == y ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>& + optional<T&>::operator= ( T& rhs + ) ; +

+
    +
  • + Effect: (Re)binds the wrapped reference. +
  • +
  • + Postconditions: *this is initialized and it references + the same object referenced by rhs. +
  • +
  • + Notes: If *this was initialized, it is rebound + to the new object. See here + for details on this behavior. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> opt(ra) ;
    +
    +def = rb ; // binds 'def' to 'b' through 'rb'
    +assert ( *def == b ) ;
    +*def = a ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +opt = rc ; // REBINDS to 'c' through 'rc'
    +c = 4 ;
    +assert ( *opt == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( T&& rhs + ) ; +

+
    +
  • + Effect: Moves the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + moved from rhs. +
  • +
  • + Throws: Whatever T::operator=( T&& ) + or T::T(T &&) + throws. +
  • +
  • + Notes: If *this was initialized, T's move-assignment operator is used, + otherwise, its move-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + move constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y1, y2, yR;
    +def = std::move(y1) ;
    +assert ( *def == yR ) ;
    +opt = std::move(y2) ;
    +assert ( *opt == yR ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>& + optional<T&>::operator= ( T&& rhs + ) = + delete; +

+
  • + Notes: This assignment operator is + deleted. +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( optional + const& + rhs ) + ; +

+
    +
  • + Requires: T + is CopyConstructible and CopyAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's copy constructor, no effect. + If an exception is thrown during the call to T's + copy assignment, the state of its contained value is as defined by + the exception safety guarantee of T's + copy assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( !def ) ;
    +// previous value (copy of 'v') destroyed from within 'opt'.
    +
    +
  • +
+

+ space +

+

+ optional<T&> + & optional<T&>::operator= ( optional<T&> const& rhs + ) ; +

+
    +
  • + Effect: (Re)binds thee wrapped reference. +
  • +
  • + Postconditions: If *rhs is initialized, *this + is initialized and it references the same object referenced by *rhs; + otherwise, *this + is uninitialized (and references no object). +
  • +
  • + Notes: If *this was initialized and so is *rhs, + *this + is rebound to the new object. See here + for details on this behavior. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> ora(ra) ;
    +optional<int&> orb(rb) ;
    +
    +def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb'
    +assert ( *def == b ) ;
    +*def = ora ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +optional<int&> orc(rc) ;
    +ora = orc ; // REBINDS ora to 'c' through 'rc'
    +c = 4 ;
    +assert ( *ora == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Requires: T + is MoveConstructible + and MoveAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value && + is_nothrow_move_assignable<T>::value. +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's move constructor, the state of + *rhs + is determined by the exception safety guarantee of T's + move constructor. If an exception is thrown during the call to T's + move-assignment, the state of **this and *rhs is determined by the exception + safety guarantee of T's move assignment. +
  • +
  • + Example: +
    optional<T> opt(T(2)) ;
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( def ) ;
    +assert ( opt ) ;
    +assert ( *opt == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&> + & optional<T&>::operator= ( optional<T&>&& rhs + ) ; +

+
  • + Effect: Same as optional<T&>::operator= ( optional<T&> + const& + rhs ). +
+

+ space +

+

+ template<U> optional& + optional<T (not a ref)>::operator= ( optional<U> const& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = opt0 ;
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> optional& + optional<T (not a ref)>::operator= ( optional<U>&& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = std::move(opt0) ;
    +assert ( opt0 );
    +assert ( opt1 )
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

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

+
    +
  • + Requires: The compiler supports rvalue + references and variadic templates. +
  • +
  • + Effect: If *this is initialized calls *this = none. + Then initializes in-place the contained value as if direct-initializing + an object of type T + with std::forward<Args>(args).... +
  • +
  • + 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 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. +
  • +
  • + Example: +
    T v;
    +optional<const T> opt;
    +opt.emplace(0);  // create in-place using ctor T(int)
    +opt.emplace();   // destroy previous and default-construct another T
    +opt.emplace(v);  // destroy and copy-construct in-place (no assignment called)
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + optional<T>& + optional<T (not a ref)>::operator=( InPlaceFactory + const& + f ); +

+

+ template<TypedInPlaceFactory> + optional<T>& + optional<T (not a ref)>::operator=( TypedInPlaceFactory + const& + f ); +

+
    +
  • + Effect: Assigns an optional + with a value of T obtained + from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, the optional + object will be reset to be uninitialized. +
  • +
+

+ space +

+

+ void optional<T + (not a ref)>::reset( T const& v ) ; +

+
  • + Deprecated: same as operator= + ( T + const& + v) + ; +
+

+ space +

+

+ void optional<T>::reset() noexcept + ; +

+
  • + Deprecated: Same as operator=( + none_t ); +
+

+ space +

+

+ T const& optional<T + (not a ref)>::get() const ; +

+

+ T& + optional<T (not a ref)>::get() ; +

+

+ inline T + const& + get ( + optional<T (not a ref)> const& ) ; +

+

+ inline T& get + ( optional<T + (not a ref)> + &) ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T&>::get() const ; +

+

+ T& + optional<T&>::get() ; +

+

+ inline T + const& + get ( + optional<T&> + const& + ) ; +

+

+ inline T& get + ( optional<T&> &) + ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: The + reference contained. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T + (not a ref)>::operator*() + const& + ; +

+

+ T& + optional<T (not a ref)>::operator*() &; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + these two overloads are replaced with the classical two: a const and non-const + member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> opt ( v );
    +T const& u = *opt;
    +assert ( u == v ) ;
    +T w ;
    +*opt = w ;
    +assert ( *opt == w ) ;
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T (not a ref)>::operator*() &&; +

+
    +
  • + Requires: *this contains a value. +
  • +
  • + Effects: Equivalent to return std::move(*val);. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + this overload is not present. +
  • +
+

+ space +

+

+ T & + optional<T&>::operator*() + const& + ; +

+

+ T & + optional<T&>::operator*() + & ; +

+

+ T & + optional<T&>::operator*() + && ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: The + reference contained. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + these three overloads are replaced with the classical two: a const and non-const + member functions. +
  • +
  • + Example: +
    T v ;
    +T& vref = v ;
    +optional<T&> opt ( vref );
    +T const& vref2 = *opt;
    +assert ( vref2 == v ) ;
    +++ v ;
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ T const& optional<T>::value() const& ; +

+

+ T& + optional<T>::value() & ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? *val : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions these two overloads are replaced + with the classical two: a const + and non-const member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> o0, o1 ( v );
    +assert ( o1.value() == v );
    +
    +try {
    +  o0.value(); // throws
    +  assert ( false );
    +}
    +catch(bad_optional_access&) {
    +  assert ( true );
    +}
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T>::value() && ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? std::move(*val) : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + const& + ; +

+
    +
  • + Effects: Equivalent to if (*this) return **this; else return + std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not CopyConstructible or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. On compilers without rvalue reference support the type of + v becomes U const&. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + && ; +

+
    +
  • + Effects: Equivalent to if (*this) return std::move(**this); else return std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not MoveConstructible + or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) const& ; +

+
    +
  • + Requires: T + is CopyConstructible and F models a Generator whose result type + is convertible to T. +
  • +
  • + Effects: if + (*this) return **this; else return f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. +
  • +
  • + Example: +
    int complain_and_0()
    +{
    +  clog << "no value returned, using default" << endl;
    +  return 0;
    +}
    +
    +optional<int> o1 = 1;
    +optional<int> oN = none;
    +
    +int i = o1.value_or_eval(complain_and_0); // fun not called
    +assert (i == 1);
    +
    +int j = oN.value_or_eval(complain_and_0); // fun called
    +assert (i == 0);
    +
    +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) && + ; +

+
    +
  • + Requires: T + is MoveConstructible + and F models a Generator + whose result type is convertible to T. +
  • +
  • + Effects: if + (*this) return std::move(**this); else return + f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ T const& optional<T + (not a ref)>::get_value_or( + T const& default) const ; +

+

+ T& + optional<T (not a ref)>::get_value_or( T& default + ) ; +

+

+ inline T + const& + get_optional_value_or ( + optional<T (not a ref)> const& o, T const& default ) ; +

+

+ inline T& get_optional_value_or + ( optional<T + (not a ref)>& + o, + T& + default ) + ; +

+
    +
  • + Deprecated: Use value_or() instead. +
  • +
  • + Returns: A reference to the contained + value, if any, or default. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v, z ;
    +optional<T> def;
    +T const& y = def.get_value_or(z);
    +assert ( y == z ) ;
    +
    +optional<T> opt ( v );
    +T const& u = get_optional_value_or(opt,z);
    +assert ( u == v ) ;
    +assert ( u != z ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T + (not a ref)>::get_ptr() + const ; +

+

+ T* + optional<T (not a ref)>::get_ptr() ; +

+

+ inline T + const* + get_pointer ( + optional<T (not a ref)> const& ) ; +

+

+ inline T* get_pointer + ( optional<T + (not a ref)> + &) ; +

+
    +
  • + Returns: If *this is initialized, a pointer to the + contained value; else 0 + (null). +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The contained value is permanently + stored within *this, + so you should not hold nor delete this pointer +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> const copt(v);
    +T* p = opt.get_ptr() ;
    +T const* cp = copt.get_ptr();
    +assert ( p == get_pointer(opt) );
    +assert ( cp == get_pointer(copt) ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T + (not a ref)>::operator ->() + const ; +

+

+ T* + optional<T (not a ref)>::operator + ->() ; +

+
    +
  • + Requires: *this is initialized. +
  • +
  • + Returns: A pointer to the contained + value. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
  • + Example: +
    struct X { int mdata ; } ;
    +X x ;
    +optional<X> opt (x);
    +opt->mdata = 2 ;
    +
    +
  • +
+

+ space +

+

+ explicit optional<T>::operator + bool() + const noexcept + ; +

+
    +
  • + Returns: get_ptr() != 0. +
  • +
  • + Notes: On compilers that do not support + explicit conversion operators this falls back to safe-bool idiom. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( def == 0 );
    +optional<T> opt ( v ) ;
    +assert ( opt );
    +assert ( opt != 0 );
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::operator!() noexcept + ; +

+
    +
  • + Returns: If *this is uninitialized, true; else false. +
  • +
  • + Notes: This operator is provided for + those compilers which can't use the unspecified-bool-type + operator in certain boolean contexts. +
  • +
  • + Example: +
    optional<T> opt ;
    +assert ( !opt );
    +*opt = some_T ;
    +
    +// Notice the "double-bang" idiom here.
    +assert ( !!opt ) ;
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::is_initialized() const ; +

+
  • + Deprecated: Same as explicit operator + bool () + ; +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + 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 new file mode 100644 index 0000000..f786277 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html @@ -0,0 +1,497 @@ + + + +Detailed Semantics - Free Functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ space +

+

+ optional<T> make_optional( + T const& v ) +

+
    +
  • + Returns: optional<T>(v) for the deduced + type T of v. +
  • +
  • + Example: +
    template<class T> void foo ( optional<T> const& opt ) ;
    +
    +foo ( make_optional(1+1) ) ; // Creates an optional<int>
    +
    +
  • +
+

+ space +

+

+ optional<T> make_optional( + bool condition, T const& v ) +

+
    +
  • + Returns: optional<T>(condition, v) for the deduced + type T of v. +
  • +
  • + Example: +
    optional<double> calculate_foo()
    +{
    +  double val = compute_foo();
    +  return make_optional(is_not_nan_and_finite(val),val);
    +}
    +
    +optional<double> v = calculate_foo();
    +if ( !v )
    +  error("foo wasn't computed");
    +
    +
  • +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: T + shall meet requirements of EqualityComparable. +
  • +
  • + Returns: If both x + and y are initialized, + (*x + == *y). + If only x or y is initialized, false. + If both are uninitialized, true. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is compared unequal to any optional<T> containing any value, and equal + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator== directly in generic code which expect + to be given either an optional<T> or a pointer; use equal_pointees() + instead +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o1(T(1)), o1_(T(1));
    +optional<T> o2(T(2));
    +
    +assert ( oN == oN );  // Identity implies equality
    +assert ( o1 == o1 );  //
    +
    +assert ( oN == oN_ ); // Both uninitialized compare equal
    +
    +assert ( oN != o1 );  // Initialized unequal to initialized.
    +
    +assert ( o1 == o1_ ); // Both initialized compare as (*lhs == *rhs)
    +assert ( o1 != o2 );  //
    +
    +
  • +
+

+ space +

+

+ bool operator + < ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: Expression *x < *y shall be well-formed and its result + shall be convertible to bool. +
  • +
  • + Returns: (!y) ? false : (!x) ? true : *x < + *y. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is ordered as less than any optional<T> containing any value, and equivalent + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator< directly in generic code which + expect to be given either an optional<T> or a pointer; use less_pointees() + instead. T need not + be LessThanComparable. Only + single operator< + is required. Other relational operations are defined in terms of this + one. If T's operator< + satisfies the axioms of LessThanComparable (transitivity, + antisymmetry and irreflexivity), optinal<T> is LessThanComparable. +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o0(T(0));
    +optional<T> o1(T(1));
    +
    +assert ( !(oN < oN) );  // Identity implies equivalence
    +assert ( !(o1 < o1) );
    +
    +assert ( !(oN < oN_) ); // Two uninitialized are equivalent
    +assert ( !(oN_ < oN) );
    +
    +assert ( oN < o0 );     // Uninitialized is less than initialized
    +assert ( !(o0 < oN) );
    +
    +assert ( o1 < o2 ) ;    // Two initialized compare as (*lhs < *rhs)
    +assert ( !(o2 < o1) ) ;
    +assert ( !(o2 < o2) ) ;
    +
    +
  • +
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, optional<T> const& y ); +

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

+ space +

+

+ bool operator + > ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: ( + y < + x ); +
+

+ space +

+

+ bool operator + <= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + y < + x ); +
+

+ space +

+

+ bool operator + >= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + x < + y ); +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + == ( + none_t, + optional<T> const& x ) noexcept; +

+
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + != ( + none_t, + optional<T> const& x ) noexcept; +

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

+ space +

+

+ auto get_pointer + ( optional<T>& o + ) -> + typename optional<T>::pointer_type + ; +

+

+ auto get_pointer + ( optional<T> const& o ) -> typename optional<T>::pointer_const_type + ; +

+
    +
  • + Returns: o.get_ptr(). +
  • +
  • + Throws: Nothing. +
  • +
+

+ space +

+

+ auto get_optional_value_or + ( optional<T>& o, typename optional<T>::reference_type def + ) -> + typename optional<T>::reference_type + ; +

+

+ auto get_optional_value_or + ( optional<T> const& o, typename optional<T>::reference_const_type def + ) -> + typename optional<T>::reference_const_type + ; +

+
    +
  • + Returns: o.get_value_or(def). +
  • +
  • + Throws: Nothing. +
  • +
  • + Remarks: This function is deprecated. +
  • +
+

+ space +

+

+ void swap + ( optional<T>& x, optional<T>& y + ) ; +

+
    +
  • + Requires: Lvalues of type T shall be swappable and T shall be MoveConstructible. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + calls swap(*(*this), *rhs) +

    +
    +

    + initializes the contained value of *this as if direct-initializing + an object of type T + with the expression std::move(*rhs), followed by rhs.val->T::~T(), + *this + contains a value and rhs + does not contain a value +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + initializes the contained value of rhs + as if direct-initializing an object of type T with the expression + std::move(*(*this)), + followed by val->T::~T(), *this does not contain a value + and rhs contains + a value +

    +
    +

    + no effect +

    +
    +
  • +
  • + Postconditions: The states of x and y + interchanged. +
  • +
  • + Throws: If both are initialized, whatever + swap(T&,T&) + throws. If only one is initialized, whatever T::T ( T&& ) + throws. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +optional<T> def0 ;
    +optional<T> def1 ;
    +optional<T> optX(x);
    +optional<T> optY(y);
    +
    +boost::swap(def0,def1); // no-op
    +
    +boost::swap(def0,optX);
    +assert ( *def0 == x );
    +assert ( !optX );
    +
    +boost::swap(def0,optX); // Get back to original values
    +
    +boost::swap(optX,optY);
    +assert ( *optX == y );
    +assert ( *optY == x );
    +
    +
  • +
+

+ space +

+

+ void swap + ( optional<T&>& x, optional<T&>& y + ) noexcept + ; +

+
    +
  • + Postconditions: x + refers to what y refererred + to before the swap (if anything). y + refers to whatever x + referred to before the swap. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +
    +optional<T&> opt0;
    +optional<T&> optX (x);
    +optional<T&> optY (y);
    +
    +boost::swap(optX, optY);
    +assert (addressof(*optX) == addressof(y));
    +assert (addressof(*optY) == addressof(x));
    +
    +boost::swap(opt0, optX);
    +assert ( opt0 );
    +assert ( !optX );
    +assert (addressof(*opt0) == addressof(y));
    +
    +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + 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 new file mode 100644 index 0000000..05e3e21 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html @@ -0,0 +1,509 @@ + + + +Detailed Semantics - Optional References + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ space +

+

+ optional<T&>::optional() + noexcept; +

+

+ optional<T&>::optional(none_t) noexcept; +

+
  • + Postconditions: bool(*this) == false; *this refers to nothing. +
+

+ space +

+

+ template<class R> optional<T&>::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<R> is an instance of boost::optional. +
  • +
  • + Example: +
    T v;
    +T& vref = v ;
    +optional<T&> opt(vref);
    +assert ( *opt == v ) ;
    +++ v ; // mutate referee
    +assert (*opt == v);
    +
    +
  • +
+

+ space +

+

+ template<class R> optional<T&>::optional(bool cond, R&& + r) + noexcept; +

+
    +
  • + Effects: Initializes ref with expression cond ? + addressof(r) : nullptr. +
  • +
  • + Postconditions: bool(*this) == cond; If bool(*this), 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<R> is an instance of boost::optional. +
  • +
+

+ space +

+

+ optional<T&>::optional ( + optional const& rhs + ) noexcept + ; +

+
    +
  • + Effects: Initializes ref with expression rhs.ref. +
  • +
  • + Postconditions: bool(*this) == bool(rhs). +
  • +
  • + Example: +
    optional<T&> uninit ;
    +assert (!uninit);
    +
    +optional<T&> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +T v = 2 ; T& ref = v ;
    +optional<T> init(ref);
    +assert ( *init == v ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( *init2 == v ) ;
    +
    +v = 3 ;
    +
    +assert ( *init  == 3 ) ;
    +assert ( *init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ template<class U> explicit + optional<T&>::optional ( + optional<U&> + const& + rhs ) + noexcept ; +

+
    +
  • + Requires: is_convertible<U&, T&>::value + is true. +
  • +
  • + Effects: Initializes ref with expression rhs.ref. +
  • +
  • + Postconditions: bool(*this) == bool(rhs). +
  • +
+

+ space +

+

+ optional<T&>::operator= ( none_t + ) noexcept + ; +

+
    +
  • + Effects: Assigns ref + with expression nullptr. +
  • +
  • + returns: *this. +
  • +
  • + Postconditions: bool(*this) == false. +
  • +
+

+ optional& + optional<T&>::operator= ( optional + const& + rhs ) + noexcept ; +

+
    +
  • + Effects: Assigns ref + with expression rhs.ref. +
  • +
  • + returns: *this. +
  • +
  • + Postconditions: bool(*this) == bool(rhs). +
  • +
  • + Notes: This behaviour is called rebinding + semantics. See here + for details. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> ora(ra) ;
    +optional<int&> orb(rb) ;
    +
    +def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb'
    +assert ( *def == b ) ;
    +*def = ora ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +optional<int&> orc(rc) ;
    +ora = orc ; // REBINDS ora to 'c' through 'rc'
    +c = 4 ;
    +assert ( *ora == 4 ) ;
    +
    +
  • +
+

+ template<class U> optional& optional<T&>::operator= ( optional<U&> const& rhs + ) noexcept + ; +

+
    +
  • + Requires: is_convertible<U&, T&>::value + is true. +
  • +
  • + Effects: Assigns ref + with expression rhs.ref. +
  • +
  • + returns: *this. +
  • +
  • + Postconditions: bool(*this) == bool(rhs). +
  • +
+

+ space +

+

+ template<class R> optional& optional<T&>::operator= ( R&& r + ) noexcept + ; +

+
    +
  • + Effects: Assigns ref + with expression r. +
  • +
  • + returns: *this. +
  • +
  • + Postconditions: bool(*this) == true. +
  • +
  • + Remarks: Unless R + is an lvalue reference, the program is ill-formed. This function does + not participate in overload resolution if decay<R> is an instance of boost::optional. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> opt(ra) ;
    +
    +def = rb ; // binds 'def' to 'b' through 'rb'
    +assert ( *def == b ) ;
    +*def = a ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +opt = rc ; // REBINDS to 'c' through 'rc'
    +c = 4 ;
    +assert ( *opt == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ void optional<T&>::emplace( R&& r + ) noexcept + ; +

+
    +
  • + Effects: Assigns ref + with expression r. +
  • +
  • + Postconditions: bool(*this) == true. +
  • +
  • + Remarks: Unless R + is an lvalue reference, the program is ill-formed. This function does + not participate in overload resolution if decay<R> is an instance of boost::optional. +
  • +
+

+ space +

+

+ T& + optional<T&>::get() const ; +

+

+ T& + optional<T&>::operator *() + const ; +

+
    +
  • + Requires: bool(*this) == true. +
  • +
  • + Effects: Returns *ref. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v ;
    +T& vref = v ;
    +optional<T&> opt ( vref );
    +T const& vref2 = *opt;
    +assert ( vref2 == v ) ;
    +++ v ;
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ T* + optional<T&>::operator -> + () const + ; +

+
    +
  • + Requires: bool(*this) == true. +
  • +
  • + Effects: Returns ref. +
  • +
  • + Throws: Nothing. +
  • +
+

+ space +

+

+ T& + optional<T&>::value() const ; +

+
  • + Effects: Equivalent to return bool(*this) ? *val : throw bad_optional_access();. +
+

+ space +

+

+ template<class R> T& optional<T&>::value_or( R&& r + ) const + noexcept; +

+
    +
  • + Effects: Equivalent to if (*this) return **this; else return + r;. +
  • +
  • + Remarks: Unless R + is an lvalue reference, the program is ill-formed. +
  • +
+

+ space +

+

+ template<class F> T& optional<T&>::value_or( F f ) const ; +

+
    +
  • + Effects: Equivalent to if (*this) return **this; else return + f();. +
  • +
  • + Remarks: Unless decltype(f()) is an lvalue reference, the program + is ill-formed. +
  • +
+

+ space +

+

+ T* + optional<T&>::get_ptr () + const noexcept; +

+
  • + Returns: ref. +
+

+ space +

+

+ optional<T&>::operator bool + () const + noexcept; +

+
  • + Returns: bool(ref). +
+

+ space +

+

+ optional<T&>::operator ! () const noexcept; +

+
  • + Returns: !bool(ref). +
+

+ space +

+

+ void optional<T&>::reset() noexcept; +

+
    +
  • + Effects: Use *this = none instead. +
  • +
  • + Remarks: This function is depprecated. +
  • +
+

+ space +

+

+ template<class R> void optional<T&>::reset ( R&& + r) + noexcept; +

+
    +
  • + Effects: Equivalent to *this = std::forward<R>(r). +
  • +
  • + Remarks: This function is depprecated. +
  • +
+

+ space +

+

+ bool optional<T&>::is_initialized() const noexcept; +

+
    +
  • + Effects: Equivalent to return bool(*this). +
  • +
  • + Remarks: This function is depprecated. +
  • +
+

+ space +

+

+ template<class R> T& optional<T&>::get_value_or( R&& r + ) const + noexcept; +

+
    +
  • + Effects: Equivalent to return value_or(std::forward<R>(r);. +
  • +
  • + Remarks: This function is depprecated. +
  • +
+
+ + + +
+
+
+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 new file mode 100644 index 0000000..a33ad48 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html @@ -0,0 +1,1584 @@ + + + +Detailed Semantics - Optional Values + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ + + + + +
[Note]Note

+ The following section contains various assert() which are used only to show the postconditions + as sample code. It is not implied that the type T + must support each particular expression but that if the expression is + supported, the implied condition holds. +

+

+ space +

+

+ optional<T>::optional() + noexcept; +

+
    +
  • + Effect: Default-Constructs an optional. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's default constructor is not called. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( !def ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + none_t ) + noexcept; +

+
    +
  • + Effect: Constructs an optional uninitialized. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's + default constructor is not called. + The expression boost::none + denotes an instance of boost::none_t + that can be used as the parameter. +
  • +
  • + Example: +
    #include <boost/none.hpp>
    +optional<T> n(none) ;
    +assert ( !n ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + T const& v ) +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is a copy of v. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: T::T( T const& + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + T&& + v ) +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Move-Constructs an + optional. +
  • +
  • + Postconditions: *this is initialized + and its value is move-constructed from v. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Notes: T::T( T&& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, the state of v + is determined by exception safety guarantees for T::T(T&&). +
  • +
  • + Example: +
    T v1, v2;
    +optional<T> opt(std::move(v1));
    +assert ( *opt == v2 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + bool condition, T const& v ) ; +

+
  • + If condition is true, same as: +
+

+ optional<T>::optional( + T const& v ) +

+
  • + otherwise, same as: +
+

+ optional<T>::optional() +

+

+ space +

+

+ optional<T>::optional( + optional const& rhs + ); +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs is initialized, + *this + is initialized and its value is a copy of the + value of rhs; else + *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: If rhs is initialized, T::T(T const& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<T> uninit ;
    +assert (!uninit);
    +
    +optional<T> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<T> init( T(2) );
    +assert ( *init == T(2) ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( init2 == init ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + optional&& + rhs ) + noexcept(see + below); +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move constructed from rhs; else *this is uninitialized. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value. +
  • +
  • + Notes: If rhs + is initialized, T::T( T && + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + of T::T(T&&). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<std::unique_ptr<T>> init( std::uniqye_ptr<T>(new T(2)) );
    +assert ( **init == T(2) ) ;
    +
    +optional<std::unique_ptr<T>> init2 ( std::move(init) ) ;
    +assert ( init );
    +assert ( *init == nullptr );
    +assert ( init2 );
    +assert ( **init2 == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T>::optional( optional<U> const& rhs + ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is a copy of the + value of rhs converted to type T; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U const& + ) throws. +
  • +
  • + Notes: T::T( U const& + ) is called if rhs is initialized, which requires + a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(x) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T>::optional( optional<U>&& rhs + ); +

+
    +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move-constructed from *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U&& ) + throws. +
  • +
  • + Notes: T::T( U&& ) + is called if rhs is + initialized, which requires a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + guarantee of T::T( U&& + ). +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(std::move(x)) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + explicit optional<T>::optional( InPlaceFactory + const& + f ); +

+

+ template<TypedInPlaceFactory> + explicit optional<T>::optional( TypedInPlaceFactory + const& + f ); +

+
    +
  • + Effect: Constructs an optional with a value of T obtained from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, this constructor has + no effect. +
  • +
  • + Example: +
    class C { C ( char, double, std::string ) ; } ;
    +
    +C v('A',123.4,"hello");
    +
    +optional<C> x( in_place   ('A', 123.4, "hello") ); // InPlaceFactory used
    +optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used
    +
    +assert ( *x == v ) ;
    +assert ( *y == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( none_t + ) noexcept; +

+
    +
  • + Effect: If *this is initialized destroys its contained + value. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( T const& rhs ) ; +

+
    +
  • + Effect: Assigns the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + a copy of rhs. +
  • +
  • + Throws: Whatever T::operator=( T const& + ) or T::T(T const&) + throws. +
  • +
  • + Notes: If *this was initialized, T's assignment operator is used, + otherwise, its copy-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + copy constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y;
    +def = y ;
    +assert ( *def == y ) ;
    +opt = y ;
    +assert ( *opt == y ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( T&& rhs + ) ; +

+
    +
  • + Effect: Moves the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + moved from rhs. +
  • +
  • + Throws: Whatever T::operator=( T&& ) + or T::T(T &&) + throws. +
  • +
  • + Notes: If *this was initialized, T's move-assignment operator is used, + otherwise, its move-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + move constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y1, y2, yR;
    +def = std::move(y1) ;
    +assert ( *def == yR ) ;
    +opt = std::move(y2) ;
    +assert ( *opt == yR ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( optional + const& + rhs ) + ; +

+
    +
  • + Requires: T + is CopyConstructible and CopyAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's copy constructor, no effect. + If an exception is thrown during the call to T's + copy assignment, the state of its contained value is as defined by + the exception safety guarantee of T's + copy assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( !def ) ;
    +// previous value (copy of 'v') destroyed from within 'opt'.
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Requires: T + is MoveConstructible + and MoveAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value && + is_nothrow_move_assignable<T>::value. +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's move constructor, the state of + *rhs + is determined by the exception safety guarantee of T's + move constructor. If an exception is thrown during the call to T's + move-assignment, the state of **this and *rhs is determined by the exception + safety guarantee of T's move assignment. +
  • +
  • + Example: +
    optional<T> opt(T(2)) ;
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( def ) ;
    +assert ( opt ) ;
    +assert ( *opt == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> optional& + optional<T>::operator= ( optional<U> const& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = opt0 ;
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> optional& + optional<T>::operator= ( optional<U>&& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = std::move(opt0) ;
    +assert ( opt0 );
    +assert ( opt1 )
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

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

+
    +
  • + Requires: The compiler supports rvalue + references and variadic templates. +
  • +
  • + Effect: If *this is initialized calls *this = none. + Then initializes in-place the contained value as if direct-initializing + an object of type T + with std::forward<Args>(args).... +
  • +
  • + 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 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. +
  • +
  • + Example: +
    T v;
    +optional<const T> opt;
    +opt.emplace(0);  // create in-place using ctor T(int)
    +opt.emplace();   // destroy previous and default-construct another T
    +opt.emplace(v);  // destroy and copy-construct in-place (no assignment called)
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + optional<T>& + optional<T>::operator=( InPlaceFactory const& f ); +

+

+ template<TypedInPlaceFactory> + optional<T>& + optional<T>::operator=( TypedInPlaceFactory const& f ); +

+
    +
  • + Effect: Assigns an optional + with a value of T obtained + from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, the optional + object will be reset to be uninitialized. +
  • +
+

+ space +

+

+ void optional<T>::reset( T const& v ) ; +

+
  • + Deprecated: same as operator= + ( T + const& + v) + ; +
+

+ space +

+

+ void optional<T>::reset() noexcept + ; +

+
  • + Deprecated: Same as operator=( + none_t ); +
+

+ space +

+

+ T const& optional<T>::get() const ; +

+

+ T& + optional<T>::get() ; +

+

+ inline T + const& + get ( + optional<T> const& ) ; +

+

+ inline T& get + ( optional<T> &) + ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T>::operator*() const& ; +

+

+ T& + optional<T>::operator*() + &; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + these two overloads are replaced with the classical two: a const and non-const + member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> opt ( v );
    +T const& u = *opt;
    +assert ( u == v ) ;
    +T w ;
    +*opt = w ;
    +assert ( *opt == w ) ;
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T>::operator*() + &&; +

+
    +
  • + Requires: *this contains a value. +
  • +
  • + Effects: Equivalent to return std::move(*val);. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + this overload is not present. +
  • +
+

+ space +

+

+ T const& optional<T>::value() const& ; +

+

+ T& + optional<T>::value() & ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? *val : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions these two overloads are replaced + with the classical two: a const + and non-const member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> o0, o1 ( v );
    +assert ( o1.value() == v );
    +
    +try {
    +  o0.value(); // throws
    +  assert ( false );
    +}
    +catch(bad_optional_access&) {
    +  assert ( true );
    +}
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T>::value() && ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? std::move(*val) : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + const& + ; +

+
    +
  • + Effects: Equivalent to if (*this) return **this; else return + std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not CopyConstructible or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. On compilers without rvalue reference support the type of + v becomes U const&. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + && ; +

+
    +
  • + Effects: Equivalent to if (*this) return std::move(**this); else return std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not MoveConstructible + or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) const& ; +

+
    +
  • + Requires: T + is CopyConstructible and F models a Generator whose result type + is convertible to T. +
  • +
  • + Effects: if + (*this) return **this; else return f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. +
  • +
  • + Example: +
    int complain_and_0()
    +{
    +  clog << "no value returned, using default" << endl;
    +  return 0;
    +}
    +
    +optional<int> o1 = 1;
    +optional<int> oN = none;
    +
    +int i = o1.value_or_eval(complain_and_0); // fun not called
    +assert (i == 1);
    +
    +int j = oN.value_or_eval(complain_and_0); // fun called
    +assert (i == 0);
    +
    +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) && + ; +

+
    +
  • + Requires: T + is MoveConstructible + and F models a Generator + whose result type is convertible to T. +
  • +
  • + Effects: if + (*this) return std::move(**this); else return + f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ T const& optional<T>::get_value_or( T const& default) const ; +

+

+ T& + optional<T>::get_value_or( + T& + default ) + ; +

+
    +
  • + Deprecated: Use value_or() instead. +
  • +
  • + Returns: A reference to the contained + value, if any, or default. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v, z ;
    +optional<T> def;
    +T const& y = def.get_value_or(z);
    +assert ( y == z ) ;
    +
    +optional<T> opt ( v );
    +T const& u = opt.get_value_or(z);
    +assert ( u == v ) ;
    +assert ( u != z ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T>::get_ptr() const ; +

+

+ T* + optional<T>::get_ptr() + ; +

+
    +
  • + Returns: If *this is initialized, a pointer to the + contained value; else 0 + (null). +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The contained value is permanently + stored within *this, + so you should not hold nor delete this pointer +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> const copt(v);
    +T* p = opt.get_ptr() ;
    +T const* cp = copt.get_ptr();
    +assert ( p == get_pointer(opt) );
    +assert ( cp == get_pointer(copt) ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T>::operator + ->() const + ; +

+

+ T* + optional<T>::operator ->() + ; +

+
    +
  • + Requires: *this is initialized. +
  • +
  • + Returns: A pointer to the contained + value. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
  • + Example: +
    struct X { int mdata ; } ;
    +X x ;
    +optional<X> opt (x);
    +opt->mdata = 2 ;
    +
    +
  • +
+

+ space +

+

+ explicit optional<T>::operator + bool() + const noexcept + ; +

+
    +
  • + Returns: get_ptr() != 0. +
  • +
  • + Notes: On compilers that do not support + explicit conversion operators this falls back to safe-bool idiom. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( def == 0 );
    +optional<T> opt ( v ) ;
    +assert ( opt );
    +assert ( opt != 0 );
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::operator!() noexcept + ; +

+
    +
  • + Returns: If *this is uninitialized, true; else false. +
  • +
  • + Notes: This operator is provided for + those compilers which can't use the unspecified-bool-type + operator in certain boolean contexts. +
  • +
  • + Example: +
    optional<T> opt ;
    +assert ( !opt );
    +*opt = some_T ;
    +
    +// Notice the "double-bang" idiom here.
    +assert ( !!opt ) ;
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::is_initialized() const ; +

+
  • + Deprecated: Same as explicit operator + bool () + ; +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header__boost_optional_hpp_.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header__boost_optional_hpp_.html new file mode 100644 index 0000000..8496d37 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header__boost_optional_hpp_.html @@ -0,0 +1,47 @@ + + + +Header <boost/optional.hpp> + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This is an alias for header <boost/optional/optional.hpp>. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_refs.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_refs.html new file mode 100644 index 0000000..c3325c5 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_refs.html @@ -0,0 +1,113 @@ + + + +Optional References + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
template <class T>
+class optional<T&> // specilization for lvalue references
+{
+public :
+
+    typedef T& value_type;
+    typedef T& reference_type;
+    typedef T& reference_const_type; // no const propagation
+    typedef T* pointer_type;
+    typedef T* pointer_const_type;   // no const propagation
+
+    optional () noexcept ; R
+
+    optional ( none_t ) noexcept ; R
+
+    template<class R> optional(R&& r) noexcept ;  R
+
+    template <class R> optional(bool cond, R&& r) noexcept ; R
+
+    optional ( optional const& rhs ) noexcept ; R
+
+    template<class U> explicit optional ( optional<U&> const& rhs ) noexcept ; R
+
+    optional& operator = ( none_t ) noexcept ; R
+
+
+    optional& operator = ( optional const& rhs ) noexcept; R
+
+    template<class U> optional& operator = ( optional<U&> const& rhs ) noexcept ; R
+
+    template<class R> optional& operator = (R&& r) noexcept ; R
+
+    template<class R> void emplace ( R&& r ) noexcept ; R
+
+    T& get() const ; R
+    T& operator *() const ; R
+
+    T* operator ->() const ; R
+
+    T& value() const& ; R
+
+    template<class R> T& value_or( R && r ) const noexcept ; R
+
+    template<class F> T& value_or_eval( F f ) const ; R
+
+    T* get_ptr() const noexcept ; R
+
+    explicit operator bool() const noexcept ; R
+
+    bool operator!() const noexcept ; R
+
+    // deprecated methods
+
+    // (deprecated)
+    void reset() noexcept ; R
+
+    // (deprecated)
+    template<class R> void reset ( R && r ) noexcept ; R
+
+    // (deprecated)
+    bool is_initialized() const noexcept ; R
+
+    // (deprecated)
+    template<class R> T& get_value_or( R && r ) constnoexcept; R
+
+private:
+    T* ref; // exposition only
+};
+
+
+ + + +
+
+
+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 new file mode 100644 index 0000000..2877563 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html @@ -0,0 +1,140 @@ + + + +Optional Values + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
template <class T>
+class optional
+{
+public :
+
+    typedef T         value_type ;
+    typedef T &       reference_type ;
+    typedef T const&  reference_const_type ;
+    typedef T *       pointer_type ;
+    typedef T const*  pointer_const_type ;
+
+    optional () noexcept ; R
+
+    optional ( none_t ) noexcept ; R
+
+    optional ( T const& v ) ; R
+
+    optional ( T&& v ) ; R
+
+    // [new in 1.34]
+    optional ( bool condition, T const& v ) ; R
+
+    optional ( optional const& rhs ) ; R
+
+    optional ( optional&& rhs ) noexcept(see below) ; R
+
+    template<class U> explicit optional ( optional<U> const& rhs ) ; R
+
+    template<class U> explicit optional ( optional<U>&& rhs ) ; R
+
+    template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; R
+
+    template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; R
+
+    optional& operator = ( none_t ) noexcept ; R
+
+    optional& operator = ( T const& v ) ; R
+
+    optional& operator = ( T&& v ) ; R
+
+    optional& operator = ( optional const& rhs ) ; R
+
+    optional& operator = ( optional&& rhs ) noexcept(see below) ; R
+
+    template<class U> optional& operator = ( optional<U> const& rhs ) ; R
+
+    template<class U> optional& operator = ( optional<U>&& rhs ) ; R
+
+    template<class... Args> void emplace ( Args...&& args ) ; R
+
+    template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; R
+
+    template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; R
+
+    T const& get() const ; R
+    T&       get() ; R
+
+    T const* operator ->() const ; R
+    T*       operator ->() ; R
+
+    T const& operator *() const& ; R
+    T&       operator *() & ; R
+    T&&      operator *() && ; R
+
+    T const& value() const& ; R
+    T&       value() & ; R
+    T&&      value() && ; R
+
+    template<class U> T value_or( U && v ) const& ; R
+    template<class U> T value_or( U && v ) && ; R
+
+    template<class F> T value_or_eval( F f ) const& ; R
+    template<class F> T value_or_eval( F f ) && ; R
+
+    T const* get_ptr() const ; R
+    T*       get_ptr() ; R
+
+    explicit operator bool() const noexcept ; R
+
+    bool operator!() const noexcept ; R
+
+    // deprecated methods
+
+    // (deprecated)
+    void reset() noexcept ; R
+
+    // (deprecated)
+    void reset ( T const& ) ; R
+
+    // (deprecated)
+    bool is_initialized() const ; R
+
+    // (deprecated)
+    T const& get_value_or( T const& default ) const ; R
+};
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_optional/reference/relnotes.html b/doc/html/boost_optional/reference/relnotes.html new file mode 100644 index 0000000..c67535e --- /dev/null +++ b/doc/html/boost_optional/reference/relnotes.html @@ -0,0 +1,183 @@ + + + +Release Notes + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ + Boost Release + X.XX +
+
  • + Now boost::optional is specialized for reference + parameters. This way the sizeof + of optional reference is that of a pointer, and a number of bugs is avoided. +
+
+ + Boost Release + 1.60 +
+
  • + Changed the implementation of boost::none + again. Now it is a const object with internal linkage (as any other tag). + This fixes Trac + #11203. +
+
+ + Boost Release + 1.59 +
+
    +
  • + For C++03 compilers, added 0-argument overload for member function emplace(), + and therewith removed the dependency on <boost/utility/in_place_factory.hpp>. +
  • +
  • + Fixed Trac + #11241. +
  • +
+
+ + Boost Release + 1.58 +
+
    +
  • + boost::none_t is no longer convertible from + literal 0. This avoids a + bug where optional<rational<int>> + oi = + 0; + would initialize an optional object with no contained value. +
  • +
  • + Improved the trick that prevents streaming out optional + without header optional_io.hpp + by using safe-bool idiom. This addresses Trac + #10825. +
  • +
  • + IOStream operators are now mentioned in documentation. +
  • +
  • + Added a way to manually disable move semantics: just define macro BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES. + This can be used to work around Trac + #10399. +
  • +
  • + It is no longer possible to assign optional<U> to optional<T> when U + is not assignable or convertible to T + (Trac #11087). +
  • +
  • + Value accessors now work correctly on rvalues of optional<T&> (Trac + #10839). +
  • +
+
+ + Boost Release + 1.57 +
+
  • + Git pull #9: + "Supply <string> + to fix C++03 compile error on logic_error("...")". +
+
+ + Boost Release + 1.56 +
+
    +
  • + Added support for rvalue references. Now optional<T> works with moveable but non-copyable + T's, +
  • +
  • + Improved swap (now uses + move operations), +
  • +
  • + Added function emplace(). This is the last of the requests from + Trac #1841, +
  • +
  • + optional is moveable, + including conditional noexcept + specifications, which make it move_if_noexcept-friendly, +
  • +
  • + Using explicit operator bool() on platforms that support it (Trac + #4227) (breaking change), +
  • +
  • + Forward declaration of operator<<(ostream&, optional + const&) + to prevent inadvertent incorrect serialization of optional objects, +
  • +
  • + Removed deprecated function reset() from examples (Trac + #9005), +
  • +
  • + Equality comparison with boost::none + does not require that T + be EqualityComparable, +
  • +
  • + Optional rvalue references are explicitly disallowed, +
  • +
  • + Binding temporaries to optional references is explicitly disallowed (breaking + change), +
  • +
  • + More ways to access the contained value, functions value(), value_or(), value_or_eval(), +
  • +
  • + Updated and reorganized documentation, added tutorial and quick guide + sections. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/index.html b/doc/html/index.html index b138f4f..2cdf6cd 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -146,7 +146,7 @@
- +

Last revised: February 13, 2016 at 13:50:14 GMT

Last revised: February 16, 2016 at 20:02:53 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 f8905f5..a395d63 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

@@ -36,134 +36,50 @@ namespace boost { template <class T> -class optional -{ -public : +class optional ; R - typedef T value_type; +template <class T> +class optional<T&> ; R - // (If T is of reference type, the parameters and results by reference are by value) +template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ; R - optional () noexcept ; R +template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ; R - optional ( none_t ) noexcept ; R +template<class T> inline bool operator < ( optional<T> const& x, optional<T> const& y ) ; R - optional ( T const& v ) ; R +template<class T> inline bool operator > ( optional<T> const& x, optional<T> const& y ) ; R - optional ( T&& v ) ; R +template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ; R - // [new in 1.34] - optional ( bool condition, T const& v ) ; R +template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; R - optional ( optional const& rhs ) ; R +template<class T> inline bool operator == ( optional<T> const& x, none_t ) noexcept ; R - optional ( optional&& rhs ) noexcept(see below) ; R +template<class T> inline bool operator != ( optional<T> const& x, none_t ) noexcept ; R - template<class U> explicit optional ( optional<U> const& rhs ) ; R +template<class T> inline optional<T> make_optional ( T const& v ) ; R - template<class U> explicit optional ( optional<U>&& rhs ) ; R +template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ; R - template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; R +template<class T> inline auto get_optional_value_or ( optional<T> const& opt, typename optional<T>::reference_const_type def ) -> typename optional<T>::reference_const_type; R - template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; R +template<class T> inline auto get_optional_value_or ( optional<T> const& opt, typename optional<T>::reference_type def ) -> typename optional<T>::reference_type ; R - optional& operator = ( none_t ) noexcept ; R +template<class T> inline T const& get ( optional<T> const& opt ) ; R - optional& operator = ( T const& v ) ; R +template<class T> inline T& get ( optional<T> & opt ) ; R - optional& operator = ( T&& v ) ; R +template<class T> inline T const* get ( optional<T> const* opt ) ; R - optional& operator = ( optional const& rhs ) ; R +template<class T> inline T* get ( optional<T>* opt ) ; R - optional& operator = ( optional&& rhs ) noexcept(see below) ; R +template<class T> inline auto get_pointer ( optional<T> const& opt ) -> see below; R - template<class U> optional& operator = ( optional<U> const& rhs ) ; R +template<class T> inline auto get_pointer ( optional<T> & opt ) -> see below; R - template<class U> optional& operator = ( optional<U>&& rhs ) ; R +template<class T> inline void swap( optional<T>& x, optional<T>& y ) ; R - template<class... Args> void emplace ( Args...&& args ) ; R - - template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; R - - template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; R - - T const& get() const ; R - T& get() ; R - - T const* operator ->() const ; R - T* operator ->() ; R - - T const& operator *() const& ; R - T& operator *() & ; R - T&& operator *() && ; R - - T const& value() const& ; R - T& value() & ; R - T&& value() && ; R - - template<class U> T value_or( U && v ) const& ; R - template<class U> T value_or( U && v ) && ; R - - template<class F> T value_or_eval( F f ) const& ; R - template<class F> T value_or_eval( F f ) && ; R - - T const* get_ptr() const ; R - T* get_ptr() ; R - - explicit operator bool() const noexcept ; R - - bool operator!() const noexcept ; R - - // deprecated methods - - // (deprecated) - void reset() noexcept ; R - - // (deprecated) - void reset ( T const& ) ; R - - // (deprecated) - bool is_initialized() const ; R - - // (deprecated) - T const& get_value_or( T const& default ) const ; R -}; - -template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ; R - -template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ; R - -template<class T> inline bool operator < ( optional<T> const& x, optional<T> const& y ) ; R - -template<class T> inline bool operator > ( optional<T> const& x, optional<T> const& y ) ; R - -template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ; R - -template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; R - -template<class T> inline bool operator == ( optional<T> const& x, none_t ) noexcept ; R - -template<class T> inline bool operator != ( optional<T> const& x, none_t ) noexcept ; R - -template<class T> inline optional<T> make_optional ( T const& v ) ; R - -template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ; R - -template<class T> inline T const& get_optional_value_or ( optional<T> const& opt, T const& default ) ; R - -template<class T> inline T const& get ( optional<T> const& opt ) ; R - -template<class T> inline T& get ( optional<T> & opt ) ; R - -template<class T> inline T const* get ( optional<T> const* opt ) ; R - -template<class T> inline T* get ( optional<T>* opt ) ; R - -template<class T> inline T const* get_pointer ( optional<T> const& opt ) ; R - -template<class T> inline T* get_pointer ( optional<T> & opt ) ; R - -template<class T> inline void swap( optional<T>& x, optional<T>& y ) ; R +template<class T> inline void swap( optional<T&>& x, optional<T&>& y ) ; R } // namespace boost @@ -179,7 +95,7 @@


-PrevUpHomeNext +PrevUpHomeNext
From b0602a1161b043f2b1fdfdd2fda68fc72c8a2778 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Tue, 16 Feb 2016 23:49:15 +0100 Subject: [PATCH 39/54] more unit test for opt ref swap and abstract types --- doc/91_relnotes.qbk | 7 +- doc/html/boost_optional/relnotes.html | 29 ++++- doc/html/index.html | 2 +- test/Jamfile.v2 | 1 - ...ional_test_ref_assign_portable_minimum.cpp | 2 +- ...tional_test_ref_convert_assign_non_int.cpp | 2 +- test/optional_test_ref_converting_ctor.cpp | 2 +- test/optional_test_ref_portable_minimum.cpp | 39 +++++-- test/optional_test_ref_swap.cpp | 106 ------------------ 9 files changed, 66 insertions(+), 124 deletions(-) delete mode 100644 test/optional_test_ref_swap.cpp diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index 81449dc..1dced5f 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -13,7 +13,12 @@ [heading Boost Release X.XX] -* Now `boost::optional` is specialized for reference parameters. This way the `sizeof` of optional reference is that of a pointer, and a number of bugs is avoided. +* Now `boost::optional` is specialized for reference parameters. This addresses a couple of issues: + * the `sizeof` of optional reference is that of a pointer, + * some bugs connected to copying optional references are gone, + * you can swap optional references: it is like swapping pointers: shalow, underlying objects are not affected, + * optional references to abstract types work. +* Documented nested typedefs ([@https://svn.boost.org/trac/boost/ticket/5193 Trac #5193]). [heading Boost Release 1.60] diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html index c920338..53b9020 100644 --- a/doc/html/boost_optional/relnotes.html +++ b/doc/html/boost_optional/relnotes.html @@ -31,11 +31,32 @@ Boost Release X.XX -
  • +
      +
    • Now boost::optional is specialized for reference - parameters. This way the sizeof - of optional reference is that of a pointer, and a number of bugs is avoided. -
    + parameters. This addresses a couple of issues: +
      +
    • + the sizeof of optional + reference is that of a pointer, +
    • +
    • + some bugs connected to copying optional references are gone, +
    • +
    • + you can swap optional references: it is like swapping pointers: shalow, + underlying objects are not affected, +
    • +
    • + optional references to abstract types work. +
    • +
    +
  • +
  • + Documented nested typedefs (Trac + #5193). +
  • +

Boost diff --git a/doc/html/index.html b/doc/html/index.html index 2cdf6cd..15c6d1e 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -146,7 +146,7 @@ - +

Last revised: February 16, 2016 at 20:02:53 GMT

Last revised: February 16, 2016 at 22:59:47 GMT


diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index bcb3c75..765fe53 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -30,7 +30,6 @@ import testing ; [ run optional_test_ref_convert_assign_const_int.cpp ] [ run optional_test_ref_portable_minimum.cpp ] [ run optional_test_ref_move.cpp ] - [ run optional_test_ref_swap.cpp ] [ run optional_test_inplace_factory.cpp ] [ run optional_test_io.cpp ] [ run optional_test_move.cpp ] diff --git a/test/optional_test_ref_assign_portable_minimum.cpp b/test/optional_test_ref_assign_portable_minimum.cpp index 2a548ab..9ee0a0f 100644 --- a/test/optional_test_ref_assign_portable_minimum.cpp +++ b/test/optional_test_ref_assign_portable_minimum.cpp @@ -38,7 +38,7 @@ void test_optional_ref_assignment() int main() { test_optional_ref_assignment(); - //test_optional_ref_assignment(); + test_optional_ref_assignment(); return boost::report_errors(); } diff --git a/test/optional_test_ref_convert_assign_non_int.cpp b/test/optional_test_ref_convert_assign_non_int.cpp index d59e46e..556b757 100644 --- a/test/optional_test_ref_convert_assign_non_int.cpp +++ b/test/optional_test_ref_convert_assign_non_int.cpp @@ -33,7 +33,7 @@ void test_all_const_cases() int main() { test_all_const_cases(); - //test_all_const_cases(); + test_all_const_cases(); return boost::report_errors(); } diff --git a/test/optional_test_ref_converting_ctor.cpp b/test/optional_test_ref_converting_ctor.cpp index d7df3dc..735c354 100644 --- a/test/optional_test_ref_converting_ctor.cpp +++ b/test/optional_test_ref_converting_ctor.cpp @@ -101,7 +101,7 @@ int main() { test_all_const_cases(); test_all_const_cases(); - //test_all_const_cases(); + test_all_const_cases(); return boost::report_errors(); } diff --git a/test/optional_test_ref_portable_minimum.cpp b/test/optional_test_ref_portable_minimum.cpp index e8439c9..a923804 100644 --- a/test/optional_test_ref_portable_minimum.cpp +++ b/test/optional_test_ref_portable_minimum.cpp @@ -256,11 +256,11 @@ void test_equality() BOOST_TEST( (o2 != oN)); } -template +template void test_order() { typename concrete_type_of::type v1(1), v2(2), v2_(2), v3(3); - optional o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_; + optional o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_; // o2 and o2_ point to different objects; o3 and o3_ point to the same object BOOST_TEST(!(oN < oN)); @@ -399,13 +399,35 @@ void test_order() BOOST_TEST(!(o3_ < oN_)); } -template +template void test_swap() { typename concrete_type_of::type v1(1), v2(2); - optional o1(v1), o1_(v1), o2(v2), o2_(v2), oN, oN_; + optional o1(v1), o1_(v1), o2(v2), o2_(v2), oN, oN_; - // swap(o1, o1); DOESN'T WORK + swap(o1, o1); + BOOST_TEST(o1); + BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1)); + + swap(oN, oN_); + BOOST_TEST(!oN); + BOOST_TEST(!oN_); + + swap(o1, oN); + BOOST_TEST(!o1); + BOOST_TEST(oN); + BOOST_TEST(boost::addressof(*oN) == boost::addressof(v1)); + + swap(oN, o1); + BOOST_TEST(!oN); + BOOST_TEST(o1); + BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1)); + + swap(o1_, o2_); + BOOST_TEST(o1_); + BOOST_TEST(o2_); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(v2)); + BOOST_TEST(boost::addressof(*o2_) == boost::addressof(v1)); } template @@ -431,18 +453,19 @@ void test_optional_const_ref() test_arrow_noconst_const(); test_equality(); test_order(); - //test_swap(); + test_swap(); + test_swap(); } int main() { test_optional_ref(); test_optional_ref(); - //test_optional_ref(); + test_optional_ref(); test_optional_const_ref(); test_optional_const_ref(); - //test_optional_const_ref(); + test_optional_const_ref(); return boost::report_errors(); } diff --git a/test/optional_test_ref_swap.cpp b/test/optional_test_ref_swap.cpp deleted file mode 100644 index c9a6986..0000000 --- a/test/optional_test_ref_swap.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (C) 2016 Andrzej Krzemienski. -// -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/lib/optional for documentation. -// -// You are welcome to contact the maintainer at: akrzemi1@gmail.com - - -#include "boost/optional/optional.hpp" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#include -#include "boost/core/addressof.hpp" -#include "boost/core/lightweight_test.hpp" - -using boost::optional; - -struct Iface -{ - virtual void fun() = 0; - protected: ~Iface() {} -}; - -struct Impl : Iface -{ - void fun() {} -}; - -template -void test_swap_empty_with_empty() -{ - boost::optional o1, o2; - swap(o1, o2); - - BOOST_TEST(!o1); - BOOST_TEST(!o2); -} - -template -void test_swap_value_with_empty(U v1) -{ - boost::optional o1 (v1), o2; - swap(o1, o2); - - BOOST_TEST(!o1); - BOOST_TEST(o2); - BOOST_TEST(boost::addressof(*o2) == boost::addressof(v1)); -} - -template -void test_swap_empty_with_value(U v2) -{ - boost::optional o1, o2(v2); - swap(o1, o2); - - BOOST_TEST(o1); - BOOST_TEST(boost::addressof(*o1) == boost::addressof(v2)); - BOOST_TEST(!o2); -} - -template -void test_swap_value_with_value(U v1, U v2) -{ - boost::optional o1(v1), o2(v2); - swap(o1, o2); - - BOOST_TEST(o1); - BOOST_TEST(o2); - BOOST_TEST(boost::addressof(*o1) == boost::addressof(v2)); - BOOST_TEST(boost::addressof(*o2) == boost::addressof(v1)); -} - -int main() -{ - std::string s1 ("AAA"), s2 ("BB"); - int i1 = 1, i2 = 2; - Impl p1, p2; - - test_swap_empty_with_empty( ); - test_swap_value_with_empty(s1 ); - test_swap_empty_with_value( s2); - test_swap_value_with_value(s1, s2); - - test_swap_empty_with_empty( ); - test_swap_value_with_empty(i1 ); - test_swap_empty_with_value( i2); - test_swap_value_with_value(i1, i2); - - test_swap_empty_with_empty( ); - test_swap_value_with_empty(p1 ); - test_swap_empty_with_value( p2); - test_swap_value_with_value(p1, p2); - - test_swap_empty_with_empty( ); - test_swap_value_with_empty(p1 ); - test_swap_empty_with_value( p2); - test_swap_value_with_value(p1, p2); - - return boost::report_errors(); -} From 414728970aed033c784112ed5b509fe6a372215b Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Wed, 17 Feb 2016 16:26:47 +0100 Subject: [PATCH 40/54] fixed optional refs test. I was using default values for function teplate parameters, wchich does not compile in C++03. --- test/optional_test_ref_portable_minimum.cpp | 31 +++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/test/optional_test_ref_portable_minimum.cpp b/test/optional_test_ref_portable_minimum.cpp index a923804..5bd7d11 100644 --- a/test/optional_test_ref_portable_minimum.cpp +++ b/test/optional_test_ref_portable_minimum.cpp @@ -199,11 +199,11 @@ void test_direct_init_for() BOOST_TEST_EQ(val(v), 7); } -template +template void test_clearing_the_value() { typename concrete_type_of::type v(2); - optional o1(v), o2(v); + optional o1(v), o2(v); BOOST_TEST(o1); BOOST_TEST(o1 != none); @@ -220,11 +220,11 @@ void test_clearing_the_value() BOOST_TEST_EQ(val(v), 2); } -template +template void test_equality() { typename concrete_type_of::type v1(1), v2(2), v2_(2), v3(3); - optional o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_; + optional o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_; // o2 and o2_ point to different objects; o3 and o3_ point to the same object BOOST_TEST(oN == oN); @@ -256,7 +256,7 @@ void test_equality() BOOST_TEST( (o2 != oN)); } -template +template void test_order() { typename concrete_type_of::type v1(1), v2(2), v2_(2), v3(3); @@ -399,7 +399,7 @@ void test_order() BOOST_TEST(!(o3_ < oN_)); } -template +template void test_swap() { typename concrete_type_of::type v1(1), v2(2); @@ -435,11 +435,11 @@ void test_optional_ref() { test_not_containing_value_for(); test_direct_init_for(); - test_clearing_the_value(); + test_clearing_the_value(); test_arrow(); - test_equality(); - test_order(); - test_swap(); + test_equality(); + test_order(); + test_swap(); } template @@ -448,12 +448,15 @@ void test_optional_const_ref() test_not_containing_value_for(); test_direct_init_for_const(); test_direct_init_for_noconst_const(); - test_clearing_the_value(); + test_clearing_the_value(); + test_clearing_the_value(); test_arrow_const(); test_arrow_noconst_const(); - test_equality(); - test_order(); - test_swap(); + test_equality(); + test_equality(); + test_order(); + test_order(); + test_swap(); test_swap(); } From 87ef50360680447b0a978660e1a8821e9cbb6418 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Wed, 17 Feb 2016 16:39:07 +0100 Subject: [PATCH 41/54] Removed empty optional destructor --- include/boost/optional/optional.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index d73bd62..819ab26 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -712,8 +712,6 @@ class optional : public optional_detail::optional_base {} #endif - // No-throw (assuming T::~T() doesn't) - ~optional() {} #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) // Assigns from an expression. See corresponding constructor. From c65337252439d6e516342671573bdfcd26b94596 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 18 Feb 2016 00:24:59 +0100 Subject: [PATCH 42/54] cleanup after separating references --- .../detail/optional_aligned_storage.hpp | 18 +++++ include/boost/optional/optional.hpp | 70 +++++-------------- 2 files changed, 36 insertions(+), 52 deletions(-) diff --git a/include/boost/optional/detail/optional_aligned_storage.hpp b/include/boost/optional/detail/optional_aligned_storage.hpp index c0ad272..35b3d12 100644 --- a/include/boost/optional/detail/optional_aligned_storage.hpp +++ b/include/boost/optional/detail/optional_aligned_storage.hpp @@ -46,6 +46,24 @@ class aligned_storage void const* address() const { return dummy_.data; } void * address() { return dummy_.data; } #endif + +#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) + // This workaround is supposed to silence GCC warnings about broken strict aliasing rules + T const& ref() const + { + union { void const* ap_pvoid; T const* as_ptype; } caster = { address() }; + return *caster.as_ptype; + } + T & ref() + { + union { void* ap_pvoid; T* as_ptype; } caster = { address() }; + return *caster.as_ptype; + } +#else + T const& ref() const { return *static_cast(address()); } + T & ref() { return *static_cast (address()); } +#endif + } ; } // namespace optional_detail diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 819ab26..2af9150 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -65,8 +65,7 @@ class optional_base : public optional_tag { private : - typedef T internal_type ; - typedef aligned_storage storage_type ; + typedef aligned_storage storage_type ; typedef optional_base this_type ; protected : @@ -321,14 +320,14 @@ class optional_base : public optional_tag void construct ( argument_type val ) { - ::new (m_storage.address()) internal_type(val) ; + ::new (m_storage.address()) value_type(val) ; m_initialized = true ; } #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES void construct ( rval_reference_type val ) { - ::new (m_storage.address()) internal_type( boost::move(val) ) ; + ::new (m_storage.address()) value_type( boost::move(val) ) ; m_initialized = true ; } #endif @@ -341,7 +340,7 @@ class optional_base : public optional_tag void emplace_assign ( Args&&... args ) { destroy(); - ::new (m_storage.address()) internal_type( boost::forward(args)... ); + ::new (m_storage.address()) value_type( boost::forward(args)... ); m_initialized = true ; } #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) @@ -349,14 +348,14 @@ class optional_base : public optional_tag void emplace_assign ( Arg&& arg ) { destroy(); - ::new (m_storage.address()) internal_type( boost::forward(arg) ); + ::new (m_storage.address()) value_type( boost::forward(arg) ); m_initialized = true ; } void emplace_assign () { destroy(); - ::new (m_storage.address()) internal_type(); + ::new (m_storage.address()) value_type(); m_initialized = true ; } #else @@ -364,7 +363,7 @@ class optional_base : public optional_tag void emplace_assign ( const Arg& arg ) { destroy(); - ::new (m_storage.address()) internal_type( arg ); + ::new (m_storage.address()) value_type( arg ); m_initialized = true ; } @@ -372,14 +371,14 @@ class optional_base : public optional_tag void emplace_assign ( Arg& arg ) { destroy(); - ::new (m_storage.address()) internal_type( arg ); + ::new (m_storage.address()) value_type( arg ); m_initialized = true ; } void emplace_assign () { destroy(); - ::new (m_storage.address()) internal_type(); + ::new (m_storage.address()) value_type(); m_initialized = true ; } #endif @@ -461,7 +460,7 @@ class optional_base : public optional_tag template void construct ( Expr&& expr, void const* ) { - new (m_storage.address()) internal_type(boost::forward(expr)) ; + new (m_storage.address()) value_type(boost::forward(expr)) ; m_initialized = true ; } @@ -482,7 +481,7 @@ class optional_base : public optional_tag template void construct ( Expr const& expr, void const* ) { - new (m_storage.address()) internal_type(expr) ; + new (m_storage.address()) value_type(expr) ; m_initialized = true ; } @@ -520,7 +519,7 @@ class optional_base : public optional_tag { // An exception can be thrown here. // It it happens, THIS will be left uninitialized. - new (m_storage.address()) internal_type(boost::move(expr.get())) ; + new (m_storage.address()) value_type(boost::move(expr.get())) ; m_initialized = true ; } } @@ -533,7 +532,7 @@ class optional_base : public optional_tag { // An exception can be thrown here. // It it happens, THIS will be left uninitialized. - new (m_storage.address()) internal_type(expr.get()) ; + new (m_storage.address()) value_type(expr.get()) ; m_initialized = true ; } } @@ -551,48 +550,15 @@ class optional_base : public optional_tag destroy_impl() ; } - reference_const_type get_impl() const { return dereference(get_object()) ; } - reference_type get_impl() { return dereference(get_object()) ; } + reference_const_type get_impl() const { return m_storage.ref() ; } + reference_type get_impl() { return m_storage.ref() ; } - pointer_const_type get_ptr_impl() const { return cast_ptr(get_object()) ; } - pointer_type get_ptr_impl() { return cast_ptr(get_object()) ; } + pointer_const_type get_ptr_impl() const { return boost::addressof(m_storage.ref()); } + pointer_type get_ptr_impl() { return boost::addressof(m_storage.ref()); } private : - // internal_type can be either T or reference_content -#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) - // This workaround is supposed to silence GCC warnings about broken strict aliasing rules - internal_type const* get_object() const - { - union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() }; - return caster.as_ptype; - } - internal_type * get_object() - { - union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() }; - return caster.as_ptype; - } -#else - internal_type const* get_object() const { return static_cast(m_storage.address()); } - internal_type * get_object() { return static_cast (m_storage.address()); } -#endif - - // reference_content lacks an implicit conversion to T&, so the following is needed to obtain a proper reference. - reference_const_type dereference( internal_type const* p ) const { return *p ; } - reference_type dereference( internal_type* p ) { return *p ; } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) - void destroy_impl ( ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; } -#else - void destroy_impl ( ) { get_ptr_impl()->~T() ; m_initialized = false ; } -#endif - - - // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error. - // Decent compilers should disallow conversions from reference_content* to T*, but just in case, - // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference. - pointer_const_type cast_ptr( internal_type const* p ) const { return p ; } - pointer_type cast_ptr( internal_type * p ) { return p ; } + void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; } bool m_initialized ; storage_type m_storage ; From 630fbb7973e105c85656bafc37a5173a4a5aa5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Thu, 18 Feb 2016 09:16:59 +0100 Subject: [PATCH 43/54] re-added explicit optional destructor If it is not there T::~T() is never called in buggy msvc-8.0. --- 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 2af9150..9d20282 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -678,7 +678,9 @@ class optional : public optional_detail::optional_base {} #endif - + // I need this declaration for msvc-8.0 (otherwise, T::~T() is never called) + ~optional() {} + #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) // Assigns from an expression. See corresponding constructor. // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED From 7ae2db7312a4f2bcdacb80373b0f7ec0f273adaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Thu, 18 Feb 2016 11:00:24 +0100 Subject: [PATCH 44/54] Conditionally removing optional destructor --- include/boost/optional/optional.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 9d20282..d227af5 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -678,8 +678,12 @@ class optional : public optional_detail::optional_base {} #endif - // I need this declaration for msvc-8.0 (otherwise, T::~T() is never called) - ~optional() {} + +#if BOOST_WORKAROUND(_MSC_VER, <= 1500) + // On old MSVC compilers the implicitly declared dtor is not called + ~optional() {} +#else + #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) // Assigns from an expression. See corresponding constructor. From b38b64cee9b0a90590e304da1aa6bdf2fc2af293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Thu, 18 Feb 2016 12:34:08 +0100 Subject: [PATCH 45/54] extended destructor workaround to MSVC 10.0 --- include/boost/optional/optional.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index d227af5..d8731ad 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -679,7 +679,7 @@ class optional : public optional_detail::optional_base #endif -#if BOOST_WORKAROUND(_MSC_VER, <= 1500) +#if BOOST_WORKAROUND(_MSC_VER, <= 1600) // On old MSVC compilers the implicitly declared dtor is not called ~optional() {} #else From 1671966380e8e337309435ed83064fa8ec25be9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Krzemie=C5=84ski?= Date: Thu, 18 Feb 2016 15:02:07 +0100 Subject: [PATCH 46/54] fixed preprocessor typeo --- include/boost/optional/optional.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index d8731ad..10b46ef 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -682,7 +682,7 @@ class optional : public optional_detail::optional_base #if BOOST_WORKAROUND(_MSC_VER, <= 1600) // On old MSVC compilers the implicitly declared dtor is not called ~optional() {} -#else +#endif #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) From 44d57a1d8bf1a4517c66f347bfa3065fb495affa Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 18 Feb 2016 23:18:01 +0100 Subject: [PATCH 47/54] Fix: prevented the binding illegal temporary to optional Older MSVC versions add illegal temporary when you want to assign from const integral value. --- doc/11_development.qbk | 2 +- doc/15_optional_references.qbk | 5 +- doc/28_ref_optional_semantics.qbk | 2 +- doc/90_dependencies.qbk | 8 +- doc/91_relnotes.qbk | 1 + .../optional_reference_binding.html | 26 +++-- ...ailed_semantics___optional_references.html | 2 +- doc/html/boost_optional/relnotes.html | 4 + .../design_overview/the_interface.html | 6 +- .../tutorial/in_place_factories.html | 6 +- .../tutorial/optional_references.html | 106 +++++++++--------- doc/html/index.html | 4 +- doc/html/optional/tutorial.html | 2 - .../detail/optional_reference_spec.hpp | 28 ++++- test/Jamfile.v2 | 1 + test/optional_ref_assign_test_defs.hpp | 20 +--- ...onal_test_ref_convert_assign_const_int.cpp | 6 +- ...ref_convert_assign_const_int_prevented.cpp | 32 ++++++ ...al_test_ref_convert_assign_mutable_int.cpp | 3 +- ...tional_test_ref_convert_assign_non_int.cpp | 6 +- 20 files changed, 161 insertions(+), 109 deletions(-) create mode 100644 test/optional_test_ref_convert_assign_const_int_prevented.cpp diff --git a/doc/11_development.qbk b/doc/11_development.qbk index 9e3ef44..de5d00d 100644 --- a/doc/11_development.qbk +++ b/doc/11_development.qbk @@ -228,7 +228,7 @@ For value access operations `optional<>` uses operators `*` and `->` to lexically warn about the possibly uninitialized state appealing to the familiar pointer semantics w.r.t. to null pointers. -[warning +[caution However, it is particularly important to note that `optional<>` objects are not pointers. [_`optional<>` is not, and does not model, a pointer]. ] diff --git a/doc/15_optional_references.qbk b/doc/15_optional_references.qbk index 2f8b3c6..acb1226 100644 --- a/doc/15_optional_references.qbk +++ b/doc/15_optional_references.qbk @@ -1,6 +1,8 @@  [section Optional references] +[section Overview] + This library allows the template parameter `T` to be of reference type: `T&`, and to some extent, `T const&`. @@ -21,7 +23,7 @@ will nonetheless refer to the same object. * Value-access will actually provide access to the referenced object rather than the reference itself. -[warning On compilers that do not conform to Standard C++ rules of reference binding, operations on optional references might give adverse results: rather than binding a reference to a designated object they may create an unexpected temporary and bind to it. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].] +[caution On compilers that do not conform to Standard C++ rules of reference binding, some operations on optional references are disabled in order to prevent subtle bugs. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].] [heading Rvalue references] @@ -118,3 +120,4 @@ In such a scenario, you can assign the value itself directly, as in: *opt=value; [endsect] +[endsect] diff --git a/doc/28_ref_optional_semantics.qbk b/doc/28_ref_optional_semantics.qbk index ca62937..31dc178 100644 --- a/doc/28_ref_optional_semantics.qbk +++ b/doc/28_ref_optional_semantics.qbk @@ -857,7 +857,7 @@ __SPACE__ * [*Postconditions:] `bool(*this) == bool(rhs)`. -* [*Notes:] This behaviour is called ['rebinding semantics]. See [link boost_optional.tutorial.rebinding_semantics_for_assignment_of_optional_references here] for details. +* [*Notes:] This behaviour is called ['rebinding semantics]. See [link boost_optional.tutorial.optional_references.rebinding_semantics_for_assignment_of_optional_references here] for details. * [*Example:] `` diff --git a/doc/90_dependencies.qbk b/doc/90_dependencies.qbk index cf678dc..80e1803 100644 --- a/doc/90_dependencies.qbk +++ b/doc/90_dependencies.qbk @@ -30,17 +30,17 @@ The implementation uses the following other Boost modules: [section Optional Reference Binding] -On compilers that do not conform to Standard C++ rules of reference binding, operations on optional references might give adverse results: rather than binding a reference to a designated object they may create an unexpected temporary and bind to it. Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. On these compilers prefer using 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 or1; - optional or2 = i; // not portable - or1 = i; // not portable + optional or2 = i; // caution: not portable + or1 = i; // caution: not portable optional or3(i); // portable or1 = optional(i); // portable -In order to check if your compiler correctly implements reference binding use this test program. +Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program. #include diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index 1dced5f..4af88a5 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -16,6 +16,7 @@ * Now `boost::optional` is specialized for reference parameters. This addresses a couple of issues: * the `sizeof` of optional reference is that of a pointer, * some bugs connected to copying optional references are gone, + * all run-time bugs caused by incorrect reference binding on some compilers are now turned into compile-time errors, * you can swap optional references: it is like swapping pointers: shalow, underlying objects are not affected, * optional references to abstract types work. * Documented nested typedefs ([@https://svn.boost.org/trac/boost/ticket/5193 Trac #5193]). 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 eef5322..fbe4ba8 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,24 +28,30 @@ Reference Binding

- On compilers that do not conform to Standard C++ rules of reference binding, - operations on optional references might give adverse results: rather than - binding a reference to a designated object they may create an unexpected - temporary and bind to it. Compilers known to have these deficiencies include - GCC versions 4.2, 4.3, 4.4, 4.5; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, - 11.0, 12.0. On these compilers prefer using 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;
-optional<const int&> or2 = i;  // not portable
-or1 = i;                       // not portable
+optional<const int&> or2 = i;  // caution: not portable
+or1 = i;                       // caution: not portable
 
 optional<const int&> or3(i);   // portable
 or1 = optional<const int&>(i); // portable
 

+ Compilers known to have these deficiencies include GCC versions 4.2, 4.3, + 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program.

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 05e3e21..0bca093 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 @@ -189,7 +189,7 @@
  • Notes: This behaviour is called rebinding - semantics. See here + semantics. See here for details.
  • diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html index 53b9020..0f05f9e 100644 --- a/doc/html/boost_optional/relnotes.html +++ b/doc/html/boost_optional/relnotes.html @@ -43,6 +43,10 @@
  • some bugs connected to copying optional references are gone,
  • +
  • + all run-time bugs caused by incorrect reference binding on some compilers + are now turned into compile-time errors, +
  • you can swap optional references: it is like swapping pointers: shalow, underlying objects are not affected, diff --git a/doc/html/boost_optional/tutorial/design_overview/the_interface.html b/doc/html/boost_optional/tutorial/design_overview/the_interface.html index 86c886f..77e17a5 100644 --- a/doc/html/boost_optional/tutorial/design_overview/the_interface.html +++ b/doc/html/boost_optional/tutorial/design_overview/the_interface.html @@ -142,10 +142,10 @@ about the possibly uninitialized state appealing to the familiar pointer semantics w.r.t. to null pointers.

    -
    +
    - - + +
    [Warning]Warning[Caution]Caution

    However, it is particularly important to note that optional<> objects are not pointers. optional<> is not, and does not model, a diff --git a/doc/html/boost_optional/tutorial/in_place_factories.html b/doc/html/boost_optional/tutorial/in_place_factories.html index ed63397..3b72041 100644 --- a/doc/html/boost_optional/tutorial/in_place_factories.html +++ b/doc/html/boost_optional/tutorial/in_place_factories.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@


    -PrevUpHomeNext +PrevUpHomeNext

    @@ -191,7 +191,7 @@


  • -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/tutorial/optional_references.html b/doc/html/boost_optional/tutorial/optional_references.html index ff03059..9dd45b3 100644 --- a/doc/html/boost_optional/tutorial/optional_references.html +++ b/doc/html/boost_optional/tutorial/optional_references.html @@ -7,7 +7,7 @@ - + @@ -20,85 +20,87 @@

    -PrevUpHomeNext +PrevUpHomeNext
    +
    +

    - This library allows the template parameter T - to be of reference type: T&, and to some extent, T - const&. -

    + This library allows the template parameter T + to be of reference type: T&, and to some extent, T const&. +

    - However, since references are not real objects some restrictions apply and - some operations are not available in this case: -

    + However, since references are not real objects some restrictions apply + and some operations are not available in this case: +

    • - Converting constructors -
    • + Converting constructors +
    • - Converting assignment -
    • + Converting assignment +
    • - InPlace construction -
    • + InPlace construction +
    • - InPlace assignment -
    • + InPlace assignment +
    • - Value-access via pointer -
    • + Value-access via pointer +

    - Also, even though optional<T&> - treats it wrapped pseudo-object much as a real value, a true real reference - is stored so aliasing will ocurr: -

    + Also, even though optional<T&> treats it wrapped pseudo-object + much as a real value, a true real reference is stored so aliasing will + ocurr: +

    • - Copies of optional<T&> - will copy the references but all these references will nonetheless refer - to the same object. -
    • + Copies of optional<T&> will copy the references but + all these references will nonetheless refer to the same object. +
    • - Value-access will actually provide access to the referenced object rather - than the reference itself. -
    • + Value-access will actually provide access to the referenced object + rather than the reference itself. +
    -
    +
    - - + + + On compilers that do not conform to Standard C++ rules of reference binding, + some operations on optional references are disabled in order to prevent + subtle bugs. For more details see Dependencies + and Portability section. +

    [Warning]Warning[Caution]Caution

    - On compilers that do not conform to Standard C++ rules of reference binding, - operations on optional references might give adverse results: rather than - binding a reference to a designated object they may create an unexpected - temporary and bind to it. For more details see Dependencies - and Portability section. -

    -
    - - Rvalue - references -
    +
    + + Rvalue + references +

    - Rvalue references and lvalue references to const have the ability in C++ - to extend the life time of a temporary they bind to. Optional references - do not have this capability, therefore to avoid surprising effects it is - not possible to initialize an optional references from a temporary. Optional - rvalue references are disabled altogether. Also, the initialization and assignment - of an optional reference to const from rvalue reference is disabled. -

    + Rvalue references and lvalue references to const have the ability in C++ + to extend the life time of a temporary they bind to. Optional references + do not have this capability, therefore to avoid surprising effects it is + not possible to initialize an optional references from a temporary. Optional + rvalue references are disabled altogether. Also, the initialization and + assignment of an optional reference to const from rvalue reference is disabled. +

    const int& i = 1;            // legal
     optional<const int&> oi = 1; // illegal
     
    +

    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/index.html b/doc/html/index.html index 15c6d1e..12d4f4d 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -62,8 +62,6 @@
    IO operators
    Optional references
    -
    Rebinding - semantics for assignment of optional references
    In-Place Factories
    A @@ -146,7 +144,7 @@ - +

    Last revised: February 16, 2016 at 22:59:47 GMT

    Last revised: February 18, 2016 at 23:24:54 GMT


    diff --git a/doc/html/optional/tutorial.html b/doc/html/optional/tutorial.html index 8e41ac8..556944d 100644 --- a/doc/html/optional/tutorial.html +++ b/doc/html/optional/tutorial.html @@ -36,8 +36,6 @@
    IO operators
    Optional references
    -
    Rebinding - semantics for assignment of optional references
    In-Place Factories
    A diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 0b08b84..eeabade 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -12,6 +12,11 @@ #ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP #define BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP +#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT +#include +#include +#endif + # if 1 namespace boost { @@ -39,6 +44,19 @@ BOOST_DEDUCED_TYPENAME boost::remove_reference::type& forward_reference(T&& r #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +template +void prevent_assignment_from_false_const_integral() +{ +#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES +#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), + "binding const lvalue references to integral types is disabled in this compiler"); +#endif +#endif +} + template struct is_optional_ { @@ -140,11 +158,15 @@ public: template 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 { ptr_ = boost::addressof(v); return *this; } - + 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 { ptr_ = boost::addressof(v); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 765fe53..e085c29 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -39,6 +39,7 @@ import testing ; [ run optional_test_emplace.cpp ] [ run optional_test_minimum_requirements.cpp ] [ run optional_test_msvc_bug_workaround.cpp ] + [ compile-fail optional_test_ref_convert_assign_const_int_prevented.cpp ] [ compile-fail optional_test_fail1.cpp ] [ compile-fail optional_test_fail3a.cpp ] [ compile-fail optional_test_fail3b.cpp ] diff --git a/test/optional_ref_assign_test_defs.hpp b/test/optional_ref_assign_test_defs.hpp index 292d0fc..1b2a1b0 100644 --- a/test/optional_ref_assign_test_defs.hpp +++ b/test/optional_ref_assign_test_defs.hpp @@ -163,26 +163,11 @@ void test_rebinding_assignment_semantics() BOOST_TEST_EQ(val(v), 2); } -template +template void test_converting_assignment() { typename concrete_type_of::type v1(1), v2(2), v3(3); - optional oA(v1), oB(none); - - oA = v2; - BOOST_TEST(oA); - BOOST_TEST(addressof(*oA) == addressof(v2)); - - oB = v3; - BOOST_TEST(oB); - BOOST_TEST(addressof(*oB) == addressof(v3)); -} - -template -void test_converting_assignment_for_noconst_const() -{ - typename concrete_type_of::type v1(1), v2(2), v3(3); - optional oA(v1), oB(none); + optional oA(v1), oB(none); oA = v2; BOOST_TEST(oA); @@ -194,4 +179,3 @@ void test_converting_assignment_for_noconst_const() } #endif //BOOST_OPTIONAL_TEST_OPTIONAL_REF_ASSIGN_TEST_DEFS_AK_07JAN2015_HPP - diff --git a/test/optional_test_ref_convert_assign_const_int.cpp b/test/optional_test_ref_convert_assign_const_int.cpp index 30d37a6..fb44aa1 100644 --- a/test/optional_test_ref_convert_assign_const_int.cpp +++ b/test/optional_test_ref_convert_assign_const_int.cpp @@ -23,8 +23,8 @@ int main() { - test_converting_assignment(); - test_converting_assignment_for_noconst_const(); - +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + test_converting_assignment(); +#endif return boost::report_errors(); } diff --git a/test/optional_test_ref_convert_assign_const_int_prevented.cpp b/test/optional_test_ref_convert_assign_const_int_prevented.cpp new file mode 100644 index 0000000..a08ca7a --- /dev/null +++ b/test/optional_test_ref_convert_assign_const_int_prevented.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2015 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/addressof.hpp" +#include "boost/core/enable_if.hpp" +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" +#include "optional_ref_assign_test_defs.hpp" + +int main() +{ +#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + test_converting_assignment(); +#else + BOOST_STATIC_ASSERT(false, "EXPECTED TEST COMPILE-TIME FAILURE"); +#endif + return boost::report_errors(); +} diff --git a/test/optional_test_ref_convert_assign_mutable_int.cpp b/test/optional_test_ref_convert_assign_mutable_int.cpp index 4338e52..56a6e80 100644 --- a/test/optional_test_ref_convert_assign_mutable_int.cpp +++ b/test/optional_test_ref_convert_assign_mutable_int.cpp @@ -23,7 +23,8 @@ int main() { - test_converting_assignment(); + test_converting_assignment(); + test_converting_assignment(); return boost::report_errors(); } diff --git a/test/optional_test_ref_convert_assign_non_int.cpp b/test/optional_test_ref_convert_assign_non_int.cpp index 556b757..80566b2 100644 --- a/test/optional_test_ref_convert_assign_non_int.cpp +++ b/test/optional_test_ref_convert_assign_non_int.cpp @@ -25,9 +25,9 @@ template void test_all_const_cases() { - test_converting_assignment(); - test_converting_assignment(); - test_converting_assignment_for_noconst_const(); + test_converting_assignment(); + test_converting_assignment(); + test_converting_assignment(); } int main() From 5ffa3fd2f6417d0e663e0179e675f2f8c639f3f9 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 19 Feb 2016 01:51:08 +0100 Subject: [PATCH 48/54] turned a complicatedcondition in enable_if into a metafun --- include/boost/optional/optional.hpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 10b46ef..3d89928 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -564,6 +565,19 @@ class optional_base : public optional_tag storage_type m_storage ; } ; + +template +struct is_optional_related + : boost::conditional::type>::value + || boost::is_same::type, none_t>::value, + boost::true_type, boost::false_type>::type +{}; + +template +struct is_optional_val_init_candidate + : boost::conditional::value, boost::true_type, boost::false_type>::type +{}; + } // namespace optional_detail template @@ -652,9 +666,7 @@ class optional : public optional_detail::optional_base template explicit optional ( Expr&& expr, - BOOST_DEDUCED_TYPENAME boost::disable_if_c< - (boost::is_base_of::type>::value) || - boost::is_same::type, none_t>::value >::type* = 0 + BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate >::type* = 0 ) : base(boost::forward(expr),boost::addressof(expr)) {} @@ -691,11 +703,7 @@ class optional : public optional_detail::optional_base #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES template - BOOST_DEDUCED_TYPENAME boost::disable_if_c< - boost::is_base_of::type>::value || - boost::is_same::type, none_t>::value, - optional& - >::type + BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type operator= ( Expr&& expr ) { this->assign_expr(boost::forward(expr),boost::addressof(expr)); From f6e09fbf9c0418364d88fcc15b2c5ccf95a489ef Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 19 Feb 2016 18:41:42 +0100 Subject: [PATCH 49/54] value constructor is sfinae-friendly --- doc/91_relnotes.qbk | 1 + doc/html/boost_optional/relnotes.html | 3 ++ doc/html/index.html | 2 +- include/boost/optional/optional.hpp | 35 ++++++++++++++--- test/Jamfile.v2 | 1 + ...tional_test_sfinae_friendly_value_ctor.cpp | 38 +++++++++++++++++++ 6 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 test/optional_test_sfinae_friendly_value_ctor.cpp diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index 4af88a5..ec6aaed 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -20,6 +20,7 @@ * you can swap optional references: it is like swapping pointers: shalow, underlying objects are not affected, * optional references to abstract types work. * Documented nested typedefs ([@https://svn.boost.org/trac/boost/ticket/5193 Trac #5193]). +* Made the optional value constructor SFINAE-friendly, which fixes [@https://svn.boost.org/trac/boost/ticket/12002 Trac #12002]. [heading Boost Release 1.60] diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html index 0f05f9e..b505936 100644 --- a/doc/html/boost_optional/relnotes.html +++ b/doc/html/boost_optional/relnotes.html @@ -60,6 +60,9 @@ Documented nested typedefs (Trac #5193). +
  • + Made the optional value constructor SFINAE-friendly, which fixes Trac #12002. +
  • diff --git a/doc/html/index.html b/doc/html/index.html index 12d4f4d..74917d5 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -144,7 +144,7 @@ - +

    Last revised: February 18, 2016 at 23:24:54 GMT

    Last revised: February 19, 2016 at 17:38:50 GMT


    diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 3d89928..af117bd 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -565,17 +566,39 @@ class optional_base : public optional_tag storage_type m_storage ; } ; - +// definition of metafunciton is_optional_val_init_candidate template struct is_optional_related - : boost::conditional::type>::value - || boost::is_same::type, none_t>::value, + : boost::conditional< boost::is_base_of::type>::value + || boost::is_same::type, none_t>::value, boost::true_type, boost::false_type>::type {}; - -template + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) + // this condition is a copy paste from is_constructible.hpp + +template +struct is_convertible_to_T_or_factory + : boost::conditional< boost::is_base_of::type>::value + || boost::is_base_of::type>::value + || boost::is_constructible::value + , boost::true_type, boost::false_type>::type +{}; + +#else + +#define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT + +template +struct is_convertible_to_T_or_factory : boost::true_type +{}; + +#endif // is_convertible condition + +template struct is_optional_val_init_candidate - : boost::conditional::value, boost::true_type, boost::false_type>::type + : boost::conditional< !is_optional_related::value && is_convertible_to_T_or_factory::value + , boost::true_type, boost::false_type>::type {}; } // namespace optional_detail diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e085c29..1800142 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -39,6 +39,7 @@ import testing ; [ run optional_test_emplace.cpp ] [ run optional_test_minimum_requirements.cpp ] [ run optional_test_msvc_bug_workaround.cpp ] + [ compile optional_test_sfinae_friendly_value_ctor.cpp ] [ compile-fail optional_test_ref_convert_assign_const_int_prevented.cpp ] [ compile-fail optional_test_fail1.cpp ] [ compile-fail optional_test_fail3a.cpp ] diff --git a/test/optional_test_sfinae_friendly_value_ctor.cpp b/test/optional_test_sfinae_friendly_value_ctor.cpp new file mode 100644 index 0000000..d7af15d --- /dev/null +++ b/test/optional_test_sfinae_friendly_value_ctor.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +using boost::optional; + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT) + +struct X {}; +struct Y {}; + +struct Resource +{ + explicit Resource(const X&) {} +}; + +BOOST_STATIC_ASSERT(( boost::is_constructible::value)); +BOOST_STATIC_ASSERT((!boost::is_constructible::value)); + +BOOST_STATIC_ASSERT(( boost::is_constructible, const X&>::value)); +BOOST_STATIC_ASSERT((!boost::is_constructible, const Y&>::value)); + +#endif + +int main() { } From 1334602a2b3460d0911be296be9176804c11d8b8 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Fri, 19 Feb 2016 18:48:37 +0100 Subject: [PATCH 50/54] minor release note change --- doc/91_relnotes.qbk | 2 +- doc/html/boost_optional/relnotes.html | 4 +++- doc/html/index.html | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index ec6aaed..074d3a8 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -20,7 +20,7 @@ * you can swap optional references: it is like swapping pointers: shalow, underlying objects are not affected, * optional references to abstract types work. * Documented nested typedefs ([@https://svn.boost.org/trac/boost/ticket/5193 Trac #5193]). -* Made the optional value constructor SFINAE-friendly, which fixes [@https://svn.boost.org/trac/boost/ticket/12002 Trac #12002]. +* Made the perfect-forwarding constructor SFINAE-friendly, which fixes [@https://svn.boost.org/trac/boost/ticket/12002 Trac #12002]. However, this only works in the newer compilers that implement variadic macros and `decltype` correctly. [heading Boost Release 1.60] diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html index b505936..50ddc8e 100644 --- a/doc/html/boost_optional/relnotes.html +++ b/doc/html/boost_optional/relnotes.html @@ -61,7 +61,9 @@ #5193).
  • - Made the optional value constructor SFINAE-friendly, which fixes Trac #12002. + Made the perfect-forwarding constructor SFINAE-friendly, which fixes Trac #12002. + However, this only works in the newer compilers that implement variadic + macros and decltype correctly.
  • diff --git a/doc/html/index.html b/doc/html/index.html index 74917d5..b3bf68a 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -144,7 +144,7 @@ - +

    Last revised: February 19, 2016 at 17:38:50 GMT

    Last revised: February 19, 2016 at 17:45:39 GMT


    From 3b58b0f4dabc87d5ef8cf71672223e8d24a21f06 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 20 Feb 2016 11:34:18 +0100 Subject: [PATCH 51/54] speculative fix for msvc 8.0 test failure --- include/boost/optional/optional.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index af117bd..5a3f284 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -560,7 +560,11 @@ class optional_base : public optional_tag private : +#if BOOST_WORKAROUND(BOOST_MSVC, < 1400) + void destroy_impl ( ) { boost::addressof(m_storage.ref())->~T() ; m_initialized = false ; } +#else void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; } +#endif bool m_initialized ; storage_type m_storage ; From c0084a04517014baffe5f568174b4f5ec4d2c1c4 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 20 Feb 2016 16:11:16 +0100 Subject: [PATCH 52/54] extended speculative fix to more MSVC compilers --- include/boost/optional/optional.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 5a3f284..5ead15f 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -560,7 +560,7 @@ class optional_base : public optional_tag private : -#if BOOST_WORKAROUND(BOOST_MSVC, < 1400) +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1600) void destroy_impl ( ) { boost::addressof(m_storage.ref())->~T() ; m_initialized = false ; } #else void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; } From 9118518516ef858def22318bc7e5360783ad76ee Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 20 Feb 2016 16:36:48 +0100 Subject: [PATCH 53/54] more extensive speculative fix --- .../optional/detail/optional_aligned_storage.hpp | 15 +++++++++------ include/boost/optional/optional.hpp | 6 +++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/boost/optional/detail/optional_aligned_storage.hpp b/include/boost/optional/detail/optional_aligned_storage.hpp index 35b3d12..6c7d581 100644 --- a/include/boost/optional/detail/optional_aligned_storage.hpp +++ b/include/boost/optional/detail/optional_aligned_storage.hpp @@ -49,21 +49,24 @@ class aligned_storage #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) // This workaround is supposed to silence GCC warnings about broken strict aliasing rules - T const& ref() const + T const* ptr_ref() const { union { void const* ap_pvoid; T const* as_ptype; } caster = { address() }; - return *caster.as_ptype; + return caster.as_ptype; } - T & ref() + T * ptr_ref() { union { void* ap_pvoid; T* as_ptype; } caster = { address() }; - return *caster.as_ptype; + return caster.as_ptype; } #else - T const& ref() const { return *static_cast(address()); } - T & ref() { return *static_cast (address()); } + T const* ptr_ref() const { return static_cast(address()); } + T * ptr_ref() { return static_cast (address()); } #endif + T const& ref() const { return *ptr_ref(); } + T & ref() { return *ptr_ref(); } + } ; } // namespace optional_detail diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 5ead15f..46717fe 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -555,13 +555,13 @@ class optional_base : public optional_tag reference_const_type get_impl() const { return m_storage.ref() ; } reference_type get_impl() { return m_storage.ref() ; } - pointer_const_type get_ptr_impl() const { return boost::addressof(m_storage.ref()); } - pointer_type get_ptr_impl() { return boost::addressof(m_storage.ref()); } + pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); } + pointer_type get_ptr_impl() { return m_storage.ptr_ref(); } private : #if BOOST_WORKAROUND(BOOST_MSVC, <= 1600) - void destroy_impl ( ) { boost::addressof(m_storage.ref())->~T() ; m_initialized = false ; } + void destroy_impl ( ) { m_storage.ptr_ref()->~T() ; m_initialized = false ; } #else void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; } #endif From d3dda39beb4355717a02d00f62fae2372da546ac Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 20 Feb 2016 21:18:47 +0100 Subject: [PATCH 54/54] removed 'exploration' test --- test/Jamfile.v2 | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1800142..20be6cf 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -68,6 +68,5 @@ import testing ; [ run-fail optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp ] [ run optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp ] [ compile-fail optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp ] - [ run optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp ] ; }