diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 95574ce..abdaf20 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -21,8 +21,10 @@ boostbook standalone : optional : - toc.max.depth=1 - toc.section.depth=1 + boost.root=../../../.. + boost.libraries=../../../libraries.htm + toc.max.depth=2 + toc.section.depth=2 chunk.section.depth=1 ; diff --git a/doc/html/boost_optional/a_note_about_optional_bool_.html b/doc/html/boost_optional/a_note_about_optional_bool_.html index 42d69df..5191d1d 100644 --- a/doc/html/boost_optional/a_note_about_optional_bool_.html +++ b/doc/html/boost_optional/a_note_about_optional_bool_.html @@ -12,17 +12,17 @@ Guarantees"> - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -74,11 +74,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/acknowledgments.html b/doc/html/boost_optional/acknowledgments.html index e2cc05a..09e3c71 100644 --- a/doc/html/boost_optional/acknowledgments.html +++ b/doc/html/boost_optional/acknowledgments.html @@ -10,24 +10,24 @@ and Portability"> - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHome +PrevUpHome

- + Pre-formal review

@@ -66,7 +66,7 @@

- + Post-formal review

@@ -112,11 +112,15 @@
- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHome +PrevUpHome
diff --git a/doc/html/boost_optional/dependencies_and_portability.html b/doc/html/boost_optional/dependencies_and_portability.html index ccc0d2c..35ecb80 100644 --- a/doc/html/boost_optional/dependencies_and_portability.html +++ b/doc/html/boost_optional/dependencies_and_portability.html @@ -11,17 +11,17 @@ - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -36,11 +36,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/detailed_semantics.html b/doc/html/boost_optional/detailed_semantics.html index bbebfd7..ef68023 100644 --- a/doc/html/boost_optional/detailed_semantics.html +++ b/doc/html/boost_optional/detailed_semantics.html @@ -10,17 +10,17 @@ - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -29,36 +29,42 @@

Because T might be of reference type, in the sequel, those entries whose semantic depends on T being of reference type or not will be - distinguished using the following convention: * If the entry reads: optional<T(not a ref)>, the description corresponds only to the - case where T is not of reference - type. * If the entry reads: optional<T&>, - the description corresponds only to the case where T - is of reference type. * If the entry reads: optional<T>, - the description is the same for both cases. + distinguished using the following convention:

+
    +
  • + If the entry reads: optional<T(not + a ref)>, the description + corresponds only to the case where T + is not of reference type. +
  • +
  • + If the entry reads: optional<T&>, + the description corresponds only to the case where T + is of reference type. +
  • +
  • + If the entry reads: optional<T>, + the description is the same for both cases. +
  • +
- + - +
[Note][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. -

-

-

-

+ 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 class member functions

@@ -1334,7 +1340,7 @@ space

- + Free functions

@@ -1693,11 +1699,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/development.html b/doc/html/boost_optional/development.html index c013432..8d58d8b 100644 --- a/doc/html/boost_optional/development.html +++ b/doc/html/boost_optional/development.html @@ -10,17 +10,17 @@ - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -292,7 +292,7 @@ itself which are supported by a special interface.

- + Lexically-hinted Value Access in the presence of possibly untitialized optional objects: The operators * and -> @@ -357,7 +357,7 @@ incarnated by pointers.

- + Optional<T> as a model of OptionalPointee
@@ -369,19 +369,12 @@

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

-

-

- However, it is particularly important to note that optional<> objects are not pointers. optional<> is not, and does not model, a - pointer. -

-

-

-

+ However, it is particularly important to note that optional<> objects are not pointers. optional<> is not, and does not model, a pointer. +

For instance, optional<> @@ -405,11 +398,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/examples.html b/doc/html/boost_optional/examples.html index 7fdb8c8..7685a73 100644 --- a/doc/html/boost_optional/examples.html +++ b/doc/html/boost_optional/examples.html @@ -10,17 +10,17 @@ - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -141,11 +141,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/exception_safety_guarantees.html b/doc/html/boost_optional/exception_safety_guarantees.html index 6b4ab64..8f6504f 100644 --- a/doc/html/boost_optional/exception_safety_guarantees.html +++ b/doc/html/boost_optional/exception_safety_guarantees.html @@ -12,17 +12,17 @@ - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -116,7 +116,7 @@ }

- + Swap

@@ -130,11 +130,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/implementation_notes.html b/doc/html/boost_optional/implementation_notes.html index 54af9ab..c0225b3 100644 --- a/doc/html/boost_optional/implementation_notes.html +++ b/doc/html/boost_optional/implementation_notes.html @@ -11,17 +11,17 @@ and Portability"> - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -42,11 +42,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/in_place_factories.html b/doc/html/boost_optional/in_place_factories.html index be2ccbf..a972384 100644 --- a/doc/html/boost_optional/in_place_factories.html +++ b/doc/html/boost_optional/in_place_factories.html @@ -12,17 +12,17 @@ optional<bool>"> - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -190,11 +190,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/optional_references.html b/doc/html/boost_optional/optional_references.html index 396dff0..1222a42 100644 --- a/doc/html/boost_optional/optional_references.html +++ b/doc/html/boost_optional/optional_references.html @@ -11,17 +11,17 @@ semantics for assignment of optional references"> - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -72,11 +72,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html b/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html index 8906812..5b894aa 100644 --- a/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html +++ b/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html @@ -11,17 +11,17 @@ - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -75,7 +75,7 @@ assert(b==3);

- + Rationale

@@ -141,11 +141,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/synopsis.html b/doc/html/boost_optional/synopsis.html index 198750e..c128fc6 100644 --- a/doc/html/boost_optional/synopsis.html +++ b/doc/html/boost_optional/synopsis.html @@ -10,17 +10,17 @@ - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -137,11 +137,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/type_requirements.html b/doc/html/boost_optional/type_requirements.html index 8da1a86..0676bf1 100644 --- a/doc/html/boost_optional/type_requirements.html +++ b/doc/html/boost_optional/type_requirements.html @@ -11,17 +11,17 @@ - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-PrevUpHomeNext +PrevUpHomeNext

@@ -40,11 +40,15 @@

- +
Copyright © 2003 -2007 Fernando Luis Cacciola Carballal

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boostbook.css b/doc/html/boostbook.css old mode 100755 new mode 100644 diff --git a/doc/html/index.html b/doc/html/index.html index 298875d..24277e1 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -8,16 +8,16 @@ - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+ + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore

-
Next
+
Next

@@ -27,7 +27,7 @@

- - + +

Last revised: May 29, 2007 at 06:31:03 GMT

Last revised: February 12, 2008 at 22:47:14 GMT


-
Next
+
Next
diff --git a/doc/optional.qbk b/doc/optional.qbk index 388f686..5217e49 100644 --- a/doc/optional.qbk +++ b/doc/optional.qbk @@ -22,7 +22,7 @@ Distributed under the Boost Software License, Version 1.0. [/ Cited Boost resources ] [def __BOOST_VARIANT__ [@../../../variant/index.html Boost.Variant]] -[def __BOOST_TRIBOOL__ [@../../../tribool/index.html boost::tribool]] +[def __BOOST_TRIBOOL__ [@../../../../doc/html/tribool.html boost::tribool]] [def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html OptionalPointee]] [def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html Copy Constructible]] @@ -40,11 +40,6 @@ Distributed under the Boost Software License, Version 1.0. [/ Icons ] -[def __NOTE__ [$images/note.png]] -[def __ALERT__ [$images/caution.png]] -[def __DETAIL__ [$images/note.png]] -[def __TIP__ [$images/tip.png]] -[def __QUESTION_MARK__ [$images/question.png]] [def __SPACE__ [$images/space.png]] [def __GO_TO__ [$images/callouts/R.png]] diff --git a/doc/reference.qbk b/doc/reference.qbk index 73993b3..c50b61a 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -126,6 +126,7 @@ Because `T` might be of reference type, in the sequel, those entries whose semantic depends on `T` being of reference type or not will be distinguished using the following convention: + * If the entry reads: `optional`, the description corresponds only to the case where `T` is not of reference type. * If the entry reads: `optional`, the description corresponds only to diff --git a/include/boost/none.hpp b/include/boost/none.hpp index b0e94a2..bd342da 100644 --- a/include/boost/none.hpp +++ b/include/boost/none.hpp @@ -4,7 +4,7 @@ // (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. +// See http://www.boost.org/libs/optional for documentation. // // You are welcome to contact the author at: // fernando_cacciola@hotmail.com diff --git a/include/boost/none_t.hpp b/include/boost/none_t.hpp index 4b97e20..63ad926 100644 --- a/include/boost/none_t.hpp +++ b/include/boost/none_t.hpp @@ -4,7 +4,7 @@ // 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. +// See http://www.boost.org/libs/optional for documentation. // // You are welcome to contact the author at: // fernando_cacciola@hotmail.com diff --git a/include/boost/optional.hpp b/include/boost/optional.hpp index bc5c5d3..40cf12e 100644 --- a/include/boost/optional.hpp +++ b/include/boost/optional.hpp @@ -4,7 +4,7 @@ // 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. +// See http://www.boost.org/libs/optional for documentation. // // You are welcome to contact the author at: // fernando_cacciola@hotmail.com diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 8a78a40..01db469 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. // // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -9,6 +9,9 @@ // You are welcome to contact the author at: // fernando_cacciola@hotmail.com // +// Revisions: +// 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen +// #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP @@ -19,6 +22,7 @@ #include "boost/assert.hpp" #include "boost/type.hpp" #include "boost/type_traits/alignment_of.hpp" +#include "boost/type_traits/has_nothrow_constructor.hpp" #include "boost/type_traits/type_with_alignment.hpp" #include "boost/type_traits/remove_reference.hpp" #include "boost/type_traits/is_reference.hpp" @@ -26,8 +30,9 @@ #include "boost/mpl/bool.hpp" #include "boost/mpl/not.hpp" #include "boost/detail/reference_content.hpp" -#include "boost/none_t.hpp" +#include "boost/none.hpp" #include "boost/utility/compare_pointees.hpp" +#include "boost/utility/in_place_factory.hpp" #include "boost/optional/optional_fwd.hpp" @@ -76,6 +81,19 @@ #define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION #endif +// 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 + void construct(Factory const& factory, void* address) + { + factory.BOOST_NESTED_TEMPLATE apply(address); + } +} + namespace boost { @@ -173,7 +191,7 @@ class optional_base : public optional_tag // Creates an optional uninitialized. // No-throw - optional_base ( none_t const& ) + optional_base ( none_t ) : m_initialized(false) {} @@ -266,7 +284,7 @@ class optional_base : public optional_tag // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED // No-throw (assuming T::~T() doesn't) - void assign ( none_t const& ) { destroy(); } + void assign ( none_t ) { destroy(); } #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT template @@ -309,7 +327,7 @@ class optional_base : public optional_tag void construct ( Expr const& factory, in_place_factory_base const* ) { BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ; - factory.BOOST_NESTED_TEMPLATE apply(m_storage.address()) ; + boost_optional_detail::construct(factory, m_storage.address()); m_initialized = true ; } @@ -428,6 +446,8 @@ class optional_base : public optional_tag // 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 ; @@ -459,7 +479,7 @@ class optional : public optional_detail::optional_base // Creates an optional uninitialized. // No-throw - optional( none_t const& none_ ) : base(none_) {} + optional( none_t none_ ) : base(none_) {} // Creates an optional initialized with 'val'. // Can throw if T::T(T const&) does @@ -501,7 +521,7 @@ class optional : public optional_detail::optional_base // Creates a deep copy of another optional // Can throw if T::T(T const&) does - optional ( optional const& rhs ) : base(rhs) {} + optional ( optional const& rhs ) : base( static_cast(rhs) ) {} // No-throw (assuming T::~T() doesn't) ~optional() {} @@ -535,7 +555,7 @@ class optional : public optional_detail::optional_base // (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( rhs ) ; + this->assign( static_cast(rhs) ) ; return *this ; } @@ -550,12 +570,20 @@ class optional : public optional_detail::optional_base // 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 const& none_ ) + optional& operator= ( none_t none_ ) { this->assign( none_ ) ; return *this ; } + void swap( optional & arg ) + { + // allow for Koenig lookup + using boost::swap ; + swap(*this, arg); + } + + // Returns a reference to the value if this is initialized, otherwise, // the behaviour is UNDEFINED // No-throw @@ -678,6 +706,11 @@ get_pointer ( optional& opt ) // 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 ) @@ -708,64 +741,141 @@ inline bool operator >= ( optional const& x, optional const& y ) { return !( x < y ) ; } + +// +// optional vs T cases +// template inline -bool operator == ( optional const& x, none_t const& ) +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 ) { return equal_pointees(x, optional() ); } template inline -bool operator < ( optional const& x, none_t const& ) +bool operator < ( optional const& x, none_t ) { return less_pointees(x,optional() ); } template inline -bool operator != ( optional const& x, none_t const& y ) +bool operator != ( optional const& x, none_t y ) { return !( x == y ) ; } template inline -bool operator > ( optional const& x, none_t const& y ) +bool operator > ( optional const& x, none_t y ) { return y < x ; } template inline -bool operator <= ( optional const& x, none_t const& y ) +bool operator <= ( optional const& x, none_t y ) { return !( y < x ) ; } template inline -bool operator >= ( optional const& x, none_t const& y ) +bool operator >= ( optional const& x, none_t y ) { return !( x < y ) ; } +// +// none vs optional cases +// + template inline -bool operator == ( none_t const& x, optional const& y ) +bool operator == ( none_t x, optional const& y ) { return equal_pointees(optional() ,y); } template inline -bool operator < ( none_t const& x, optional const& y ) +bool operator < ( none_t x, optional const& y ) { return less_pointees(optional() ,y); } template inline -bool operator != ( none_t const& x, optional const& y ) +bool operator != ( none_t x, optional const& y ) { return !( x == y ) ; } template inline -bool operator > ( none_t const& x, optional const& y ) +bool operator > ( none_t x, optional const& y ) { return y < x ; } template inline -bool operator <= ( none_t const& x, optional const& y ) +bool operator <= ( none_t x, optional const& y ) { return !( y < x ) ; } template inline -bool operator >= ( none_t const& x, optional const& y ) +bool operator >= ( none_t x, optional const& y ) { return !( x < y ) ; } // @@ -781,44 +891,77 @@ namespace optional_detail { #define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE #endif -// optional's swap: -// If both are initialized, calls swap(T&, T&). If this swap throws, both will remain initialized but their values are now unspecified. -// If only one is initialized, calls U.reset(*I), THEN I.reset(). -// If U.reset(*I) throws, both are left UNCHANGED (U is kept uinitialized and I is never reset) -// If both are uninitialized, do nothing (no-throw) -template -inline -void optional_swap ( optional& x, optional& y ) -{ - if ( !x && !!y ) + template struct swap_selector; + + template<> + struct swap_selector { - x.reset(*y); - y.reset(); - } - else if ( !!x && !y ) - { - y.reset(*x); - x.reset(); - } - else if ( !!x && !!y ) - { -// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC) + template + static void optional_swap ( optional& x, optional& y ) + { + bool hasX = x; + bool hasY = y; + + if ( !hasX && !hasY ) + return; + + if( !hasX ) + x = boost::in_place(); + else if ( !hasY ) + y = boost::in_place(); + + // GCC > 3.2 and all other compilers have the using declaration at function scope (FLC) #ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE - // allow for Koenig lookup - using std::swap ; + // allow for Koenig lookup + using std::swap ; #endif - swap(*x,*y); - } -} + swap(*x,*y); + + if( !hasX ) + y = boost::none ; + else if( !hasY ) + x = boost::none ; + } + }; + + template<> + struct swap_selector + { + template + static void optional_swap ( optional& x, optional& y ) + { + if ( !x && !!y ) + { + x = *y; + y = boost::none ; + } + else if ( !!x && !y ) + { + y = *x ; + x = boost::none ; + } + else if ( !!x && !!y ) + { + // GCC > 3.2 and all other compilers have the using declaration at function scope (FLC) + #ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE + // allow for Koenig lookup + using std::swap ; + #endif + swap(*x,*y); + } + } + }; } // namespace optional_detail +template +struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor {} ; + template inline void swap ( optional& x, optional& y ) { - optional_detail::optional_swap(x,y); + optional_detail::swap_selector::value>::optional_swap(x, y); } - } // namespace boost #endif diff --git a/include/boost/optional/optional_fwd.hpp b/include/boost/optional/optional_fwd.hpp index 2cf4fa6..a74fe10 100644 --- a/include/boost/optional/optional_fwd.hpp +++ b/include/boost/optional/optional_fwd.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. // // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -9,6 +9,9 @@ // You are welcome to contact the author at: // fernando_cacciola@hotmail.com // +// Revisions: +// 10 May 2008 (added swap related forward declaration) Niels Dekker +// #ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP #define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP @@ -16,6 +19,10 @@ namespace boost { template class optional ; +template void swap ( optional& , optional& ) ; + +template struct optional_swap_should_use_default_constructor ; + } // namespace boost #endif diff --git a/index.html b/index.html index ed59314..84b7c93 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,13 @@ - + Automatic redirection failed, please go to -doc/optional.html
-

© Copyright Beman Dawes, 2001

+doc/html/index.html
+

� Copyright Beman Dawes, 2001

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at www.boost.org/LICENSE_1_0.txt)

- \ No newline at end of file + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d20cd84..16d4f3c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -22,11 +22,9 @@ import testing ; [ run optional_test_inplace.cpp ] [ run optional_test_io.cpp ] [ compile-fail optional_test_fail1.cpp ] - [ compile-fail optional_test_fail2.cpp ] [ compile-fail optional_test_fail3a.cpp ] [ compile-fail optional_test_fail3b.cpp ] [ compile-fail optional_test_ref_fail1.cpp ] - [ compile-fail optional_test_ref_fail2.cpp ] [ compile-fail optional_test_ref_fail3.cpp ] [ compile-fail optional_test_ref_fail4.cpp ] [ compile-fail optional_test_inplace_fail.cpp ] diff --git a/test/optional_test.cpp b/test/optional_test.cpp index 5c10eed..e841194 100644 --- a/test/optional_test.cpp +++ b/test/optional_test.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. // // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -9,6 +9,9 @@ // You are welcome to contact the author at: // fernando_cacciola@hotmail.com // +// Revisions: +// 12 May 2008 (added more swap tests) +// #include #include #include @@ -16,6 +19,8 @@ #define BOOST_ENABLE_ASSERT_HANDLER #include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin +#include "boost/mpl/bool.hpp" +#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_ #include "boost/optional/optional.hpp" @@ -704,16 +709,16 @@ void test_relops( T const* ) { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); - T v0(18); - T v1(19); - T v2(19); + T v0(0); + T v1(1); + T v2(1); optional def0 ; optional def1 ; optional opt0(v0); optional opt1(v1); optional opt2(v2); - + // Check identity BOOST_CHECK ( def0 == def0 ) ; BOOST_CHECK ( opt0 == opt0 ) ; @@ -751,6 +756,33 @@ void test_relops( T const* ) BOOST_CHECK ( opt1 > opt0 ) ; BOOST_CHECK ( opt1 <= opt2 ) ; BOOST_CHECK ( 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 ) ; } template @@ -767,6 +799,10 @@ void test_none( T const* ) 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 ) ; non_def = none ; BOOST_CHECK ( !non_def ) ; @@ -774,6 +810,24 @@ void test_none( T const* ) test_default_implicit_construction(T(1),none); } +template +void test_arrow( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T a(1234); + + optional oa(a) ; + optional const coa(a) ; + + BOOST_CHECK ( coa->V() == 1234 ) ; + + oa->V() = 4321 ; + + BOOST_CHECK ( a.V() = 1234 ) ; + BOOST_CHECK ( (*oa).V() = 4321 ) ; +} + void test_with_builtin_types() { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); @@ -804,6 +858,7 @@ void test_with_class_type() test_throwing_swap( ARG(X) ); test_relops( ARG(X) ) ; test_none( ARG(X) ) ; + test_arrow( ARG(X) ) ; BOOST_CHECK ( X::count == 0 ) ; } @@ -877,6 +932,337 @@ void test_conversions2() BOOST_CHECK(*get(&opt1) == static_cast(f)); } + +namespace optional_swap_test +{ + class default_ctor_exception : public std::exception {} ; + class copy_ctor_exception : public std::exception {} ; + class assignment_exception : public std::exception {} ; + + // + // Base class for swap test classes. Its assignment should not be called, when swapping + // optional objects. (The default std::swap would do so.) + // + class base_class_with_forbidden_assignment + { + public: + base_class_with_forbidden_assignment & operator=(const base_class_with_forbidden_assignment &) + { + BOOST_CHECK(!"The assignment should not be used while swapping!"); + throw assignment_exception(); + } + + virtual ~base_class_with_forbidden_assignment() {} + }; + + // + // Class without default constructor + // + class class_without_default_ctor : public base_class_with_forbidden_assignment + { + public: + char data; + explicit class_without_default_ctor(char arg) : data(arg) {} + }; + + // + // Class whose default constructor should not be used by optional::swap! + // + class class_whose_default_ctor_should_not_be_used : public base_class_with_forbidden_assignment + { + public: + char data; + explicit class_whose_default_ctor_should_not_be_used(char arg) : data(arg) {} + + class_whose_default_ctor_should_not_be_used() + { + BOOST_CHECK(!"This default constructor should not be used while swapping!"); + throw default_ctor_exception(); + } + }; + + // + // Class whose default constructor should be used by optional::swap. + // Its copy constructor should be avoided! + // + class class_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment + { + public: + char data; + explicit class_whose_default_ctor_should_be_used(char arg) : data(arg) { } + + class_whose_default_ctor_should_be_used() : data('\0') { } + + class_whose_default_ctor_should_be_used(const class_whose_default_ctor_should_be_used &) + { + BOOST_CHECK(!"This copy constructor should not be used while swapping!"); + throw copy_ctor_exception(); + } + }; + + // + // Class template whose default constructor should be used by optional::swap. + // Its copy constructor should be avoided! + // + template + class template_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment + { + public: + T data; + explicit template_whose_default_ctor_should_be_used(T arg) : data(arg) { } + + template_whose_default_ctor_should_be_used() : data('\0') { } + + template_whose_default_ctor_should_be_used(const template_whose_default_ctor_should_be_used &) + { + BOOST_CHECK(!"This copy constructor should not be used while swapping!"); + throw copy_ctor_exception(); + } + }; + + // + // Class whose explicit constructor should be used by optional::swap. + // Its other constructors should be avoided! + // + class class_whose_explicit_ctor_should_be_used : public base_class_with_forbidden_assignment + { + public: + char data; + explicit class_whose_explicit_ctor_should_be_used(char arg) : data(arg) { } + + class_whose_explicit_ctor_should_be_used() + { + BOOST_CHECK(!"This default constructor should not be used while swapping!"); + throw default_ctor_exception(); + } + + class_whose_explicit_ctor_should_be_used(const class_whose_explicit_ctor_should_be_used &) + { + BOOST_CHECK(!"This copy constructor should not be used while swapping!"); + throw copy_ctor_exception(); + } + }; + + void swap(class_whose_default_ctor_should_not_be_used & lhs, class_whose_default_ctor_should_not_be_used & rhs) + { + std::swap(lhs.data, rhs.data); + } + + void swap(class_whose_default_ctor_should_be_used & lhs, class_whose_default_ctor_should_be_used & rhs) + { + std::swap(lhs.data, rhs.data); + } + + void swap(class_without_default_ctor & lhs, class_without_default_ctor & rhs) + { + std::swap(lhs.data, rhs.data); + } + + void swap(class_whose_explicit_ctor_should_be_used & lhs, class_whose_explicit_ctor_should_be_used & rhs) + { + std::swap(lhs.data, rhs.data); + } + + template + void swap(template_whose_default_ctor_should_be_used & lhs, template_whose_default_ctor_should_be_used & rhs) + { + std::swap(lhs.data, rhs.data); + } + + // + // optional::swap should be customized when neither the copy constructor + // nor the default constructor of T are supposed to be used when swapping, e.g., + // for the following type T = class_whose_explicit_ctor_should_be_used. + // + void swap(boost::optional & x, boost::optional & y) + { + bool hasX = x; + bool hasY = y; + + if ( !hasX && !hasY ) + return; + + if( !hasX ) + x = boost::in_place('\0'); + else if ( !hasY ) + y = boost::in_place('\0'); + + optional_swap_test::swap(*x,*y); + + if( !hasX ) + y = boost::none ; + else if( !hasY ) + x = boost::none ; + } + + +} // End of namespace optional_swap_test. + + +namespace boost { + +// +// Compile time tweaking on whether or not swap should use the default constructor: +// + +template <> struct optional_swap_should_use_default_constructor< + optional_swap_test::class_whose_default_ctor_should_be_used> : mpl::true_ {} ; + +template <> struct optional_swap_should_use_default_constructor< + optional_swap_test::class_whose_default_ctor_should_not_be_used> : mpl::false_ {} ; + +template struct optional_swap_should_use_default_constructor< + optional_swap_test::template_whose_default_ctor_should_be_used > : mpl::true_ {} ; + + +// +// Specialization of boost::swap: +// +template <> +void swap(optional & x, optional & y) +{ + optional_swap_test::swap(x, y); +} + +} // namespace boost + + +namespace std { + +// +// Specializations of std::swap: +// + +template <> +void swap(optional_swap_test::class_whose_default_ctor_should_be_used & x, optional_swap_test::class_whose_default_ctor_should_be_used & y) +{ + optional_swap_test::swap(x, y); +} + +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) +{ + 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) +{ + optional_swap_test::swap(x, y); +} + +template <> +void swap(optional_swap_test::class_whose_explicit_ctor_should_be_used & x, optional_swap_test::class_whose_explicit_ctor_should_be_used & y) +{ + optional_swap_test::swap(x, y); +} + +} // namespace std + + +// +// Tests whether the swap function works properly for optional. +// Assumes that T has one data member, of type char. +// Returns true iff the test is passed. +// +template +bool test_swap_function( T const* ) +{ + const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter(); + try + { + optional obj1; + optional obj2('a'); + + // Self-swap should not have any effect. + swap(obj1, obj1); + swap(obj2, obj2); + BOOST_CHECK(!obj1); + BOOST_CHECK(!!obj2 && obj2->data == 'a'); + + // Call non-member swap. + swap(obj1, obj2); + + // Test if obj1 and obj2 are really swapped. + BOOST_CHECK(!!obj1 && obj1->data == 'a'); + BOOST_CHECK(!obj2); + + // Call non-member swap one more time. + swap(obj1, obj2); + + // Test if obj1 and obj2 are swapped back. + BOOST_CHECK(!obj1); + BOOST_CHECK(!!obj2 && obj2->data == 'a'); + } + catch(const std::exception &) + { + // The swap function should not throw, for our test cases. + return false ; + } + return boost::minimal_test::errors_counter() == counter_before_test ; +} + +// +// Tests whether the optional::swap member function works properly. +// Assumes that T has one data member, of type char. +// Returns true iff the test is passed. +// +template +bool test_swap_member_function( T const* ) +{ + const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter(); + try + { + optional obj1; + optional obj2('a'); + + // Self-swap should not have any effect. + obj1.swap(obj1); + obj2.swap(obj2); + BOOST_CHECK(!obj1); + BOOST_CHECK(!!obj2 && obj2->data == 'a'); + + // Call member swap. + obj1.swap(obj2); + + // Test if obj1 and obj2 are really swapped. + BOOST_CHECK(!!obj1 && obj1->data == 'a'); + BOOST_CHECK(!obj2); + + // Call member swap one more time. + obj1.swap(obj2); + + // Test if obj1 and obj2 are swapped back. + BOOST_CHECK(!obj1); + BOOST_CHECK(!!obj2 && obj2->data == 'a'); + } + catch(const std::exception &) + { + // The optional::swap member function should not throw, for our test cases. + return false ; + } + return boost::minimal_test::errors_counter() == counter_before_test ; +} + + +// +// Tests compile time tweaking of swap, by means of +// optional_swap_should_use_default_constructor. +// +void test_swap_tweaking() +{ + BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_without_default_ctor) ) ); + BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) ); + BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) ); + BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) ); + BOOST_CHECK( test_swap_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used) ) ); + BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_without_default_ctor) ) ); + BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) ); + BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) ); + BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) ); + BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used) ) ); +} + int test_main( int, char* [] ) { try @@ -886,6 +1272,7 @@ int test_main( int, char* [] ) test_no_implicit_conversions(); test_conversions1(); test_conversions2(); + test_swap_tweaking(); } catch ( ... ) { diff --git a/test/optional_test_ref.cpp b/test/optional_test_ref.cpp index 1ccaeb4..08ee87e 100644 --- a/test/optional_test_ref.cpp +++ b/test/optional_test_ref.cpp @@ -299,6 +299,23 @@ void test_none( T const* ) BOOST_CHECK ( !non_def ) ; } +template +void test_arrow( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T a(1234); + + optional oa(a) ; + optional const coa(a) ; + + BOOST_CHECK ( coa->V() == 1234 ) ; + + oa->V() = 4321 ; + + BOOST_CHECK ( a.V() = 4321 ) ; +} + void test_with_builtin_types() { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); @@ -315,16 +332,35 @@ void test_with_class_type() test_basics( ARG(X) ); test_relops( ARG(X) ) ; test_none ( ARG(X) ) ; + test_arrow ( ARG(X) ) ; BOOST_CHECK ( X::count == 0 ) ; } +void test_binding() +{ + int i = 0 ; + optional ori1 = i ; + BOOST_CHECK( &(*ori1) == &i ) ; + + optional ori2(i) ; + BOOST_CHECK( &(*ori2) == &i ) ; + + int const ci = 0 ; + optional orci1 = ci ; + BOOST_CHECK( &(*orci1) == &ci ) ; + + optional orci2(ci) ; + BOOST_CHECK( &(*orci2) == &ci ) ; +} + int test_main( int, char* [] ) { try { test_with_class_type(); test_with_builtin_types(); + test_binding(); } catch ( ... ) {