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