X-Git-Url: https://git.donarmstrong.com/?p=rsem.git;a=blobdiff_plain;f=boost%2Foptional%2Foptional.hpp;h=0d6dba405dc59152a589e7a2280b46e6dbe4243f;hp=88041d1441ddf0a5d6e3b0a8779a2b4e77ab099a;hb=2d71eb92104693ca9baa5a2e1c23eeca776d8fd3;hpb=a95154919f950f86de9104b2b9dcf1f0c7e83387 diff --git a/boost/optional/optional.hpp b/boost/optional/optional.hpp index 88041d1..0d6dba4 100644 --- a/boost/optional/optional.hpp +++ b/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,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 -#include - -#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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #if BOOST_WORKAROUND(BOOST_MSVC, == 1200) // VC6.0 has the following bug: @@ -76,6 +83,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 @@ -83,7 +99,7 @@ namespace boost_optional_detail { template - void construct(Factory const& factory, void* address) + inline void construct(Factory const& factory, void* address) { factory.BOOST_NESTED_TEMPLATE apply(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 void swap ( optional& x, optional& y ); + namespace optional_detail { // This local class is used instead of that in "aligned_storage.hpp" @@ -105,7 +124,12 @@ template 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 @@ -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::type internal_type ; typedef aligned_storage storage_type ; @@ -200,7 +229,7 @@ class optional_base : public optional_tag { construct(val); } - + // 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 ) @@ -421,8 +450,22 @@ class optional_base : public optional_tag 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 ; } @@ -513,12 +556,12 @@ class optional : public optional_detail::optional_base // Depending on the above some T ctor is called. // Can throw is the resolved T ctor throws. template - 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 // 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() {} @@ -527,9 +570,9 @@ class optional : public optional_detail::optional_base // Assigns from an expression. See corresponding constructor. // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED template - 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 // (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 ; } @@ -573,6 +616,14 @@ class optional : public optional_detail::optional_base 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 // 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 // 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(v) -template -inline +template +inline optional make_optional ( T const& v ) { return optional(v); } // Returns optional(cond,v) -template -inline +template +inline optional make_optional ( bool cond, T const& v ) { return optional(cond,v); @@ -839,12 +890,12 @@ bool operator >= ( optional const& x, none_t y ) template inline -bool operator == ( none_t x, optional const& y ) +bool operator == ( none_t , optional const& y ) { return equal_pointees(optional() ,y); } template inline -bool operator < ( none_t x, optional const& y ) +bool operator < ( none_t , optional const& y ) { return less_pointees(optional() ,y); } template @@ -867,58 +918,74 @@ inline bool operator >= ( none_t x, optional 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 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 -inline -void optional_swap ( optional& x, optional& y ) +template<> +struct swap_selector { - 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 + static void optional_swap ( optional& x, optional& 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 +{ + 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()); + } + } +}; } // 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 -