From e9989b260e0e4acd02a839ac95904746fe9922d2 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Fri, 17 Dec 2010 21:12:56 +0000 Subject: [PATCH] Refs #4987. Added forward declaration of namespace-scope swap for boost::optional, this should fix GCC compilation errors. Also swap implementation now uses Boost.Utility.Swap to make use of the workarounds for some broken compilers. If it breaks for your compiler, let me know in the mentioned ticket. [SVN r67288] --- include/boost/optional/optional.hpp | 143 +++++++++++++--------------- 1 file changed, 65 insertions(+), 78 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 2b066e9..ec9006e 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -18,24 +18,25 @@ #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/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/addressof.hpp" -#include "boost/utility/compare_pointees.hpp" -#include "boost/utility/in_place_factory.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "boost/optional/optional_fwd.hpp" +#include #if BOOST_WORKAROUND(BOOST_MSVC, == 1200) // VC6.0 has the following bug: @@ -98,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); } @@ -110,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" @@ -615,7 +619,7 @@ class optional : public optional_detail::optional_base void swap( optional & arg ) { // allow for Koenig lookup - using boost::swap ; + using boost::swap; swap(*this, arg); } @@ -914,79 +918,63 @@ 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; - template struct swap_selector; - - template<> - struct swap_selector - { +template<> +struct swap_selector +{ template static void optional_swap ( optional& x, optional& y ) { - bool hasX = x; - bool hasY = y; + const bool hasX = !!x; + const bool hasY = !!y; - if ( !hasX && !hasY ) - return; + if ( !hasX && !hasY ) + return; - if( !hasX ) - x = boost::in_place(); - else if ( !hasY ) - y = boost::in_place(); + 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 ; -#endif - swap(*x,*y); + // 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 ; + if( !hasX ) + y = boost::none ; + else if( !hasY ) + x = boost::none ; } - }; +}; - template<> - struct swap_selector - { +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); - } + 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 @@ -995,10 +983,9 @@ struct optional_swap_should_use_default_constructor : has_nothrow_default_constr template inline void swap ( optional& x, optional& y ) { - optional_detail::swap_selector::value>::optional_swap(x, y); + optional_detail::swap_selector::value>::optional_swap(x, y); } } // namespace boost #endif -