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