/* Copyright 2005-2007 Adobe Systems Incorporated Use, modification and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). */ /*************************************************************************************************/ #ifndef BOOST_UNORDERED_DETAIL_MOVE_HEADER #define BOOST_UNORDERED_DETAIL_MOVE_HEADER #include #include #include #include #include #include #include #include #include #include /*************************************************************************************************/ #if defined(BOOST_NO_SFINAE) # define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN #elif defined(__GNUC__) && \ (__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3) # define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN #elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \ BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \ BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593)) # define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN #endif /*************************************************************************************************/ namespace boost { namespace unordered_detail { /*************************************************************************************************/ namespace move_detail { /*************************************************************************************************/ #if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN) /*************************************************************************************************/ template struct class_has_move_assign { class type { typedef T& (T::*E)(T t); typedef char (&no_type)[1]; typedef char (&yes_type)[2]; template struct sfinae { typedef yes_type type; }; template static typename sfinae<&U::operator=>::type test(int); template static no_type test(...); public: enum {value = sizeof(test(1)) == sizeof(yes_type)}; }; }; /*************************************************************************************************/ template struct has_move_assign : boost::mpl::and_, class_has_move_assign > {}; /*************************************************************************************************/ class test_can_convert_anything { }; /*************************************************************************************************/ #endif // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN /*************************************************************************************************/ /* REVISIT (sparent@adobe.com): This is a work around for Boost 1.34.1 and VC++ 2008 where boost::is_convertible fails to compile. */ template struct is_convertible : boost::mpl::or_< boost::is_same, boost::is_convertible > { }; /*************************************************************************************************/ } //namespace move_detail /*************************************************************************************************/ /*! \ingroup move_related \brief move_from is used for move_ctors. */ template struct move_from { explicit move_from(T& x) : source(x) { } T& source; private: move_from& operator=(move_from const&); }; /*************************************************************************************************/ #if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN) /*************************************************************************************************/ /*! \ingroup move_related \brief The is_movable trait can be used to identify movable types. */ template struct is_movable : boost::mpl::and_< boost::is_convertible, T>, move_detail::has_move_assign, boost::mpl::not_ > > { }; /*************************************************************************************************/ #else // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN // On compilers which don't have adequate SFINAE support, treat most types as unmovable, // unless the trait is specialized. template struct is_movable : boost::mpl::false_ { }; #endif /*************************************************************************************************/ #if !defined(BOOST_NO_SFINAE) /*************************************************************************************************/ /*! \ingroup move_related \brief copy_sink and move_sink are used to select between overloaded operations according to whether type T is movable and convertible to type U. \sa move */ template struct copy_sink : boost::enable_if< boost::mpl::and_< boost::unordered_detail::move_detail::is_convertible, boost::mpl::not_ > >, R > { }; /*************************************************************************************************/ /*! \ingroup move_related \brief move_sink and copy_sink are used to select between overloaded operations according to whether type T is movable and convertible to type U. \sa move */ template struct move_sink : boost::enable_if< boost::mpl::and_< boost::unordered_detail::move_detail::is_convertible, is_movable >, R > { }; /*************************************************************************************************/ /*! \ingroup move_related \brief This version of move is selected when T is_movable . It in turn calls the move constructor. This call, with the help of the return value optimization, will cause x to be moved instead of copied to its destination. See adobe/test/move/main.cpp for examples. */ template T move(T& x, typename move_sink::type = 0) { return T(move_from(x)); } /*************************************************************************************************/ /*! \ingroup move_related \brief This version of move is selected when T is not movable . The net result will be that x gets copied. */ template T& move(T& x, typename copy_sink::type = 0) { return x; } /*************************************************************************************************/ #else // BOOST_NO_SFINAE // On compilers without SFINAE, define copy_sink to always use the copy function. template struct copy_sink { typedef R type; }; // Always copy the element unless this is overloaded. template T& move(T& x) { return x; } #endif // BOOST_NO_SFINAE } // namespace unordered_detail } // namespace boost /*************************************************************************************************/ #endif /*************************************************************************************************/