1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2012-2012. 4 // Distributed under the Boost Software License, Version 1.0. 5 // (See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 // 8 // See http://www.boost.org/libs/move for documentation. 9 // 10 ////////////////////////////////////////////////////////////////////////////// 11 12 //! \file 13 14 #ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP 15 #define BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP 16 17 #ifndef BOOST_CONFIG_HPP 18 # include <boost/config.hpp> 19 #endif 20 # 21 #if defined(BOOST_HAS_PRAGMA_ONCE) 22 # pragma once 23 #endif 24 25 #include <cstddef> //for std::size_t 26 27 //Small meta-typetraits to support move 28 29 namespace boost { 30 31 namespace movelib { 32 33 template <class T> 34 struct default_delete; 35 36 } //namespace movelib { 37 38 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES 39 //Forward declare boost::rv 40 template <class T> class rv; 41 #endif 42 43 namespace move_upmu { 44 45 ////////////////////////////////////// 46 // nat 47 ////////////////////////////////////// 48 struct nat{}; 49 50 ////////////////////////////////////// 51 // natify 52 ////////////////////////////////////// 53 template <class T> struct natify{}; 54 55 ////////////////////////////////////// 56 // if_c 57 ////////////////////////////////////// 58 template<bool C, typename T1, typename T2> 59 struct if_c 60 { 61 typedef T1 type; 62 }; 63 64 template<typename T1, typename T2> 65 struct if_c<false,T1,T2> 66 { 67 typedef T2 type; 68 }; 69 70 ////////////////////////////////////// 71 // if_ 72 ////////////////////////////////////// 73 template<typename T1, typename T2, typename T3> 74 struct if_ : if_c<0 != T1::value, T2, T3> 75 {}; 76 77 //enable_if_ 78 template <bool B, class T = nat> 79 struct enable_if_c 80 { 81 typedef T type; 82 }; 83 84 ////////////////////////////////////// 85 // enable_if_c 86 ////////////////////////////////////// 87 template <class T> 88 struct enable_if_c<false, T> {}; 89 90 ////////////////////////////////////// 91 // enable_if 92 ////////////////////////////////////// 93 template <class Cond, class T = nat> 94 struct enable_if : public enable_if_c<Cond::value, T> {}; 95 96 ////////////////////////////////////// 97 // remove_reference 98 ////////////////////////////////////// 99 template<class T> 100 struct remove_reference 101 { 102 typedef T type; 103 }; 104 105 template<class T> 106 struct remove_reference<T&> 107 { 108 typedef T type; 109 }; 110 111 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 112 113 template<class T> 114 struct remove_reference<T&&> 115 { 116 typedef T type; 117 }; 118 119 #else 120 121 template<class T> 122 struct remove_reference< rv<T> > 123 { 124 typedef T type; 125 }; 126 127 template<class T> 128 struct remove_reference< rv<T> &> 129 { 130 typedef T type; 131 }; 132 133 template<class T> 134 struct remove_reference< const rv<T> &> 135 { 136 typedef T type; 137 }; 138 139 140 #endif 141 142 ////////////////////////////////////// 143 // remove_const 144 ////////////////////////////////////// 145 template< class T > 146 struct remove_const 147 { 148 typedef T type; 149 }; 150 151 template< class T > 152 struct remove_const<const T> 153 { 154 typedef T type; 155 }; 156 157 ////////////////////////////////////// 158 // remove_volatile 159 ////////////////////////////////////// 160 template< class T > 161 struct remove_volatile 162 { 163 typedef T type; 164 }; 165 166 template< class T > 167 struct remove_volatile<volatile T> 168 { 169 typedef T type; 170 }; 171 172 ////////////////////////////////////// 173 // remove_cv 174 ////////////////////////////////////// 175 template< class T > 176 struct remove_cv 177 { 178 typedef typename remove_volatile 179 <typename remove_const<T>::type>::type type; 180 }; 181 182 ////////////////////////////////////// 183 // remove_extent 184 ////////////////////////////////////// 185 template<class T> 186 struct remove_extent 187 { 188 typedef T type; 189 }; 190 191 template<class T> 192 struct remove_extent<T[]> 193 { 194 typedef T type; 195 }; 196 197 template<class T, std::size_t N> 198 struct remove_extent<T[N]> 199 { 200 typedef T type; 201 }; 202 203 ////////////////////////////////////// 204 // extent 205 ////////////////////////////////////// 206 207 template<class T, unsigned N = 0> 208 struct extent 209 { 210 static const std::size_t value = 0; 211 }; 212 213 template<class T> 214 struct extent<T[], 0> 215 { 216 static const std::size_t value = 0; 217 }; 218 219 template<class T, unsigned N> 220 struct extent<T[], N> 221 { 222 static const std::size_t value = extent<T, N-1>::value; 223 }; 224 225 template<class T, std::size_t N> 226 struct extent<T[N], 0> 227 { 228 static const std::size_t value = N; 229 }; 230 231 template<class T, std::size_t I, unsigned N> 232 struct extent<T[I], N> 233 { 234 static const std::size_t value = extent<T, N-1>::value; 235 }; 236 237 ////////////////////////////////////// 238 // add_lvalue_reference 239 ////////////////////////////////////// 240 template<class T> 241 struct add_lvalue_reference 242 { 243 typedef T& type; 244 }; 245 246 template<class T> 247 struct add_lvalue_reference<T&> 248 { 249 typedef T& type; 250 }; 251 252 template<> 253 struct add_lvalue_reference<void> 254 { 255 typedef void type; 256 }; 257 258 template<> 259 struct add_lvalue_reference<const void> 260 { 261 typedef const void type; 262 }; 263 264 template<> 265 struct add_lvalue_reference<volatile void> 266 { 267 typedef volatile void type; 268 }; 269 270 template<> 271 struct add_lvalue_reference<const volatile void> 272 { 273 typedef const volatile void type; 274 }; 275 276 template<class T> 277 struct add_const_lvalue_reference 278 { 279 typedef typename remove_reference<T>::type t_unreferenced; 280 typedef const t_unreferenced t_unreferenced_const; 281 typedef typename add_lvalue_reference 282 <t_unreferenced_const>::type type; 283 }; 284 285 ////////////////////////////////////// 286 // is_same 287 ////////////////////////////////////// 288 template<class T, class U> 289 struct is_same 290 { 291 static const bool value = false; 292 }; 293 294 template<class T> 295 struct is_same<T, T> 296 { 297 static const bool value = true; 298 }; 299 300 ////////////////////////////////////// 301 // is_pointer 302 ////////////////////////////////////// 303 template< class T > 304 struct is_pointer 305 { 306 static const bool value = false; 307 }; 308 309 template< class T > 310 struct is_pointer<T*> 311 { 312 static const bool value = true; 313 }; 314 315 ////////////////////////////////////// 316 // is_reference 317 ////////////////////////////////////// 318 template< class T > 319 struct is_reference 320 { 321 static const bool value = false; 322 }; 323 324 template< class T > 325 struct is_reference<T&> 326 { 327 static const bool value = true; 328 }; 329 330 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 331 332 template< class T > 333 struct is_reference<T&&> 334 { 335 static const bool value = true; 336 }; 337 338 #endif 339 340 ////////////////////////////////////// 341 // is_lvalue_reference 342 ////////////////////////////////////// 343 template<class T> 344 struct is_lvalue_reference 345 { 346 static const bool value = false; 347 }; 348 349 template<class T> 350 struct is_lvalue_reference<T&> 351 { 352 static const bool value = true; 353 }; 354 355 ////////////////////////////////////// 356 // is_array 357 ////////////////////////////////////// 358 template<class T> 359 struct is_array 360 { 361 static const bool value = false; 362 }; 363 364 template<class T> 365 struct is_array<T[]> 366 { 367 static const bool value = true; 368 }; 369 370 template<class T, std::size_t N> 371 struct is_array<T[N]> 372 { 373 static const bool value = true; 374 }; 375 376 ////////////////////////////////////// 377 // has_pointer_type 378 ////////////////////////////////////// 379 template <class T> 380 struct has_pointer_type 381 { 382 struct two { char c[2]; }; 383 template <class U> static two test(...); 384 template <class U> static char test(typename U::pointer* = 0); 385 static const bool value = sizeof(test<T>(0)) == 1; 386 }; 387 388 ////////////////////////////////////// 389 // pointer_type 390 ////////////////////////////////////// 391 template <class T, class D, bool = has_pointer_type<D>::value> 392 struct pointer_type_imp 393 { 394 typedef typename D::pointer type; 395 }; 396 397 template <class T, class D> 398 struct pointer_type_imp<T, D, false> 399 { 400 typedef T* type; 401 }; 402 403 template <class T, class D> 404 struct pointer_type 405 { 406 typedef typename pointer_type_imp 407 <typename remove_extent<T>::type, typename remove_reference<D>::type>::type type; 408 }; 409 410 ////////////////////////////////////// 411 // is_convertible 412 ////////////////////////////////////// 413 #if defined(_MSC_VER) && (_MSC_VER >= 1400) 414 415 //use intrinsic since in MSVC 416 //overaligned types can't go through ellipsis 417 template <class T, class U> 418 struct is_convertible 419 { 420 static const bool value = __is_convertible_to(T, U); 421 }; 422 423 #else 424 425 template <class T, class U> 426 class is_convertible 427 { 428 typedef typename add_lvalue_reference<T>::type t_reference; 429 typedef char true_t; 430 class false_t { char dummy[2]; }; 431 static false_t dispatch(...); 432 static true_t dispatch(U); 433 static t_reference trigger(); 434 public: 435 static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); 436 }; 437 438 #endif 439 440 ////////////////////////////////////// 441 // is_unary_function 442 ////////////////////////////////////// 443 #if defined(BOOST_MSVC) || defined(__BORLANDC_) 444 #define BOOST_MOVE_TT_DECL __cdecl 445 #else 446 #define BOOST_MOVE_TT_DECL 447 #endif 448 449 #if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(_M_ARM64) && !defined(UNDER_CE) 450 #define BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS 451 #endif 452 453 template <typename T> 454 struct is_unary_function_impl 455 { static const bool value = false; }; 456 457 // avoid duplicate definitions of is_unary_function_impl 458 #ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS 459 460 template <typename R> 461 struct is_unary_function_impl<R (*)()> 462 { static const bool value = true; }; 463 464 template <typename R> 465 struct is_unary_function_impl<R (*)(...)> 466 { static const bool value = true; }; 467 468 #else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS 469 470 template <typename R> 471 struct is_unary_function_impl<R (__stdcall*)()> 472 { static const bool value = true; }; 473 474 #ifndef _MANAGED 475 476 template <typename R> 477 struct is_unary_function_impl<R (__fastcall*)()> 478 { static const bool value = true; }; 479 480 #endif 481 482 template <typename R> 483 struct is_unary_function_impl<R (__cdecl*)()> 484 { static const bool value = true; }; 485 486 template <typename R> 487 struct is_unary_function_impl<R (__cdecl*)(...)> 488 { static const bool value = true; }; 489 490 #endif 491 492 // avoid duplicate definitions of is_unary_function_impl 493 #ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS 494 495 template <typename R, class T0> 496 struct is_unary_function_impl<R (*)(T0)> 497 { static const bool value = true; }; 498 499 template <typename R, class T0> 500 struct is_unary_function_impl<R (*)(T0...)> 501 { static const bool value = true; }; 502 503 #else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS 504 505 template <typename R, class T0> 506 struct is_unary_function_impl<R (__stdcall*)(T0)> 507 { static const bool value = true; }; 508 509 #ifndef _MANAGED 510 511 template <typename R, class T0> 512 struct is_unary_function_impl<R (__fastcall*)(T0)> 513 { static const bool value = true; }; 514 515 #endif 516 517 template <typename R, class T0> 518 struct is_unary_function_impl<R (__cdecl*)(T0)> 519 { static const bool value = true; }; 520 521 template <typename R, class T0> 522 struct is_unary_function_impl<R (__cdecl*)(T0...)> 523 { static const bool value = true; }; 524 525 #endif 526 527 template <typename T> 528 struct is_unary_function_impl<T&> 529 { static const bool value = false; }; 530 531 template<typename T> 532 struct is_unary_function 533 { static const bool value = is_unary_function_impl<T>::value; }; 534 535 ////////////////////////////////////// 536 // has_virtual_destructor 537 ////////////////////////////////////// 538 #if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\ 539 || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500)) 540 # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) 541 #elif defined(BOOST_CLANG) && defined(__has_feature) 542 # if __has_feature(has_virtual_destructor) 543 # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) 544 # endif 545 #elif defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG) 546 # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) 547 #elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600) 548 # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) 549 #elif defined(BOOST_CODEGEARC) 550 # define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) 551 #endif 552 553 #ifdef BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR 554 template<class T> 555 struct has_virtual_destructor{ static const bool value = BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T); }; 556 #else 557 //If no intrinsic is available you trust the programmer knows what is doing 558 template<class T> 559 struct has_virtual_destructor{ static const bool value = true; }; 560 #endif 561 562 } //namespace move_upmu { 563 } //namespace boost { 564 565 #endif //#ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP 566