$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r67183 - in branches/release: boost/optional libs/optional/test
From: andrey.semashev_at_[hidden]
Date: 2010-12-12 06:34:14
Author: andysem
Date: 2010-12-12 06:34:12 EST (Sun, 12 Dec 2010)
New Revision: 67183
URL: http://svn.boost.org/trac/boost/changeset/67183
Log:
Merged changes from trunk. Fixes #3395. Also updates swap behavior: if default constructor has no-throw guarantee, swap will use it to provide no-throw guarantee itself. operator>> behavior changed slightly so that the stream is not accessed when unrecognized character sequence is detected. The stream is marked with failbit in such a case.
Text files modified: 
   branches/release/boost/optional/optional.hpp             |   178 +++++++++++----                         
   branches/release/boost/optional/optional_io.hpp          |    32 ++                                      
   branches/release/libs/optional/test/optional_test.cpp    |   433 ++++++++++++++++++++++++++++++++++++--- 
   branches/release/libs/optional/test/optional_test_io.cpp |     9                                         
   4 files changed, 557 insertions(+), 95 deletions(-)
Modified: branches/release/boost/optional/optional.hpp
==============================================================================
--- branches/release/boost/optional/optional.hpp	(original)
+++ branches/release/boost/optional/optional.hpp	2010-12-12 06:34:12 EST (Sun, 12 Dec 2010)
@@ -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,16 +9,20 @@
 // You are welcome to contact the author at:
 //  fernando_cacciola_at_[hidden]
 //
+// 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
 
-#include<new>
-#include<algorithm>
+#include <new>
+#include <algorithm>
 
 #include "boost/config.hpp"
 #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"
@@ -27,7 +31,9 @@
 #include "boost/mpl/not.hpp"
 #include "boost/detail/reference_content.hpp"
 #include "boost/none.hpp"
+#include "boost/utility/addressof.hpp"
 #include "boost/utility/compare_pointees.hpp"
+#include "boost/utility/in_place_factory.hpp"
 
 #include "boost/optional/optional_fwd.hpp"
 
@@ -76,6 +82,15 @@
 #define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
 #endif
 
+#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 302 \
+    && !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
+
 // 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
@@ -105,7 +120,12 @@
 class aligned_storage
 {
     // Borland ICEs if unnamed unions are used for this!
-    union dummy_u
+    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<
@@ -114,8 +134,13 @@
 
   public:
 
-    void const* address() const { return &dummy_.data[0]; }
-    void      * address()       { return &dummy_.data[0]; }
+#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<class T>
@@ -149,7 +174,7 @@
     typedef
 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
     BOOST_DEDUCED_TYPENAME
-#endif 
+#endif
     ::boost::detail::make_reference_content<T>::type internal_type ;
 
     typedef aligned_storage<internal_type> storage_type ;
@@ -200,7 +225,7 @@
     {
       construct(val);
     }
-    
+
     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
     // Can throw if T::T(T const&) does
     optional_base ( bool cond, argument_type val )
@@ -421,8 +446,22 @@
   private :
 
     // internal_type can be either T or reference_content<T>
+#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<internal_type const*>(m_storage.address()); }
     internal_type *      get_object()       { return static_cast<internal_type *>     (m_storage.address()); }
+#endif
 
     // reference_content<T> 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 ; }
@@ -513,12 +552,12 @@
     // Depending on the above some T ctor is called.
     // Can throw is the resolved T ctor throws.
     template<class Expr>
-    explicit optional ( Expr const& expr ) : base(expr,&expr) {}
+    explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
 #endif
 
     // Creates a deep copy of another optional<T>
     // Can throw if T::T(T const&) does
-    optional ( optional const& rhs ) : base(rhs) {}
+    optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
 
    // No-throw (assuming T::~T() doesn't)
     ~optional() {}
@@ -527,9 +566,9 @@
     // Assigns from an expression. See corresponding constructor.
     // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
     template<class Expr>
-    optional& operator= ( Expr expr )
+    optional& operator= ( Expr const& expr )
       {
-        this->assign_expr(expr,&expr);
+        this->assign_expr(expr,boost::addressof(expr));
         return *this ;
       }
 #endif
@@ -552,7 +591,7 @@
     //  (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<base const&>(rhs) ) ;
         return *this ;
       }
 
@@ -573,6 +612,14 @@
         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
@@ -582,7 +629,7 @@
     // 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
@@ -599,22 +646,22 @@
     // No-throw
     operator unspecified_bool_type() const { return this->safe_bool() ; }
 
-       // This is provided for those compilers which don't like the conversion to bool
-       // on some contexts.
-       bool operator!() const { return !this->is_initialized() ; }
+    // This is provided for those compilers which don't like the conversion to bool
+    // on some contexts.
+    bool operator!() const { return !this->is_initialized() ; }
 } ;
 
 // Returns optional<T>(v)
-template<class T> 
-inline 
+template<class T>
+inline
 optional<T> make_optional ( T const& v  )
 {
   return optional<T>(v);
 }
 
 // Returns optional<T>(cond,v)
-template<class T> 
-inline 
+template<class T>
+inline
 optional<T> make_optional ( bool cond, T const& v )
 {
   return optional<T>(cond,v);
@@ -880,44 +927,77 @@
 #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<class T>
-inline
-void optional_swap ( optional<T>& x, optional<T>& y )
-{
-  if ( !x && !!y )
-  {
-    x.reset(*y);
-    y.reset();
-  }
-  else if ( !!x && !y )
-  {
-    y.reset(*x);
-    x.reset();
-  }
-  else if ( !!x && !!y )
+  template<bool use_default_constructor> struct swap_selector;
+
+  template<>
+  struct swap_selector<true>
   {
-// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
+    template<class T>
+    static void optional_swap ( optional<T>& x, optional<T>& 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<false>
+  {
+    template<class T>
+    static void optional_swap ( optional<T>& x, optional<T>& 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<class T>
+struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
+
 template<class T> inline void swap ( optional<T>& x, optional<T>& y )
 {
-  optional_detail::optional_swap(x,y);
+  optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
 }
 
-
 } // namespace boost
 
 #endif
Modified: branches/release/boost/optional/optional_io.hpp
==============================================================================
--- branches/release/boost/optional/optional_io.hpp	(original)
+++ branches/release/boost/optional/optional_io.hpp	2010-12-12 06:34:12 EST (Sun, 12 Dec 2010)
@@ -13,19 +13,20 @@
 #define BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP
 
 #if defined __GNUC__
-#  if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97) 
+#  if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97)
 #    define BOOST_OPTIONAL_NO_TEMPLATED_STREAMS
 #  endif
 #endif // __GNUC__
 
 #if defined BOOST_OPTIONAL_NO_TEMPLATED_STREAMS
 #  include <iostream>
-#else 
+#else
 #  include <istream>
 #  include <ostream>
-#endif  
-
+#endif
 
+#include <boost/none.hpp>
+#include <boost/assert.hpp>
 #include "boost/optional/optional.hpp"
 #include "boost/utility/value_init.hpp"
 
@@ -62,17 +63,30 @@
 operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v)
 #endif
 {
-  if ( in.good() )
+  if (in.good())
   {
     int d = in.get();
-    if ( d == ' ' )
+    if (d == ' ')
     {
-      T x ;
+      T x;
       in >> x;
-      v = x ;
+      v = x;
     }
     else
-      v = optional<T>() ;
+    {
+      if (d == '-')
+      {
+        d = in.get();
+
+        if (d == '-')
+        {
+          v = none;
+          return in;
+        }
+      }
+
+      in.setstate( std::ios::failbit );
+    }
   }
 
   return in;
Modified: branches/release/libs/optional/test/optional_test.cpp
==============================================================================
--- branches/release/libs/optional/test/optional_test.cpp	(original)
+++ branches/release/libs/optional/test/optional_test.cpp	2010-12-12 06:34:12 EST (Sun, 12 Dec 2010)
@@ -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_at_[hidden]
 //
+// Revisions:
+// 12 May 2008 (added more swap tests)
+//
 #include<iostream>
 #include<stdexcept>
 #include<string>
@@ -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"
 
@@ -153,27 +158,27 @@
   ob.reset();
   check_is_pending_dtor( ARG(T) ) ;
   check_uninitialized(ob);
-  
+
 }
 
 template<class T>
 void test_conditional_ctor_and_get_valur_or ( T const* )
 {
   TRACE( std::endl << BOOST_CURRENT_FUNCTION  );
-  
+
   T a(321);
-  
+
   T z(123);
-  
+
   optional<T> const cdef0(false,a);
-  
+
   optional<T> def0(false,a);
   optional<T> def1 = boost::make_optional(false,a); //  T is not within boost so ADL won't find make_optional unqualified
   check_uninitialized(def0);
   check_uninitialized(def1);
 
   optional<T> const co0(true,a);
-  
+
   optional<T> o0(true,a);
   optional<T> o1 = boost::make_optional(true,a); //  T is not within boost so ADL won't find make_optional unqualified
 
@@ -181,65 +186,65 @@
   check_initialized(o1);
   check_value(o0,a,z);
   check_value(o1,a,z);
-  
+
   T b = def0.get_value_or(z);
   BOOST_CHECK( b == z ) ;
-  
+
   b = get_optional_value_or(def0,z);
   BOOST_CHECK( b == z ) ;
-  
+
   b = o0.get_value_or(z);
   BOOST_CHECK( b == a ) ;
 
   b = get_optional_value_or(o0,z);
   BOOST_CHECK( b == a ) ;
-  
-  
+
+
   T const& crz = z ;
   T&        rz = z ;
-  
+
   T const& crzz = def0.get_value_or(crz);
   BOOST_CHECK( crzz == crz ) ;
-  
+
   T& rzz = def0.get_value_or(rz);
   BOOST_CHECK( rzz == rz ) ;
-  
+
   T const& crzzz = get_optional_value_or(cdef0,crz);
   BOOST_CHECK( crzzz == crz ) ;
-  
+
   T& rzzz = get_optional_value_or(def0,rz);
   BOOST_CHECK( rzzz == rz ) ;
-  
+
   T const& crb = o0.get_value_or(crz);
   BOOST_CHECK( crb == a ) ;
-  
+
   T& rb = o0.get_value_or(rz);
   BOOST_CHECK( rb == b ) ;
-  
+
   T const& crbb = get_optional_value_or(co0,crz);
   BOOST_CHECK( crbb == b ) ;
-  
+
   T const& crbbb = get_optional_value_or(o0,crz);
   BOOST_CHECK( crbbb == b ) ;
-  
+
   T& rbb = get_optional_value_or(o0,rz);
   BOOST_CHECK( rbb == b ) ;
-  
+
   T& ra = a ;
-  
+
   optional<T&> defref(false,ra);
   BOOST_CHECK(!defref);
-  
+
   optional<T&> ref(true,ra);
   BOOST_CHECK(!!ref);
-  
+
   a = T(432);
-  
+
   BOOST_CHECK( *ref == a ) ;
-  
+
   T& r1 = defref.get_value_or(z);
   BOOST_CHECK( r1 == z ) ;
-  
+
   T& r2 = ref.get_value_or(z);
   BOOST_CHECK( r2 == a ) ;
 }
@@ -713,7 +718,7 @@
   optional<T> opt0(v0);
   optional<T> opt1(v1);
   optional<T> opt2(v2);
-  
+
   // Check identity
   BOOST_CHECK ( def0 == def0 ) ;
   BOOST_CHECK ( opt0 == opt0 ) ;
@@ -751,7 +756,7 @@
   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 ) ;
@@ -794,7 +799,7 @@
   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_CHECK (   non_def >= none  ) ;
@@ -814,11 +819,11 @@
 
   optional<T>        oa(a) ;
   optional<T> const coa(a) ;
-  
+
   BOOST_CHECK ( coa->V() == 1234 ) ;
-  
+
   oa->V() = 4321 ;
-  
+
   BOOST_CHECK (     a.V() = 1234 ) ;
   BOOST_CHECK ( (*oa).V() = 4321 ) ;
 }
@@ -927,6 +932,364 @@
   BOOST_CHECK(*get(&opt1) == static_cast<double>(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<T> 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 T>
+  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 <class T>
+  void swap(template_whose_default_ctor_should_be_used<T> & lhs, template_whose_default_ctor_should_be_used<T> & rhs)
+  {
+    std::swap(lhs.data, rhs.data);
+  }
+
+  //
+  // optional<T>::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<class_whose_explicit_ctor_should_be_used> & x, boost::optional<class_whose_explicit_ctor_should_be_used> & 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 <class T> struct optional_swap_should_use_default_constructor<
+  optional_swap_test::template_whose_default_ctor_should_be_used<T> > : mpl::true_ {} ;
+
+
+//
+// Specialization of boost::swap:
+//
+template <>
+void swap(optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & x, optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & 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<T>.
+// Assumes that T has one data member, of type char.
+// Returns true iff the test is passed.
+//
+template <class T>
+bool test_swap_function( T const* )
+{
+  const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter();
+  try
+  {
+    optional<T> obj1;
+    optional<T> 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<T>::swap member function works properly.
+// Assumes that T has one data member, of type char.
+// Returns true iff the test is passed.
+//
+template <class T>
+bool test_swap_member_function( T const* )
+{
+  const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter();
+  try
+  {
+    optional<T> obj1;
+    optional<T> 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<T>::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<char>) ) );
+  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<char>) ) );
+}
+
+// Test for support for classes with overridden operator&
+class CustomAddressOfClass
+{
+    int n;
+
+public:
+    CustomAddressOfClass() : n(0) {}
+    CustomAddressOfClass(CustomAddressOfClass const& that) : n(that.n) {}
+    explicit CustomAddressOfClass(int m) : n(m) {}
+    int* operator& () { return &n; }
+    bool operator== (CustomAddressOfClass const& that) const { return n == that.n; }
+};
+
+void test_custom_addressof_operator()
+{
+    boost::optional< CustomAddressOfClass > o1(CustomAddressOfClass(10));
+    BOOST_CHECK(!!o1);
+    BOOST_CHECK(o1.get() == CustomAddressOfClass(10));
+
+    o1 = CustomAddressOfClass(20);
+    BOOST_CHECK(!!o1);
+    BOOST_CHECK(o1.get() == CustomAddressOfClass(20));
+
+    o1 = boost::none;
+    BOOST_CHECK(!o1);
+}
+
 int test_main( int, char* [] )
 {
   try
@@ -936,6 +1299,8 @@
     test_no_implicit_conversions();
     test_conversions1();
     test_conversions2();
+    test_swap_tweaking();
+    test_custom_addressof_operator();
   }
   catch ( ... )
   {
Modified: branches/release/libs/optional/test/optional_test_io.cpp
==============================================================================
--- branches/release/libs/optional/test/optional_test_io.cpp	(original)
+++ branches/release/libs/optional/test/optional_test_io.cpp	2010-12-12 06:34:12 EST (Sun, 12 Dec 2010)
@@ -55,10 +55,14 @@
 {
   stringstream s ;
 
-  s << o ;
-  s >> buff ;
+  const int markv = 123 ;
+  int mark = 0 ;
+  
+  s << o << " " << markv ;
+  s >> buff >> mark ;
 
   BOOST_ASSERT( buff == o ) ;
+  BOOST_ASSERT( mark == markv ) ;
 }
 
 
@@ -77,7 +81,6 @@
   {
     test(1,2);
     test(string("hello"),string("buffer"));
-    test(string(""),string("buffer"));
   }
   catch ( ... )
   {