[44] | 1 | /* |
---|
| 2 | Copyright 2005-2007 Adobe Systems Incorporated |
---|
| 3 | |
---|
| 4 | Use, modification and distribution are subject to the Boost Software License, |
---|
| 5 | Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
| 6 | http://www.boost.org/LICENSE_1_0.txt). |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | /*************************************************************************************************/ |
---|
| 10 | |
---|
| 11 | #ifndef BOOST_UNORDERED_DETAIL_MOVE_HEADER |
---|
| 12 | #define BOOST_UNORDERED_DETAIL_MOVE_HEADER |
---|
| 13 | |
---|
| 14 | #include <boost/config.hpp> |
---|
| 15 | #include <boost/mpl/bool.hpp> |
---|
| 16 | #include <boost/mpl/and.hpp> |
---|
| 17 | #include <boost/mpl/or.hpp> |
---|
| 18 | #include <boost/mpl/not.hpp> |
---|
| 19 | #include <boost/type_traits/is_convertible.hpp> |
---|
| 20 | #include <boost/type_traits/is_same.hpp> |
---|
| 21 | #include <boost/type_traits/is_class.hpp> |
---|
| 22 | #include <boost/utility/enable_if.hpp> |
---|
| 23 | #include <boost/detail/workaround.hpp> |
---|
| 24 | |
---|
| 25 | /*************************************************************************************************/ |
---|
| 26 | |
---|
| 27 | #if defined(BOOST_NO_SFINAE) |
---|
| 28 | # define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN |
---|
| 29 | #elif defined(__GNUC__) && \ |
---|
| 30 | (__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ <= 3) |
---|
| 31 | # define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN |
---|
| 32 | #elif BOOST_WORKAROUND(BOOST_INTEL, < 900) || \ |
---|
| 33 | BOOST_WORKAROUND(__EDG_VERSION__, < 304) || \ |
---|
| 34 | BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0593)) |
---|
| 35 | # define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN |
---|
| 36 | #endif |
---|
| 37 | |
---|
| 38 | /*************************************************************************************************/ |
---|
| 39 | |
---|
| 40 | namespace boost { |
---|
| 41 | namespace unordered_detail { |
---|
| 42 | |
---|
| 43 | /*************************************************************************************************/ |
---|
| 44 | |
---|
| 45 | namespace move_detail { |
---|
| 46 | |
---|
| 47 | /*************************************************************************************************/ |
---|
| 48 | |
---|
| 49 | #if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN) |
---|
| 50 | |
---|
| 51 | /*************************************************************************************************/ |
---|
| 52 | |
---|
| 53 | template <typename T> |
---|
| 54 | struct class_has_move_assign { |
---|
| 55 | class type { |
---|
| 56 | typedef T& (T::*E)(T t); |
---|
| 57 | typedef char (&no_type)[1]; |
---|
| 58 | typedef char (&yes_type)[2]; |
---|
| 59 | template <E e> struct sfinae { typedef yes_type type; }; |
---|
| 60 | template <class U> |
---|
| 61 | static typename sfinae<&U::operator=>::type test(int); |
---|
| 62 | template <class U> |
---|
| 63 | static no_type test(...); |
---|
| 64 | public: |
---|
| 65 | enum {value = sizeof(test<T>(1)) == sizeof(yes_type)}; |
---|
| 66 | }; |
---|
| 67 | }; |
---|
| 68 | |
---|
| 69 | /*************************************************************************************************/ |
---|
| 70 | |
---|
| 71 | template<typename T> |
---|
| 72 | struct has_move_assign : boost::mpl::and_<boost::is_class<T>, class_has_move_assign<T> > {}; |
---|
| 73 | |
---|
| 74 | /*************************************************************************************************/ |
---|
| 75 | |
---|
| 76 | class test_can_convert_anything { }; |
---|
| 77 | |
---|
| 78 | /*************************************************************************************************/ |
---|
| 79 | |
---|
| 80 | #endif // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN |
---|
| 81 | |
---|
| 82 | /*************************************************************************************************/ |
---|
| 83 | |
---|
| 84 | /* |
---|
| 85 | REVISIT (sparent@adobe.com): This is a work around for Boost 1.34.1 and VC++ 2008 where |
---|
| 86 | boost::is_convertible<T, T> fails to compile. |
---|
| 87 | */ |
---|
| 88 | |
---|
| 89 | template <typename T, typename U> |
---|
| 90 | struct is_convertible : boost::mpl::or_< |
---|
| 91 | boost::is_same<T, U>, |
---|
| 92 | boost::is_convertible<T, U> |
---|
| 93 | > { }; |
---|
| 94 | |
---|
| 95 | /*************************************************************************************************/ |
---|
| 96 | |
---|
| 97 | } //namespace move_detail |
---|
| 98 | |
---|
| 99 | |
---|
| 100 | /*************************************************************************************************/ |
---|
| 101 | |
---|
| 102 | /*! |
---|
| 103 | \ingroup move_related |
---|
| 104 | \brief move_from is used for move_ctors. |
---|
| 105 | */ |
---|
| 106 | |
---|
| 107 | template <typename T> |
---|
| 108 | struct move_from |
---|
| 109 | { |
---|
| 110 | explicit move_from(T& x) : source(x) { } |
---|
| 111 | T& source; |
---|
| 112 | private: |
---|
| 113 | move_from& operator=(move_from const&); |
---|
| 114 | }; |
---|
| 115 | |
---|
| 116 | /*************************************************************************************************/ |
---|
| 117 | |
---|
| 118 | #if !defined(BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN) |
---|
| 119 | |
---|
| 120 | /*************************************************************************************************/ |
---|
| 121 | |
---|
| 122 | /*! |
---|
| 123 | \ingroup move_related |
---|
| 124 | \brief The is_movable trait can be used to identify movable types. |
---|
| 125 | */ |
---|
| 126 | template <typename T> |
---|
| 127 | struct is_movable : boost::mpl::and_< |
---|
| 128 | boost::is_convertible<move_from<T>, T>, |
---|
| 129 | move_detail::has_move_assign<T>, |
---|
| 130 | boost::mpl::not_<boost::is_convertible<move_detail::test_can_convert_anything, T> > |
---|
| 131 | > { }; |
---|
| 132 | |
---|
| 133 | /*************************************************************************************************/ |
---|
| 134 | |
---|
| 135 | #else // BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN |
---|
| 136 | |
---|
| 137 | // On compilers which don't have adequate SFINAE support, treat most types as unmovable, |
---|
| 138 | // unless the trait is specialized. |
---|
| 139 | |
---|
| 140 | template <typename T> |
---|
| 141 | struct is_movable : boost::mpl::false_ { }; |
---|
| 142 | |
---|
| 143 | #endif |
---|
| 144 | |
---|
| 145 | /*************************************************************************************************/ |
---|
| 146 | |
---|
| 147 | #if !defined(BOOST_NO_SFINAE) |
---|
| 148 | |
---|
| 149 | /*************************************************************************************************/ |
---|
| 150 | |
---|
| 151 | /*! |
---|
| 152 | \ingroup move_related |
---|
| 153 | \brief copy_sink and move_sink are used to select between overloaded operations according to |
---|
| 154 | whether type T is movable and convertible to type U. |
---|
| 155 | \sa move |
---|
| 156 | */ |
---|
| 157 | |
---|
| 158 | template <typename T, |
---|
| 159 | typename U = T, |
---|
| 160 | typename R = void*> |
---|
| 161 | struct copy_sink : boost::enable_if< |
---|
| 162 | boost::mpl::and_< |
---|
| 163 | boost::unordered_detail::move_detail::is_convertible<T, U>, |
---|
| 164 | boost::mpl::not_<is_movable<T> > |
---|
| 165 | >, |
---|
| 166 | R |
---|
| 167 | > |
---|
| 168 | { }; |
---|
| 169 | |
---|
| 170 | /*************************************************************************************************/ |
---|
| 171 | |
---|
| 172 | /*! |
---|
| 173 | \ingroup move_related |
---|
| 174 | \brief move_sink and copy_sink are used to select between overloaded operations according to |
---|
| 175 | whether type T is movable and convertible to type U. |
---|
| 176 | \sa move |
---|
| 177 | */ |
---|
| 178 | |
---|
| 179 | template <typename T, |
---|
| 180 | typename U = T, |
---|
| 181 | typename R = void*> |
---|
| 182 | struct move_sink : boost::enable_if< |
---|
| 183 | boost::mpl::and_< |
---|
| 184 | boost::unordered_detail::move_detail::is_convertible<T, U>, |
---|
| 185 | is_movable<T> |
---|
| 186 | >, |
---|
| 187 | R |
---|
| 188 | > |
---|
| 189 | { }; |
---|
| 190 | |
---|
| 191 | /*************************************************************************************************/ |
---|
| 192 | |
---|
| 193 | /*! |
---|
| 194 | \ingroup move_related |
---|
| 195 | \brief This version of move is selected when T is_movable . It in turn calls the move |
---|
| 196 | constructor. This call, with the help of the return value optimization, will cause x to be moved |
---|
| 197 | instead of copied to its destination. See adobe/test/move/main.cpp for examples. |
---|
| 198 | |
---|
| 199 | */ |
---|
| 200 | template <typename T> |
---|
| 201 | T move(T& x, typename move_sink<T>::type = 0) { return T(move_from<T>(x)); } |
---|
| 202 | |
---|
| 203 | /*************************************************************************************************/ |
---|
| 204 | |
---|
| 205 | /*! |
---|
| 206 | \ingroup move_related |
---|
| 207 | \brief This version of move is selected when T is not movable . The net result will be that |
---|
| 208 | x gets copied. |
---|
| 209 | */ |
---|
| 210 | template <typename T> |
---|
| 211 | T& move(T& x, typename copy_sink<T>::type = 0) { return x; } |
---|
| 212 | |
---|
| 213 | /*************************************************************************************************/ |
---|
| 214 | |
---|
| 215 | #else // BOOST_NO_SFINAE |
---|
| 216 | |
---|
| 217 | // On compilers without SFINAE, define copy_sink to always use the copy function. |
---|
| 218 | |
---|
| 219 | template <typename T, |
---|
| 220 | typename U = T, |
---|
| 221 | typename R = void*> |
---|
| 222 | struct copy_sink |
---|
| 223 | { |
---|
| 224 | typedef R type; |
---|
| 225 | }; |
---|
| 226 | |
---|
| 227 | // Always copy the element unless this is overloaded. |
---|
| 228 | |
---|
| 229 | template <typename T> |
---|
| 230 | T& move(T& x) { |
---|
| 231 | return x; |
---|
| 232 | } |
---|
| 233 | |
---|
| 234 | #endif // BOOST_NO_SFINAE |
---|
| 235 | |
---|
| 236 | } // namespace unordered_detail |
---|
| 237 | } // namespace boost |
---|
| 238 | |
---|
| 239 | /*************************************************************************************************/ |
---|
| 240 | |
---|
| 241 | #endif |
---|
| 242 | |
---|
| 243 | /*************************************************************************************************/ |
---|