]> git.donarmstrong.com Git - rsem.git/blobdiff - boost/optional/optional.hpp
Updated boost to v1.55.0
[rsem.git] / boost / optional / optional.hpp
index 88041d1441ddf0a5d6e3b0a8779a2b4e77ab099a..0d6dba405dc59152a589e7a2280b46e6dbe4243f 100644 (file)
@@ -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,27 +9,34 @@
 // 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
 
-#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/type_with_alignment.hpp"
-#include "boost/type_traits/remove_reference.hpp"
-#include "boost/type_traits/is_reference.hpp"
-#include "boost/mpl/if.hpp"
-#include "boost/mpl/bool.hpp"
-#include "boost/mpl/not.hpp"
-#include "boost/detail/reference_content.hpp"
-#include "boost/none.hpp"
-#include "boost/utility/compare_pointees.hpp"
-
-#include "boost/optional/optional_fwd.hpp"
+#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>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/detail/reference_content.hpp>
+#include <boost/none.hpp>
+#include <boost/utility/swap.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>
 
 #if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
 // VC6.0 has the following bug:
 #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
@@ -83,7 +99,7 @@
 namespace boost_optional_detail
 {
   template <class T, class Factory>
-  void construct(Factory const& factory, void* address)
+  inline void construct(Factory const& factory, void* address)
   {
     factory.BOOST_NESTED_TEMPLATE apply<T>(address);
   }
@@ -95,6 +111,9 @@ 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<class T> void swap ( optional<T>& x, optional<T>& y );
+
 namespace optional_detail {
 
 // This local class is used instead of that in "aligned_storage.hpp"
@@ -105,7 +124,12 @@ template <class T>
 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 +138,13 @@ class aligned_storage
 
   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 +178,7 @@ class optional_base : public optional_tag
     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 +229,7 @@ class optional_base : public optional_tag
     {
       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 +450,22 @@ class optional_base : public optional_tag
   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 +556,12 @@ class optional : public optional_detail::optional_base<T>
     // 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 +570,9 @@ class optional : public optional_detail::optional_base<T>
     // 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 +595,7 @@ class optional : public optional_detail::optional_base<T>
     //  (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 +616,14 @@ class optional : public optional_detail::optional_base<T>
         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 +633,7 @@ class optional : public optional_detail::optional_base<T>
     // 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 +650,22 @@ class optional : public optional_detail::optional_base<T>
     // 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);
@@ -839,12 +890,12 @@ bool operator >= ( optional<T> const& x, none_t y )
 
 template<class T>
 inline
-bool operator == ( none_t x, optional<T> const& y )
+bool operator == ( none_t , optional<T> const& y )
 { return equal_pointees(optional<T>() ,y); }
 
 template<class T>
 inline
-bool operator < ( none_t x, optional<T> const& y )
+bool operator < ( none_t , optional<T> const& y )
 { return less_pointees(optional<T>() ,y); }
 
 template<class T>
@@ -867,58 +918,74 @@ inline
 bool operator >= ( none_t x, optional<T> const& y )
 { return !( x < y ) ; }
 
-//
-// The following swap implementation follows the GCC workaround as found in
-//  "boost/detail/compressed_pair.hpp"
-//
 namespace optional_detail {
 
-// GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA)
-#if BOOST_WORKAROUND(__GNUC__, < 3)                             \
-    || BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ <= 2
-   using std::swap;
-#define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
-#endif
+template<bool use_default_constructor> struct swap_selector;
 
-// 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 )
+template<>
+struct swap_selector<true>
 {
-  if ( !x && !!y )
-  {
-    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)
-#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
-    // allow for Koenig lookup
-    using std::swap ;
-#endif
-    swap(*x,*y);
-  }
-}
+    template<class T>
+    static void optional_swap ( optional<T>& x, optional<T>& y )
+    {
+        const bool hasX = !!x;
+        const bool hasY = !!y;
+
+        if ( !hasX && !hasY )
+            return;
+
+        if( !hasX )
+            x = boost::in_place();
+        else if ( !hasY )
+            y = boost::in_place();
+
+        // 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 ;
+    }
+};
+
+template<>
+struct swap_selector<false>
+{
+    template<class T>
+    static void optional_swap ( optional<T>& x, optional<T>& 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());
+        }
+    }
+};
 
 } // 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
-