1 // Copyright 2014 Renato Tegon Forti, Antony Polukhin. 2 // Copyright 2015-2019 Antony Polukhin. 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 8 #ifndef BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP 9 #define BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP 10 11 #include <boost/dll/config.hpp> 12 #ifdef BOOST_HAS_PRAGMA_ONCE 13 # pragma once 14 #endif 15 16 #include <boost/core/addressof.hpp> 17 #include <boost/core/enable_if.hpp> 18 #include <boost/static_assert.hpp> 19 #include <boost/type_traits/is_pointer.hpp> 20 #include <boost/type_traits/is_member_pointer.hpp> 21 #include <boost/type_traits/is_void.hpp> 22 #include <boost/type_traits/is_reference.hpp> 23 #include <boost/type_traits/remove_pointer.hpp> 24 #include <boost/type_traits/remove_reference.hpp> 25 #include <cstring> // std::memcpy 26 27 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ * 100 + __GNUC_MINOR__ > 301) 28 # pragma GCC system_header 29 #endif 30 31 namespace boost { namespace dll { namespace detail { 32 33 // GCC warns when reinterpret_cast between function pointer and object pointer occur. 34 // This method suppress the warnings and ensures that such casts are safe. 35 template <class To, class From> 36 BOOST_FORCEINLINE typename boost::disable_if_c<boost::is_member_pointer<To>::value || boost::is_reference<To>::value || boost::is_member_pointer<From>::value, To>::type aggressive_ptr_cast(From v)37 aggressive_ptr_cast(From v) BOOST_NOEXCEPT 38 { 39 BOOST_STATIC_ASSERT_MSG( 40 boost::is_pointer<To>::value && boost::is_pointer<From>::value, 41 "`agressive_ptr_cast` function must be used only for pointer casting." 42 ); 43 44 BOOST_STATIC_ASSERT_MSG( 45 boost::is_void< typename boost::remove_pointer<To>::type >::value 46 || boost::is_void< typename boost::remove_pointer<From>::type >::value, 47 "`agressive_ptr_cast` function must be used only for casting to or from void pointers." 48 ); 49 50 BOOST_STATIC_ASSERT_MSG( 51 sizeof(v) == sizeof(To), 52 "Pointer to function and pointer to object differ in size on your platform." 53 ); 54 55 return reinterpret_cast<To>(v); 56 } 57 58 #ifdef BOOST_MSVC 59 # pragma warning(push) 60 # pragma warning(disable: 4172) // "returning address of local variable or temporary" but **v is not local! 61 #endif 62 63 template <class To, class From> 64 BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_reference<To>::value || boost::is_member_pointer<From>::value, To>::type aggressive_ptr_cast(From v)65 aggressive_ptr_cast(From v) BOOST_NOEXCEPT 66 { 67 BOOST_STATIC_ASSERT_MSG( 68 boost::is_pointer<From>::value, 69 "`agressive_ptr_cast` function must be used only for pointer casting." 70 ); 71 72 BOOST_STATIC_ASSERT_MSG( 73 boost::is_void< typename boost::remove_pointer<From>::type >::value, 74 "`agressive_ptr_cast` function must be used only for casting to or from void pointers." 75 ); 76 77 BOOST_STATIC_ASSERT_MSG( 78 sizeof(v) == sizeof(typename boost::remove_reference<To>::type*), 79 "Pointer to function and pointer to object differ in size on your platform." 80 ); 81 return static_cast<To>( 82 **reinterpret_cast<typename boost::remove_reference<To>::type**>( 83 v 84 ) 85 ); 86 } 87 88 #ifdef BOOST_MSVC 89 # pragma warning(pop) 90 #endif 91 92 template <class To, class From> 93 BOOST_FORCEINLINE typename boost::disable_if_c<!boost::is_member_pointer<To>::value || boost::is_member_pointer<From>::value, To>::type aggressive_ptr_cast(From v)94 aggressive_ptr_cast(From v) BOOST_NOEXCEPT 95 { 96 BOOST_STATIC_ASSERT_MSG( 97 boost::is_pointer<From>::value, 98 "`agressive_ptr_cast` function must be used only for pointer casting." 99 ); 100 101 BOOST_STATIC_ASSERT_MSG( 102 boost::is_void< typename boost::remove_pointer<From>::type >::value, 103 "`agressive_ptr_cast` function must be used only for casting to or from void pointers." 104 ); 105 106 To res = 0; 107 std::memcpy(&res, &v, sizeof(From)); 108 return res; 109 } 110 111 template <class To, class From> 112 BOOST_FORCEINLINE typename boost::disable_if_c<boost::is_member_pointer<To>::value || !boost::is_member_pointer<From>::value, To>::type aggressive_ptr_cast(From)113 aggressive_ptr_cast(From /* v */) BOOST_NOEXCEPT 114 { 115 BOOST_STATIC_ASSERT_MSG( 116 boost::is_pointer<To>::value, 117 "`agressive_ptr_cast` function must be used only for pointer casting." 118 ); 119 120 BOOST_STATIC_ASSERT_MSG( 121 boost::is_void< typename boost::remove_pointer<To>::type >::value, 122 "`agressive_ptr_cast` function must be used only for casting to or from void pointers." 123 ); 124 125 BOOST_STATIC_ASSERT_MSG( 126 !sizeof(From), 127 "Casting from member pointers to void pointer is not implemnted in `agressive_ptr_cast`." 128 ); 129 130 return 0; 131 } 132 133 }}} // boost::dll::detail 134 135 #endif // BOOST_DLL_DETAIL_AGGRESSIVE_PTR_CAST_HPP 136 137