Merged changes from trunk: add namespace scope swap forward declaration to fix member swap copmilation. Swap implementation now uses Boost.Utility.Swap. Fixes #4987.

[SVN r67307]
This commit is contained in:
Andrey Semashev
2010-12-18 21:29:39 +00:00
parent ef2d285d47
commit 545f8933bc

View File

@ -18,24 +18,25 @@
#include <new> #include <new>
#include <algorithm> #include <algorithm>
#include "boost/config.hpp" #include <boost/config.hpp>
#include "boost/assert.hpp" #include <boost/assert.hpp>
#include "boost/type.hpp" #include <boost/type.hpp>
#include "boost/type_traits/alignment_of.hpp" #include <boost/type_traits/alignment_of.hpp>
#include "boost/type_traits/has_nothrow_constructor.hpp" #include <boost/type_traits/has_nothrow_constructor.hpp>
#include "boost/type_traits/type_with_alignment.hpp" #include <boost/type_traits/type_with_alignment.hpp>
#include "boost/type_traits/remove_reference.hpp" #include <boost/type_traits/remove_reference.hpp>
#include "boost/type_traits/is_reference.hpp" #include <boost/type_traits/is_reference.hpp>
#include "boost/mpl/if.hpp" #include <boost/mpl/if.hpp>
#include "boost/mpl/bool.hpp" #include <boost/mpl/bool.hpp>
#include "boost/mpl/not.hpp" #include <boost/mpl/not.hpp>
#include "boost/detail/reference_content.hpp" #include <boost/detail/reference_content.hpp>
#include "boost/none.hpp" #include <boost/none.hpp>
#include "boost/utility/addressof.hpp" #include <boost/utility/swap.hpp>
#include "boost/utility/compare_pointees.hpp" #include <boost/utility/addressof.hpp>
#include "boost/utility/in_place_factory.hpp" #include <boost/utility/compare_pointees.hpp>
#include <boost/utility/in_place_factory.hpp>
#include "boost/optional/optional_fwd.hpp" #include <boost/optional/optional_fwd.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) #if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
// VC6.0 has the following bug: // VC6.0 has the following bug:
@ -98,7 +99,7 @@
namespace boost_optional_detail namespace boost_optional_detail
{ {
template <class T, class Factory> 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); factory.BOOST_NESTED_TEMPLATE apply<T>(address);
} }
@ -110,6 +111,9 @@ namespace boost {
class in_place_factory_base ; class in_place_factory_base ;
class typed_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 { namespace optional_detail {
// This local class is used instead of that in "aligned_storage.hpp" // This local class is used instead of that in "aligned_storage.hpp"
@ -615,7 +619,7 @@ class optional : public optional_detail::optional_base<T>
void swap( optional & arg ) void swap( optional & arg )
{ {
// allow for Koenig lookup // allow for Koenig lookup
using boost::swap ; using boost::swap;
swap(*this, arg); swap(*this, arg);
} }
@ -914,79 +918,63 @@ inline
bool operator >= ( none_t x, optional<T> const& y ) bool operator >= ( none_t x, optional<T> const& y )
{ return !( x < y ) ; } { return !( x < y ) ; }
//
// The following swap implementation follows the GCC workaround as found in
// "boost/detail/compressed_pair.hpp"
//
namespace optional_detail { namespace optional_detail {
// GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA) template<bool use_default_constructor> struct swap_selector;
#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; template<>
struct swap_selector<true>
template<> {
struct swap_selector<true>
{
template<class T> template<class T>
static void optional_swap ( optional<T>& x, optional<T>& y ) static void optional_swap ( optional<T>& x, optional<T>& y )
{ {
bool hasX = x; const bool hasX = !!x;
bool hasY = y; const bool hasY = !!y;
if ( !hasX && !hasY ) if ( !hasX && !hasY )
return; return;
if( !hasX ) if( !hasX )
x = boost::in_place(); x = boost::in_place();
else if ( !hasY ) else if ( !hasY )
y = boost::in_place(); y = boost::in_place();
// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC) // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE boost::swap(x.get(),y.get());
// allow for Koenig lookup
using std::swap ;
#endif
swap(*x,*y);
if( !hasX ) if( !hasX )
y = boost::none ; y = boost::none ;
else if( !hasY ) else if( !hasY )
x = boost::none ; x = boost::none ;
} }
}; };
template<> template<>
struct swap_selector<false> struct swap_selector<false>
{ {
template<class T> template<class T>
static void optional_swap ( optional<T>& x, optional<T>& y ) static void optional_swap ( optional<T>& x, optional<T>& y )
{ {
if ( !x && !!y ) const bool hasX = !!x;
{ const bool hasY = !!y;
x = *y;
y = boost::none ; if ( !hasX && hasY )
} {
else if ( !!x && !y ) x = y.get();
{ y = boost::none ;
y = *x ; }
x = boost::none ; else if ( hasX && !hasY )
} {
else if ( !!x && !!y ) y = x.get();
{ x = boost::none ;
// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC) }
#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE else if ( hasX && hasY )
// allow for Koenig lookup {
using std::swap ; // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
#endif boost::swap(x.get(),y.get());
swap(*x,*y); }
}
} }
}; };
} // namespace optional_detail } // namespace optional_detail
@ -995,10 +983,9 @@ struct optional_swap_should_use_default_constructor : has_nothrow_default_constr
template<class T> inline void swap ( optional<T>& x, optional<T>& y ) template<class T> inline void swap ( optional<T>& x, optional<T>& y )
{ {
optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y); optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
} }
} // namespace boost } // namespace boost
#endif #endif