1 ////////////////////////////////////////////////////////////////////////////// 2 // (C) Copyright John Maddock 2000. 3 // (C) Copyright Ion Gaztanaga 2005-2015. 4 // 5 // Distributed under the Boost Software License, Version 1.0. 6 // (See accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // See http://www.boost.org/libs/move for documentation. 10 // 11 // The alignment and Type traits implementation comes from 12 // John Maddock's TypeTraits library. 13 // 14 // Some other tricks come from Howard Hinnant's papers and StackOverflow replies 15 ////////////////////////////////////////////////////////////////////////////// 16 #ifndef BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP 17 #define BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP 18 19 #ifndef BOOST_CONFIG_HPP 20 # include <boost/config.hpp> 21 #endif 22 # 23 #if defined(BOOST_HAS_PRAGMA_ONCE) 24 # pragma once 25 #endif 26 27 #include <boost/move/detail/config_begin.hpp> 28 #include <boost/move/detail/workaround.hpp> 29 30 // move/detail 31 #include <boost/move/detail/meta_utils.hpp> 32 // other 33 #include <boost/assert.hpp> 34 #include <boost/static_assert.hpp> 35 // std 36 #include <cstddef> 37 38 //Use of Boost.TypeTraits leads to long preprocessed source code due to 39 //MPL dependencies. We'll use intrinsics directly and make or own 40 //simplified version of TypeTraits. 41 //If someday Boost.TypeTraits dependencies are minimized, we should 42 //revisit this file redirecting code to Boost.TypeTraits traits. 43 44 //These traits don't care about volatile, reference or other checks 45 //made by Boost.TypeTraits because no volatile or reference types 46 //can be hold in Boost.Containers. This helps to avoid any Boost.TypeTraits 47 //dependency. 48 49 // Helper macros for builtin compiler support. 50 // If your compiler has builtin support for any of the following 51 // traits concepts, then redefine the appropriate macros to pick 52 // up on the compiler support: 53 // 54 // (these should largely ignore cv-qualifiers) 55 // BOOST_MOVE_IS_POD(T) should evaluate to true if T is a POD type 56 // BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect 57 // BOOST_MOVE_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy 58 // (Note: this trait does not guarantee T is copy constructible, the copy constructor could be deleted but still be trivial) 59 // BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) should evaluate to true if T(boost::move(t)) <==> memcpy 60 // BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy 61 // (Note: this trait does not guarantee T is assignable , the copy assignmen could be deleted but still be trivial) 62 // BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) should evaluate to true if t = boost::move(u) <==> memcpy 63 // BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect 64 // BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) should evaluate to true if "T x;" can not throw 65 // BOOST_MOVE_HAS_NOTHROW_COPY(T) should evaluate to true if T(t) can not throw 66 // BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) should evaluate to true if t = u can not throw 67 // BOOST_MOVE_IS_ENUM(T) should evaluate to true it t is a union type. 68 // BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) should evaluate to true if T has a non-throwing move constructor. 69 // BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) should evaluate to true if T has a non-throwing move assignment operator. 70 // 71 // The following can also be defined: when detected our implementation is greatly simplified. 72 // 73 // BOOST_ALIGNMENT_OF(T) should evaluate to the alignment requirements of type T. 74 75 #if defined(__MSL_CPP__) && (__MSL_CPP__ >= 0x8000) 76 // Metrowerks compiler is acquiring intrinsic type traits support 77 // post version 8. We hook into the published interface to pick up 78 // user defined specializations as well as compiler intrinsics as 79 // and when they become available: 80 # include <msl_utility> 81 # define BOOST_MOVE_IS_UNION(T) BOOST_STD_EXTENSION_NAMESPACE::is_union<T>::value 82 # define BOOST_MOVE_IS_POD(T) BOOST_STD_EXTENSION_NAMESPACE::is_POD<T>::value 83 # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_default_ctor<T>::value 84 # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_copy_ctor<T>::value 85 # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_assignment<T>::value 86 # define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_dtor<T>::value 87 #endif 88 89 #if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\ 90 || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500)) 91 # define BOOST_MOVE_IS_UNION(T) __is_union(T) 92 # define BOOST_MOVE_IS_POD(T) (__is_pod(T) && __has_trivial_constructor(T)) 93 # define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) 94 # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T) 95 # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T)|| ::boost::move_detail::is_pod<T>::value) 96 # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) || ::boost::move_detail::is_pod<T>::value) 97 # define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) || ::boost::move_detail::is_pod<T>::value) 98 # define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) || ::boost::move_detail::is_trivially_default_constructible<T>::value) 99 # define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T) || ::boost::move_detail::is_trivially_copy_constructible<T>::value) 100 # define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T) || ::boost::move_detail::is_trivially_copy_assignable<T>::value) 101 102 # define BOOST_MOVE_IS_ENUM(T) __is_enum(T) 103 # if defined(_MSC_VER) && (_MSC_VER >= 1700) 104 # define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__has_trivial_move_constructor(T) || ::boost::move_detail::is_pod<T>::value) 105 # define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) (__has_trivial_move_assign(T) || ::boost::move_detail::is_pod<T>::value) 106 # endif 107 # if _MSC_FULL_VER >= 180020827 108 # define BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) (__is_nothrow_assignable(T&, T&&)) 109 # define BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) (__is_nothrow_constructible(T, T&&)) 110 # endif 111 #endif 112 113 #if defined(BOOST_CLANG) 114 // BOOST_MOVE_HAS_TRAIT 115 # if defined __is_identifier 116 # define BOOST_MOVE_HAS_TRAIT(T) (__has_extension(T) || !__is_identifier(__##T)) 117 # elif defined(__has_extension) 118 # define BOOST_MOVE_HAS_TRAIT(T) __has_extension(T) 119 # else 120 # define BOOST_MOVE_HAS_TRAIT(T) 0 121 # endif 122 123 // BOOST_MOVE_IS_UNION 124 # if BOOST_MOVE_HAS_TRAIT(is_union) 125 # define BOOST_MOVE_IS_UNION(T) __is_union(T) 126 # endif 127 128 // BOOST_MOVE_IS_ENUM 129 # if BOOST_MOVE_HAS_TRAIT(is_enum) 130 # define BOOST_MOVE_IS_ENUM(T) __is_enum(T) 131 # endif 132 133 // BOOST_MOVE_IS_POD 134 # if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && BOOST_MOVE_HAS_TRAIT(is_pod) 135 # define BOOST_MOVE_IS_POD(T) __is_pod(T) 136 # endif 137 138 // BOOST_MOVE_IS_EMPTY 139 # if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && BOOST_MOVE_HAS_TRAIT(is_empty) 140 # define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) 141 # endif 142 143 // BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR 144 # if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_trivially_constructible) 145 # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __is_trivially_constructible(T) 146 # elif BOOST_MOVE_HAS_TRAIT(has_trivial_constructor) 147 # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T) 148 # endif 149 150 // BOOST_MOVE_HAS_TRIVIAL_COPY 151 # if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_trivially_constructible) 152 # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__is_constructible(T, const T &) && __is_trivially_constructible(T, const T &)) 153 # elif BOOST_MOVE_HAS_TRAIT(has_trivial_copy) 154 # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) __has_trivial_copy(T) 155 # endif 156 157 // BOOST_MOVE_HAS_TRIVIAL_ASSIGN 158 # if BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_trivially_assignable) 159 # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__is_assignable(T, const T &) && __is_trivially_assignable(T, const T &)) 160 # elif BOOST_MOVE_HAS_TRAIT(has_trivial_copy) 161 # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) __has_trivial_assign(T) 162 # endif 163 164 // BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR 165 # if BOOST_MOVE_HAS_TRAIT(is_trivially_destructible) 166 # define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __is_trivially_destructible(T) 167 # elif BOOST_MOVE_HAS_TRAIT(has_trivial_destructor) 168 # define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) 169 # endif 170 171 // BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR 172 # if BOOST_MOVE_HAS_TRAIT(is_nothrow_constructible) 173 # define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __is_nothrow_constructible(T) 174 # elif BOOST_MOVE_HAS_TRAIT(has_nothrow_constructor) 175 # define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T) 176 # endif 177 178 // BOOST_MOVE_HAS_NOTHROW_COPY 179 # if BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_nothrow_constructible) 180 # define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__is_constructible(T, const T &) && __is_nothrow_constructible(T, const T &)) 181 # elif BOOST_MOVE_HAS_TRAIT(has_nothrow_copy) 182 # define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T)) 183 # endif 184 185 // BOOST_MOVE_HAS_NOTHROW_ASSIGN 186 # if BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_nothrow_assignable) 187 # define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__is_assignable(T, const T &) && __is_nothrow_assignable(T, const T &)) 188 # elif BOOST_MOVE_HAS_TRAIT(has_nothrow_assign) 189 # define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T)) 190 # endif 191 192 // BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR 193 # if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_trivially_constructible) 194 # define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__is_constructible(T, T&&) && __is_trivially_constructible(T, T&&)) 195 # elif BOOST_MOVE_HAS_TRAIT(has_trivial_move_constructor) 196 # define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) __has_trivial_move_constructor(T) 197 # endif 198 199 // BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN 200 # if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_trivially_assignable) 201 # define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) (__is_assignable(T, T&&) && __is_trivially_assignable(T, T&&)) 202 # elif BOOST_MOVE_HAS_TRAIT(has_trivial_move_assign) 203 # define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) __has_trivial_move_assign(T) 204 # endif 205 206 // BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR 207 # if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && BOOST_MOVE_HAS_TRAIT(is_constructible) && BOOST_MOVE_HAS_TRAIT(is_nothrow_constructible) 208 # define BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) (__is_constructible(T, T&&) && __is_nothrow_constructible(T, T&&)) 209 # elif BOOST_MOVE_HAS_TRAIT(has_nothrow_move_constructor) 210 # define BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) __has_nothrow_move_constructor(T) 211 # endif 212 213 // BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN 214 # if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && BOOST_MOVE_HAS_TRAIT(is_assignable) && BOOST_MOVE_HAS_TRAIT(is_nothrow_assignable) 215 # define BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) (__is_assignable(T, T&&) && __is_nothrow_assignable(T, T&&)) 216 # elif BOOST_MOVE_HAS_TRAIT(has_nothrow_move_assign) 217 # define BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) __has_nothrow_move_assign(T) 218 # endif 219 220 // BOOST_MOVE_ALIGNMENT_OF 221 # define BOOST_MOVE_ALIGNMENT_OF(T) __alignof(T) 222 223 #endif //#if defined(BOOST_CLANG) 224 225 #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG) 226 227 #ifdef BOOST_INTEL 228 # define BOOST_MOVE_INTEL_TT_OPTS || ::boost::move_detail::is_pod<T>::value 229 #else 230 # define BOOST_MOVE_INTEL_TT_OPTS 231 #endif 232 233 # define BOOST_MOVE_IS_UNION(T) __is_union(T) 234 # define BOOST_MOVE_IS_POD(T) __is_pod(T) 235 # define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) 236 # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) ((__has_trivial_constructor(T) BOOST_MOVE_INTEL_TT_OPTS)) 237 238 # if defined(BOOST_GCC) && (BOOST_GCC > 50000) 239 # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__is_trivially_constructible(T, const T &)) 240 # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__is_trivially_assignable(T, const T &)) 241 # else 242 # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_MOVE_INTEL_TT_OPTS)) 243 # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_MOVE_INTEL_TT_OPTS) ) 244 # endif 245 246 # define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_MOVE_INTEL_TT_OPTS) 247 # define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) BOOST_MOVE_INTEL_TT_OPTS) 248 # define BOOST_MOVE_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) BOOST_MOVE_INTEL_TT_OPTS)) 249 # define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_MOVE_INTEL_TT_OPTS)) 250 251 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_SFINAE_EXPR) 252 253 template <typename T> 254 T && boost_move_tt_declval() BOOST_NOEXCEPT; 255 256 # if defined(BOOST_GCC) && (BOOST_GCC >= 80000) 257 // __is_assignable / __is_constructible implemented 258 # define BOOST_MOVE_IS_ASSIGNABLE(T, U) __is_assignable(T, U) 259 # define BOOST_MOVE_IS_CONSTRUCTIBLE(T, U) __is_constructible(T, U) 260 # else 261 262 template<typename Tt, typename Ut> 263 class boost_move_tt_is_assignable 264 { 265 struct twochar { char dummy[2]; }; 266 template < class T 267 , class U 268 , class = decltype(boost_move_tt_declval<T>() = boost_move_tt_declval<U>()) 269 > static char test(int); 270 271 template<class, class> static twochar test(...); 272 273 public: 274 static const bool value = sizeof(test<Tt, Ut>(0)) == sizeof(char); 275 }; 276 277 template<typename Tt, typename Ut> 278 class boost_move_tt_is_constructible 279 { 280 struct twochar { char dummy[2]; }; 281 template < class T 282 , class U 283 , class = decltype(T(boost_move_tt_declval<U>())) 284 > static char test(int); 285 286 template<class, class> static twochar test(...); 287 288 public: 289 static const bool value = sizeof(test<Tt, Ut>(0)) == sizeof(char); 290 }; 291 292 # define BOOST_MOVE_IS_ASSIGNABLE(T, U) boost_move_tt_is_assignable<T,U>::value 293 # define BOOST_MOVE_IS_CONSTRUCTIBLE(T, U) boost_move_tt_is_constructible<T, U>::value 294 295 # endif 296 297 template <typename T, typename U, bool = BOOST_MOVE_IS_ASSIGNABLE(T, U)> 298 struct boost_move_tt_is_nothrow_assignable 299 { 300 static const bool value = false; 301 }; 302 303 template <typename T, typename U> 304 struct boost_move_tt_is_nothrow_assignable<T, U, true> 305 { 306 #if !defined(BOOST_NO_CXX11_NOEXCEPT) 307 static const bool value = noexcept(boost_move_tt_declval<T>() = boost_move_tt_declval<U>()); 308 #else 309 static const bool value = false; 310 #endif 311 }; 312 313 template <typename T, typename U, bool = BOOST_MOVE_IS_CONSTRUCTIBLE(T, U)> 314 struct boost_move_tt_is_nothrow_constructible 315 { 316 static const bool value = false; 317 }; 318 319 template <typename T, typename U> 320 struct boost_move_tt_is_nothrow_constructible<T, U, true> 321 { 322 #if !defined(BOOST_NO_CXX11_NOEXCEPT) 323 static const bool value = noexcept(T(boost_move_tt_declval<U>())); 324 #else 325 static const bool value = false; 326 #endif 327 }; 328 329 # define BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) boost_move_tt_is_nothrow_assignable<T, T&&>::value 330 # define BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) boost_move_tt_is_nothrow_constructible<T, T&&>::value 331 332 # endif 333 334 # define BOOST_MOVE_IS_ENUM(T) __is_enum(T) 335 336 // BOOST_MOVE_ALIGNMENT_OF 337 # if (!defined(unix) && !defined(__unix__)) || defined(__LP64__) 338 // GCC sometimes lies about alignment requirements 339 // of type double on 32-bit unix platforms, use the 340 // old implementation instead in that case: 341 # define BOOST_MOVE_ALIGNMENT_OF(T) __alignof__(T) 342 # endif 343 #endif 344 345 #if defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600) 346 347 # define BOOST_MOVE_IS_UNION(T) __is_union(T) 348 # define BOOST_MOVE_IS_POD(T) __is_pod(T) 349 # define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) 350 # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T) 351 # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T)) 352 # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T)) 353 # define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) 354 # define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T) 355 # define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T)) 356 # define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T)) 357 358 # define BOOST_MOVE_IS_ENUM(T) __is_enum(T) 359 # define BOOST_MOVE_ALIGNMENT_OF(T) __alignof__(T) 360 #endif 361 362 # if defined(BOOST_CODEGEARC) 363 # define BOOST_MOVE_IS_UNION(T) __is_union(T) 364 # define BOOST_MOVE_IS_POD(T) __is_pod(T) 365 # define BOOST_MOVE_IS_EMPTY(T) __is_empty(T) 366 # define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) (__has_trivial_default_constructor(T)) 367 # define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy_constructor(T)) 368 # define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T)) 369 # define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T)) 370 # define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_default_constructor(T)) 371 # define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy_constructor(T)) 372 # define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T)) 373 374 # define BOOST_MOVE_IS_ENUM(T) __is_enum(T) 375 # define BOOST_MOVE_ALIGNMENT_OF(T) alignof(T) 376 377 #endif 378 379 //Fallback definitions 380 381 #ifdef BOOST_MOVE_IS_UNION 382 #define BOOST_MOVE_IS_UNION_IMPL(T) BOOST_MOVE_IS_UNION(T) 383 #else 384 #define BOOST_MOVE_IS_UNION_IMPL(T) false 385 #endif 386 387 #ifdef BOOST_MOVE_IS_POD 388 //in some compilers the intrinsic is limited to class types so add scalar and void 389 #define BOOST_MOVE_IS_POD_IMPL(T) (::boost::move_detail::is_scalar<T>::value ||\ 390 ::boost::move_detail::is_void<T>::value ||\ 391 BOOST_MOVE_IS_POD(T)) 392 #else 393 #define BOOST_MOVE_IS_POD_IMPL(T) \ 394 (::boost::move_detail::is_scalar<T>::value || ::boost::move_detail::is_void<T>::value) 395 #endif 396 397 #ifdef BOOST_MOVE_IS_EMPTY 398 #define BOOST_MOVE_IS_EMPTY_IMPL(T) BOOST_MOVE_IS_EMPTY(T) 399 #else 400 #define BOOST_MOVE_IS_EMPTY_IMPL(T) ::boost::move_detail::is_empty_nonintrinsic<T>::value 401 #endif 402 403 #ifdef BOOST_MOVE_HAS_TRIVIAL_COPY 404 #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value ||\ 405 (::boost::move_detail::is_copy_constructible<T>::value &&\ 406 BOOST_MOVE_HAS_TRIVIAL_COPY(T)) 407 #else 408 #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value 409 #endif 410 411 #ifdef BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR 412 #define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value 413 #else 414 #define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value 415 #endif 416 417 #ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR 418 #define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value 419 #else 420 #define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value 421 #endif 422 423 #ifdef BOOST_MOVE_HAS_TRIVIAL_ASSIGN 424 #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value ||\ 425 ( ::boost::move_detail::is_copy_assignable<T>::value &&\ 426 BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T)) 427 #else 428 #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value 429 #endif 430 431 #ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN 432 #define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) || ::boost::move_detail::is_pod<T>::value 433 #else 434 #define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value 435 #endif 436 437 #ifdef BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR 438 #define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value 439 #else 440 #define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value 441 #endif 442 443 #ifdef BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR 444 #define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value 445 #else 446 #define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value 447 #endif 448 449 #ifdef BOOST_MOVE_HAS_NOTHROW_COPY 450 #define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_COPY(T) || ::boost::move_detail::is_pod<T>::value 451 #else 452 #define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) 453 #endif 454 455 #ifdef BOOST_MOVE_HAS_NOTHROW_ASSIGN 456 #define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) || ::boost::move_detail::is_pod<T>::value 457 #else 458 #define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) 459 #endif 460 461 #ifdef BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR 462 #define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE_CONSTRUCTOR(T) || ::boost::move_detail::is_pod<T>::value 463 #else 464 #define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) 465 #endif 466 467 #ifdef BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN 468 #define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T) || ::boost::move_detail::is_pod<T>::value 469 #else 470 #define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) 471 #endif 472 473 #ifdef BOOST_MOVE_IS_ENUM 474 #define BOOST_MOVE_IS_ENUM_IMPL(T) BOOST_MOVE_IS_ENUM(T) 475 #else 476 #define BOOST_MOVE_IS_ENUM_IMPL(T) ::boost::move_detail::is_enum_nonintrinsic<T>::value 477 #endif 478 479 namespace boost { 480 namespace move_detail { 481 482 ////////////////////////// 483 // is_reference 484 ////////////////////////// 485 template<class T> 486 struct is_reference 487 { static const bool value = false; }; 488 489 template<class T> 490 struct is_reference<T&> 491 { static const bool value = true; }; 492 493 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 494 template<class T> 495 struct is_reference<T&&> 496 { static const bool value = true; }; 497 #endif 498 499 ////////////////////////// 500 // is_pointer 501 ////////////////////////// 502 template<class T> 503 struct is_pointer 504 { static const bool value = false; }; 505 506 template<class T> 507 struct is_pointer<T*> 508 { static const bool value = true; }; 509 510 ////////////////////////// 511 // is_const 512 ////////////////////////// 513 template<class T> 514 struct is_const 515 { static const bool value = false; }; 516 517 template<class T> 518 struct is_const<const T> 519 { static const bool value = true; }; 520 521 ////////////////////////// 522 // unvoid_ref 523 ////////////////////////// 524 template <typename T> struct unvoid_ref : add_lvalue_reference<T>{}; 525 template <> struct unvoid_ref<void> { typedef unvoid_ref & type; }; 526 template <> struct unvoid_ref<const void> { typedef unvoid_ref & type; }; 527 template <> struct unvoid_ref<volatile void> { typedef unvoid_ref & type; }; 528 template <> struct unvoid_ref<const volatile void> { typedef unvoid_ref & type; }; 529 530 template <typename T> 531 struct add_reference : add_lvalue_reference<T> 532 {}; 533 534 ////////////////////////// 535 // add_const_reference 536 ////////////////////////// 537 template <class T> 538 struct add_const_reference 539 { typedef const T &type; }; 540 541 template <class T> 542 struct add_const_reference<T&> 543 { typedef T& type; }; 544 545 ////////////////////////// 546 // add_const_if_c 547 ////////////////////////// 548 template<class T, bool Add> 549 struct add_const_if_c 550 : if_c<Add, typename add_const<T>::type, T> 551 {}; 552 553 ////////////////////////// 554 // remove_const 555 ////////////////////////// 556 template<class T> 557 struct remove_const 558 { typedef T type; }; 559 560 template<class T> 561 struct remove_const< const T> 562 { typedef T type; }; 563 564 ////////////////////////// 565 // remove_cv 566 ////////////////////////// 567 template<typename T> struct remove_cv { typedef T type; }; 568 template<typename T> struct remove_cv<const T> { typedef T type; }; 569 template<typename T> struct remove_cv<const volatile T> { typedef T type; }; 570 template<typename T> struct remove_cv<volatile T> { typedef T type; }; 571 572 ////////////////////////// 573 // remove_cvref 574 ////////////////////////// 575 template<class T> 576 struct remove_cvref 577 : remove_cv<typename remove_reference<T>::type> 578 { 579 }; 580 581 ////////////////////////// 582 // make_unsigned 583 ////////////////////////// 584 template <class T> 585 struct make_unsigned_impl { typedef T type; }; 586 template <> struct make_unsigned_impl<signed char> { typedef unsigned char type; }; 587 template <> struct make_unsigned_impl<signed short> { typedef unsigned short type; }; 588 template <> struct make_unsigned_impl<signed int> { typedef unsigned int type; }; 589 template <> struct make_unsigned_impl<signed long> { typedef unsigned long type; }; 590 #ifdef BOOST_HAS_LONG_LONG 591 template <> struct make_unsigned_impl< ::boost::long_long_type > { typedef ::boost::ulong_long_type type; }; 592 #endif 593 594 template <class T> 595 struct make_unsigned 596 : make_unsigned_impl<typename remove_cv<T>::type> 597 {}; 598 599 ////////////////////////// 600 // is_floating_point 601 ////////////////////////// 602 template<class T> struct is_floating_point_cv { static const bool value = false; }; 603 template<> struct is_floating_point_cv<float> { static const bool value = true; }; 604 template<> struct is_floating_point_cv<double> { static const bool value = true; }; 605 template<> struct is_floating_point_cv<long double> { static const bool value = true; }; 606 607 template<class T> 608 struct is_floating_point 609 : is_floating_point_cv<typename remove_cv<T>::type> 610 {}; 611 612 ////////////////////////// 613 // is_integral 614 ////////////////////////// 615 template<class T> struct is_integral_cv { static const bool value = false; }; 616 template<> struct is_integral_cv< bool>{ static const bool value = true; }; 617 template<> struct is_integral_cv< char>{ static const bool value = true; }; 618 template<> struct is_integral_cv< unsigned char>{ static const bool value = true; }; 619 template<> struct is_integral_cv< signed char>{ static const bool value = true; }; 620 #ifndef BOOST_NO_CXX11_CHAR16_T 621 template<> struct is_integral_cv< char16_t>{ static const bool value = true; }; 622 #endif 623 #ifndef BOOST_NO_CXX11_CHAR32_T 624 template<> struct is_integral_cv< char32_t>{ static const bool value = true; }; 625 #endif 626 #ifndef BOOST_NO_INTRINSIC_WCHAR_T 627 template<> struct is_integral_cv< wchar_t>{ static const bool value = true; }; 628 #endif 629 template<> struct is_integral_cv< short>{ static const bool value = true; }; 630 template<> struct is_integral_cv< unsigned short>{ static const bool value = true; }; 631 template<> struct is_integral_cv< int>{ static const bool value = true; }; 632 template<> struct is_integral_cv< unsigned int>{ static const bool value = true; }; 633 template<> struct is_integral_cv< long>{ static const bool value = true; }; 634 template<> struct is_integral_cv< unsigned long>{ static const bool value = true; }; 635 #ifdef BOOST_HAS_LONG_LONG 636 template<> struct is_integral_cv< ::boost:: long_long_type>{ static const bool value = true; }; 637 template<> struct is_integral_cv< ::boost::ulong_long_type>{ static const bool value = true; }; 638 #endif 639 640 template<class T> 641 struct is_integral 642 : public is_integral_cv<typename remove_cv<T>::type> 643 {}; 644 645 ////////////////////////////////////// 646 // remove_all_extents 647 ////////////////////////////////////// 648 template <class T> 649 struct remove_all_extents 650 { typedef T type;}; 651 652 template <class T> 653 struct remove_all_extents<T[]> 654 { typedef typename remove_all_extents<T>::type type; }; 655 656 template <class T, std::size_t N> 657 struct remove_all_extents<T[N]> 658 { typedef typename remove_all_extents<T>::type type;}; 659 660 ////////////////////////// 661 // is_scalar 662 ////////////////////////// 663 template<class T> 664 struct is_scalar 665 { static const bool value = is_integral<T>::value || is_floating_point<T>::value; }; 666 667 ////////////////////////// 668 // is_void 669 ////////////////////////// 670 template<class T> 671 struct is_void_cv 672 { static const bool value = false; }; 673 674 template<> 675 struct is_void_cv<void> 676 { static const bool value = true; }; 677 678 template<class T> 679 struct is_void 680 : is_void_cv<typename remove_cv<T>::type> 681 {}; 682 683 ////////////////////////////////////// 684 // is_array 685 ////////////////////////////////////// 686 template<class T> 687 struct is_array 688 { static const bool value = false; }; 689 690 template<class T> 691 struct is_array<T[]> 692 { static const bool value = true; }; 693 694 template<class T, std::size_t N> 695 struct is_array<T[N]> 696 { static const bool value = true; }; 697 698 ////////////////////////////////////// 699 // is_member_pointer 700 ////////////////////////////////////// 701 template <class T> struct is_member_pointer_cv { static const bool value = false; }; 702 template <class T, class U>struct is_member_pointer_cv<T U::*> { static const bool value = true; }; 703 704 template <class T> 705 struct is_member_pointer 706 : is_member_pointer_cv<typename remove_cv<T>::type> 707 {}; 708 709 ////////////////////////////////////// 710 // is_nullptr_t 711 ////////////////////////////////////// 712 template <class T> 713 struct is_nullptr_t_cv 714 { static const bool value = false; }; 715 716 #if !defined(BOOST_NO_CXX11_NULLPTR) 717 template <> 718 struct is_nullptr_t_cv 719 #if !defined(BOOST_NO_CXX11_DECLTYPE) 720 <decltype(nullptr)> 721 #else 722 <std::nullptr_t> 723 #endif 724 { static const bool value = true; }; 725 #endif 726 727 template <class T> 728 struct is_nullptr_t 729 : is_nullptr_t_cv<typename remove_cv<T>::type> 730 {}; 731 732 ////////////////////////////////////// 733 // is_function 734 ////////////////////////////////////// 735 //Inspired by libc++, thanks to Howard Hinnant 736 //For a function to pointer an lvalue of function type T can be implicitly converted to a prvalue 737 //pointer to that function. This does not apply to non-static member functions because lvalues 738 //that refer to non-static member functions do not exist. 739 template <class T> 740 struct is_reference_convertible_to_pointer 741 { 742 struct twochar { char dummy[2]; }; 743 template <class U> static char test(U*); 744 template <class U> static twochar test(...); 745 static T& source(); 746 static const bool value = sizeof(char) == sizeof(test<T>(source())); 747 }; 748 //Filter out: 749 // - class types that might have implicit conversions 750 // - void (to avoid forming a reference to void later) 751 // - references (e.g.: filtering reference to functions) 752 // - nullptr_t (convertible to pointer) 753 template < class T 754 , bool Filter = is_class_or_union<T>::value || 755 is_void<T>::value || 756 is_reference<T>::value || 757 is_nullptr_t<T>::value > 758 struct is_function_impl 759 { static const bool value = is_reference_convertible_to_pointer<T>::value; }; 760 761 template <class T> 762 struct is_function_impl<T, true> 763 { static const bool value = false; }; 764 765 template <class T> 766 struct is_function 767 : is_function_impl<T> 768 {}; 769 770 ////////////////////////////////////// 771 // is_union 772 ////////////////////////////////////// 773 template<class T> 774 struct is_union_noextents_cv 775 { static const bool value = BOOST_MOVE_IS_UNION_IMPL(T); }; 776 777 template<class T> 778 struct is_union 779 : is_union_noextents_cv<typename remove_cv<typename remove_all_extents<T>::type>::type> 780 {}; 781 782 ////////////////////////////////////// 783 // is_class 784 ////////////////////////////////////// 785 template <class T> 786 struct is_class 787 { 788 static const bool value = is_class_or_union<T>::value && ! is_union<T>::value; 789 }; 790 791 792 ////////////////////////////////////// 793 // is_arithmetic 794 ////////////////////////////////////// 795 template <class T> 796 struct is_arithmetic 797 { 798 static const bool value = is_floating_point<T>::value || 799 is_integral<T>::value; 800 }; 801 802 ////////////////////////////////////// 803 // is_member_function_pointer 804 ////////////////////////////////////// 805 template <class T> 806 struct is_member_function_pointer_cv 807 { 808 static const bool value = false; 809 }; 810 811 template <class T, class C> 812 struct is_member_function_pointer_cv<T C::*> 813 : is_function<T> 814 {}; 815 816 template <class T> 817 struct is_member_function_pointer 818 : is_member_function_pointer_cv<typename remove_cv<T>::type> 819 {}; 820 821 ////////////////////////////////////// 822 // is_enum 823 ////////////////////////////////////// 824 #if !defined(BOOST_MOVE_IS_ENUM) 825 //Based on (http://howardhinnant.github.io/TypeHiearchy.pdf) 826 template <class T> 827 struct is_enum_nonintrinsic 828 { 829 static const bool value = !is_arithmetic<T>::value && 830 !is_reference<T>::value && 831 !is_class_or_union<T>::value && 832 !is_array<T>::value && 833 !is_void<T>::value && 834 !is_nullptr_t<T>::value && 835 !is_member_pointer<T>::value && 836 !is_pointer<T>::value && 837 !is_function<T>::value; 838 }; 839 #endif 840 841 template <class T> 842 struct is_enum 843 { static const bool value = BOOST_MOVE_IS_ENUM_IMPL(T); }; 844 845 ////////////////////////////////////// 846 // is_pod 847 ////////////////////////////////////// 848 template<class T> 849 struct is_pod_noextents_cv //for non-c++11 compilers, a safe fallback 850 { static const bool value = BOOST_MOVE_IS_POD_IMPL(T); }; 851 852 template<class T> 853 struct is_pod 854 : is_pod_noextents_cv<typename remove_cv<typename remove_all_extents<T>::type>::type> 855 {}; 856 857 ////////////////////////////////////// 858 // is_empty 859 ////////////////////////////////////// 860 #if !defined(BOOST_MOVE_IS_EMPTY) 861 862 template <typename T> 863 struct empty_helper_t1 : public T 864 { 865 empty_helper_t1(); // hh compiler bug workaround 866 int i[256]; 867 private: 868 869 empty_helper_t1(const empty_helper_t1&); 870 empty_helper_t1& operator=(const empty_helper_t1&); 871 }; 872 873 struct empty_helper_t2 { int i[256]; }; 874 875 template <typename T, bool IsClass = is_class<T>::value > 876 struct is_empty_nonintrinsic 877 { 878 static const bool value = false; 879 }; 880 881 template <typename T> 882 struct is_empty_nonintrinsic<T, true> 883 { 884 static const bool value = sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2); 885 }; 886 #endif 887 888 template <class T> 889 struct is_empty 890 { static const bool value = BOOST_MOVE_IS_EMPTY_IMPL(T); }; 891 892 893 template<class T> 894 struct has_boost_move_no_copy_constructor_or_assign_type 895 { 896 template <class U> 897 static yes_type test(typename U::boost_move_no_copy_constructor_or_assign*); 898 899 template <class U> 900 static no_type test(...); 901 902 static const bool value = sizeof(test<T>(0)) == sizeof(yes_type); 903 }; 904 905 ////////////////////////////////////// 906 // is_copy_constructible 907 ////////////////////////////////////// 908 #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_CXX11_DECLTYPE) \ 909 && !defined(BOOST_INTEL_CXX_VERSION) && \ 910 !(defined(BOOST_MSVC) && _MSC_VER == 1800) 911 #define BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE 912 #endif 913 914 template<class T> 915 struct is_copy_constructible 916 { 917 // Intel compiler has problems with SFINAE for copy constructors and deleted functions: 918 // 919 // error: function *function_name* cannot be referenced -- it is a deleted function 920 // static yes_type test(U&, decltype(U(boost::declval<U&>()))* = 0); 921 // ^ 922 // MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See: 923 // https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken 924 #if defined(BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE) 925 template<class U> static typename add_reference<U>::type source(); 926 static no_type test(...); 927 #ifdef BOOST_NO_CXX11_DECLTYPE 928 template <class U> 929 static yes_type test(U&, bool_<sizeof(U(source<U>()))>* = 0); 930 #else 931 template <class U> 932 static yes_type test(U&, decltype(U(source<U>()))* = 0); 933 #endif 934 static const bool value = sizeof(test(source<T>())) == sizeof(yes_type); 935 #else 936 static const bool value = !has_boost_move_no_copy_constructor_or_assign_type<T>::value; 937 #endif 938 }; 939 940 941 ////////////////////////////////////// 942 // is_copy_assignable 943 ////////////////////////////////////// 944 #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_CXX11_DECLTYPE) \ 945 && !defined(BOOST_INTEL_CXX_VERSION) && \ 946 !(defined(BOOST_MSVC) && _MSC_VER == 1800) 947 #define BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE 948 #endif 949 950 template <class T> 951 struct is_copy_assignable 952 { 953 // Intel compiler has problems with SFINAE for copy constructors and deleted functions: 954 // 955 // error: function *function_name* cannot be referenced -- it is a deleted function 956 // static boost::type_traits::yes_type test(T1&, decltype(T1(boost::declval<T1&>()))* = 0); 957 // ^ 958 // 959 // MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See: 960 // https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken 961 #if defined(BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE) 962 typedef char yes_type; 963 struct no_type { char dummy[2]; }; 964 965 template <class U> static typename add_reference<U>::type source(); 966 template <class U> static decltype(source<U&>() = source<const U&>(), yes_type() ) test(int); 967 template <class> static no_type test(...); 968 969 static const bool value = sizeof(test<T>(0)) == sizeof(yes_type); 970 #else 971 static const bool value = !has_boost_move_no_copy_constructor_or_assign_type<T>::value; 972 #endif 973 }; 974 975 ////////////////////////////////////// 976 // is_trivially_destructible 977 ////////////////////////////////////// 978 template<class T> 979 struct is_trivially_destructible 980 { static const bool value = BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T); }; 981 982 ////////////////////////////////////// 983 // is_trivially_default_constructible 984 ////////////////////////////////////// 985 template<class T> 986 struct is_trivially_default_constructible 987 { static const bool value = BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T); }; 988 989 ////////////////////////////////////// 990 // is_trivially_copy_constructible 991 ////////////////////////////////////// 992 template<class T> 993 struct is_trivially_copy_constructible 994 { 995 static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T); 996 }; 997 998 ////////////////////////////////////// 999 // is_trivially_move_constructible 1000 ////////////////////////////////////// 1001 template<class T> 1002 struct is_trivially_move_constructible 1003 { static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T); }; 1004 1005 ////////////////////////////////////// 1006 // is_trivially_copy_assignable 1007 ////////////////////////////////////// 1008 template<class T> 1009 struct is_trivially_copy_assignable 1010 { 1011 static const bool value = BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T); 1012 }; 1013 1014 ////////////////////////////////////// 1015 // is_trivially_move_assignable 1016 ////////////////////////////////////// 1017 template<class T> 1018 struct is_trivially_move_assignable 1019 { static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T); }; 1020 1021 ////////////////////////////////////// 1022 // is_nothrow_default_constructible 1023 ////////////////////////////////////// 1024 template<class T> 1025 struct is_nothrow_default_constructible 1026 { static const bool value = BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T); }; 1027 1028 ////////////////////////////////////// 1029 // is_nothrow_copy_constructible 1030 ////////////////////////////////////// 1031 template<class T> 1032 struct is_nothrow_copy_constructible 1033 { static const bool value = BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T); }; 1034 1035 ////////////////////////////////////// 1036 // is_nothrow_move_constructible 1037 ////////////////////////////////////// 1038 template<class T> 1039 struct is_nothrow_move_constructible 1040 { static const bool value = BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T); }; 1041 1042 ////////////////////////////////////// 1043 // is_nothrow_copy_assignable 1044 ////////////////////////////////////// 1045 template<class T> 1046 struct is_nothrow_copy_assignable 1047 { static const bool value = BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T); }; 1048 1049 ////////////////////////////////////// 1050 // is_nothrow_move_assignable 1051 ////////////////////////////////////// 1052 template<class T> 1053 struct is_nothrow_move_assignable 1054 { static const bool value = BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T); }; 1055 1056 ////////////////////////////////////// 1057 // is_nothrow_swappable 1058 ////////////////////////////////////// 1059 template<class T> 1060 struct is_nothrow_swappable 1061 { 1062 static const bool value = is_empty<T>::value || is_pod<T>::value; 1063 }; 1064 1065 ////////////////////////////////////// 1066 // alignment_of 1067 ////////////////////////////////////// 1068 template <typename T> 1069 struct alignment_of_hack 1070 { 1071 T t1; 1072 char c; 1073 T t2; 1074 alignment_of_hack(); 1075 ~alignment_of_hack(); 1076 }; 1077 1078 template <unsigned A, unsigned S> 1079 struct alignment_logic 1080 { static const std::size_t value = A < S ? A : S; }; 1081 1082 template< typename T > 1083 struct alignment_of_impl 1084 #if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) 1085 // With MSVC both the native __alignof operator 1086 // and our own logic gets things wrong from time to time :-( 1087 // Using a combination of the two seems to make the most of a bad job: 1088 : alignment_logic< sizeof(alignment_of_hack<T>) - 2*sizeof(T), __alignof(T)> 1089 {}; 1090 #elif !defined(BOOST_MOVE_ALIGNMENT_OF) 1091 : alignment_logic< sizeof(alignment_of_hack<T>) - 2*sizeof(T), sizeof(T)> 1092 {}; 1093 #else 1094 { static const std::size_t value = BOOST_MOVE_ALIGNMENT_OF(T); }; 1095 #endif 1096 1097 template< typename T > 1098 struct alignment_of 1099 : alignment_of_impl<T> 1100 {}; 1101 1102 class alignment_dummy; 1103 typedef void (*function_ptr)(); 1104 typedef int (alignment_dummy::*member_ptr); 1105 typedef int (alignment_dummy::*member_function_ptr)(); 1106 struct alignment_struct 1107 { long double dummy[4]; }; 1108 1109 ///////////////////////////// 1110 // max_align_t 1111 ///////////////////////////// 1112 //This is not standard, but should work with all compilers 1113 union max_align 1114 { 1115 char char_; 1116 short short_; 1117 int int_; 1118 long long_; 1119 #ifdef BOOST_HAS_LONG_LONG 1120 ::boost::long_long_type long_long_; 1121 #endif 1122 float float_; 1123 double double_; 1124 void * void_ptr_; 1125 long double long_double_[4]; 1126 alignment_dummy *unknown_class_ptr_; 1127 function_ptr function_ptr_; 1128 member_function_ptr member_function_ptr_; 1129 alignment_struct alignment_struct_; 1130 }; 1131 1132 typedef union max_align max_align_t; 1133 1134 ///////////////////////////// 1135 // aligned_storage 1136 ///////////////////////////// 1137 1138 #if defined(_MSC_VER) && defined(_M_IX86) 1139 1140 // Special version for usual alignments on x86 MSVC because it might crash 1141 // when passsing aligned types by value even for 8 byte alignment. 1142 template<std::size_t Align> 1143 struct aligned_struct; 1144 1145 template <> struct aligned_struct<1> { char data; }; 1146 template <> struct aligned_struct<2> { short data; }; 1147 template <> struct aligned_struct<4> { int data; }; 1148 template <> struct aligned_struct<8> { double data; }; 1149 1150 #define BOOST_MOVE_ALIGNED_STRUCT(x) \ 1151 template <> struct aligned_struct<x> { \ 1152 __declspec(align(x)) char data; \ 1153 } 1154 BOOST_MOVE_ALIGNED_STRUCT(16); 1155 BOOST_MOVE_ALIGNED_STRUCT(32); 1156 BOOST_MOVE_ALIGNED_STRUCT(64); 1157 BOOST_MOVE_ALIGNED_STRUCT(128); 1158 BOOST_MOVE_ALIGNED_STRUCT(512); 1159 BOOST_MOVE_ALIGNED_STRUCT(1024); 1160 BOOST_MOVE_ALIGNED_STRUCT(2048); 1161 BOOST_MOVE_ALIGNED_STRUCT(4096); 1162 1163 template<std::size_t Len, std::size_t Align> 1164 union aligned_union 1165 { 1166 typedef aligned_struct<Align> aligner_t; 1167 aligner_t aligner; 1168 unsigned char data[Len > sizeof(aligner_t) ? Len : sizeof(aligner_t)]; 1169 }; 1170 1171 template<std::size_t Len, std::size_t Align> 1172 struct aligned_storage_impl 1173 { 1174 typedef aligned_union<Len, Align> type; 1175 }; 1176 1177 #elif !defined(BOOST_NO_ALIGNMENT) 1178 1179 template<std::size_t Len, std::size_t Align> 1180 struct aligned_struct; 1181 1182 #define BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(A)\ 1183 template<std::size_t Len>\ 1184 struct BOOST_ALIGNMENT(A) aligned_struct<Len, A>\ 1185 {\ 1186 unsigned char data[Len];\ 1187 };\ 1188 // 1189 1190 //Up to 4K alignment (typical page size) 1191 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1) 1192 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x2) 1193 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x4) 1194 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x8) 1195 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x10) 1196 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x20) 1197 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x40) 1198 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x80) 1199 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x100) 1200 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x200) 1201 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x400) 1202 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x800) 1203 BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1000) 1204 1205 #undef BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT 1206 1207 // Workaround for bogus [-Wignored-attributes] warning on GCC 6.x/7.x: don't use a type that "directly" carries the alignment attribute. 1208 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82270 1209 template<std::size_t Len, std::size_t Align> 1210 union aligned_struct_wrapper 1211 { 1212 typedef aligned_struct<Len, Align> aligner_t; 1213 aligned_struct<Len, Align> aligner; 1214 unsigned char data[Len > sizeof(aligner_t) ? Len : sizeof(aligner_t)]; 1215 }; 1216 1217 template<std::size_t Len, std::size_t Align> 1218 struct aligned_storage_impl 1219 { 1220 typedef aligned_struct_wrapper<Len, Align> type; 1221 }; 1222 1223 #else //BOOST_NO_ALIGNMENT 1224 1225 template<class T, std::size_t Len> 1226 union aligned_union 1227 { 1228 T aligner; 1229 unsigned char data[Len > sizeof(T) ? Len : sizeof(T)]; 1230 }; 1231 1232 template<std::size_t Len, std::size_t Align, class T, bool Ok> 1233 struct aligned_next; 1234 1235 template<std::size_t Len, std::size_t Align, class T> 1236 struct aligned_next<Len, Align, T, true> 1237 { 1238 BOOST_STATIC_ASSERT((alignment_of<T>::value == Align)); 1239 typedef aligned_union<T, Len> type; 1240 }; 1241 1242 //End of search defaults to max_align_t 1243 template<std::size_t Len, std::size_t Align> 1244 struct aligned_next<Len, Align, max_align_t, false> 1245 { typedef aligned_union<max_align_t, Len> type; }; 1246 1247 //Now define a search list through types 1248 #define BOOST_MOVE_ALIGNED_NEXT_STEP(TYPE, NEXT_TYPE)\ 1249 template<std::size_t Len, std::size_t Align>\ 1250 struct aligned_next<Len, Align, TYPE, false>\ 1251 : aligned_next<Len, Align, NEXT_TYPE, Align == alignment_of<NEXT_TYPE>::value>\ 1252 {};\ 1253 // 1254 BOOST_MOVE_ALIGNED_NEXT_STEP(long double, max_align_t) 1255 BOOST_MOVE_ALIGNED_NEXT_STEP(double, long double) 1256 #ifdef BOOST_HAS_LONG_LONG 1257 BOOST_MOVE_ALIGNED_NEXT_STEP(::boost::long_long_type, double) 1258 BOOST_MOVE_ALIGNED_NEXT_STEP(long, ::boost::long_long_type) 1259 #else 1260 BOOST_MOVE_ALIGNED_NEXT_STEP(long, double) 1261 #endif 1262 BOOST_MOVE_ALIGNED_NEXT_STEP(int, long) 1263 BOOST_MOVE_ALIGNED_NEXT_STEP(short, int) 1264 BOOST_MOVE_ALIGNED_NEXT_STEP(char, short) 1265 #undef BOOST_MOVE_ALIGNED_NEXT_STEP 1266 1267 template<std::size_t Len, std::size_t Align> 1268 struct aligned_storage_impl 1269 : aligned_next<Len, Align, char, Align == alignment_of<char>::value> 1270 {}; 1271 1272 #endif 1273 1274 template<std::size_t Len, std::size_t Align = alignment_of<max_align_t>::value> 1275 struct aligned_storage 1276 { 1277 //Sanity checks for input parameters 1278 BOOST_STATIC_ASSERT(Align > 0); 1279 1280 //Sanity checks for output type 1281 typedef typename aligned_storage_impl<Len ? Len : 1, Align>::type type; 1282 static const std::size_t value = alignment_of<type>::value; 1283 BOOST_STATIC_ASSERT(value >= Align); 1284 BOOST_STATIC_ASSERT((value % Align) == 0); 1285 1286 //Just in case someone instantiates aligned_storage 1287 //instead of aligned_storage::type (typical error). 1288 private: 1289 aligned_storage(); 1290 }; 1291 1292 } //namespace move_detail { 1293 } //namespace boost { 1294 1295 #include <boost/move/detail/config_end.hpp> 1296 1297 #endif //#ifndef BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP 1298