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]
This commit is contained in:
Andrey Semashev
2010-12-17 21:12:56 +00:00
parent 646488e0e2
commit e9989b260e

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