aggressive_ptr_cast.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2014 Renato Tegon Forti, Antony Polukhin.
  2. // Copyright Antony Polukhin, 2015-2025.
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP
  8. #define BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP
  9. #include <boost/dll/config.hpp>
  10. #ifdef BOOST_HAS_PRAGMA_ONCE
  11. # pragma once
  12. #endif
  13. #include <cstring> // std::memcpy
  14. #include <memory>
  15. #include <type_traits>
  16. #if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ * 100 + __GNUC_MINOR__ > 301)
  17. # pragma GCC system_header
  18. #endif
  19. namespace boost { namespace dll { namespace detail {
  20. // GCC warns when reinterpret_cast between function pointer and object pointer occur.
  21. // This method suppress the warnings and ensures that such casts are safe.
  22. template <class To, class From>
  23. BOOST_FORCEINLINE typename std::enable_if<!std::is_member_pointer<To>::value && !std::is_reference<To>::value && !std::is_member_pointer<From>::value, To>::type
  24. aggressive_ptr_cast(From v) noexcept
  25. {
  26. static_assert(
  27. std::is_pointer<To>::value && std::is_pointer<From>::value,
  28. "`agressive_ptr_cast` function must be used only for pointer casting."
  29. );
  30. static_assert(
  31. std::is_void< typename std::remove_pointer<To>::type >::value
  32. || std::is_void< typename std::remove_pointer<From>::type >::value,
  33. "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
  34. );
  35. static_assert(
  36. sizeof(v) == sizeof(To),
  37. "Pointer to function and pointer to object differ in size on your platform."
  38. );
  39. return reinterpret_cast<To>(v);
  40. }
  41. #ifdef BOOST_MSVC
  42. # pragma warning(push)
  43. # pragma warning(disable: 4172) // "returning address of local variable or temporary" but **v is not local!
  44. #endif
  45. template <class To, class From>
  46. BOOST_FORCEINLINE typename std::enable_if<std::is_reference<To>::value && !std::is_member_pointer<From>::value, To>::type
  47. aggressive_ptr_cast(From v) noexcept
  48. {
  49. static_assert(
  50. std::is_pointer<From>::value,
  51. "`agressive_ptr_cast` function must be used only for pointer casting."
  52. );
  53. static_assert(
  54. std::is_void< typename std::remove_pointer<From>::type >::value,
  55. "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
  56. );
  57. static_assert(
  58. sizeof(v) == sizeof(typename std::remove_reference<To>::type*),
  59. "Pointer to function and pointer to object differ in size on your platform."
  60. );
  61. return static_cast<To>(
  62. **reinterpret_cast<typename std::remove_reference<To>::type**>(
  63. v
  64. )
  65. );
  66. }
  67. #ifdef BOOST_MSVC
  68. # pragma warning(pop)
  69. #endif
  70. template <class To, class From>
  71. BOOST_FORCEINLINE typename std::enable_if<std::is_member_pointer<To>::value && !std::is_member_pointer<From>::value, To>::type
  72. aggressive_ptr_cast(From v) noexcept
  73. {
  74. static_assert(
  75. std::is_pointer<From>::value,
  76. "`agressive_ptr_cast` function must be used only for pointer casting."
  77. );
  78. static_assert(
  79. std::is_void< typename std::remove_pointer<From>::type >::value,
  80. "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
  81. );
  82. To res = 0;
  83. std::memcpy(&res, &v, sizeof(From));
  84. return res;
  85. }
  86. template <class To, class From>
  87. BOOST_FORCEINLINE typename std::enable_if<!std::is_member_pointer<To>::value && std::is_member_pointer<From>::value, To>::type
  88. aggressive_ptr_cast(From /* v */) noexcept
  89. {
  90. static_assert(
  91. std::is_pointer<To>::value,
  92. "`agressive_ptr_cast` function must be used only for pointer casting."
  93. );
  94. static_assert(
  95. std::is_void< typename std::remove_pointer<To>::type >::value,
  96. "`agressive_ptr_cast` function must be used only for casting to or from void pointers."
  97. );
  98. static_assert(
  99. !sizeof(From),
  100. "Casting from member pointers to void pointer is not implemnted in `agressive_ptr_cast`."
  101. );
  102. return 0;
  103. }
  104. }}} // boost::dll::detail
  105. #endif // BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP