|
1 // Copyright David Abrahams 2002. |
|
2 // Distributed under the Boost Software License, Version 1.0. (See |
|
3 // accompanying file LICENSE_1_0.txt or copy at |
|
4 // http://www.boost.org/LICENSE_1_0.txt) |
|
5 #ifndef TYPE_ID_DWA2002517_HPP |
|
6 # define TYPE_ID_DWA2002517_HPP |
|
7 |
|
8 # include <boost/python/detail/prefix.hpp> |
|
9 |
|
10 # include <boost/python/detail/msvc_typeinfo.hpp> |
|
11 # include <boost/operators.hpp> |
|
12 # include <typeinfo> |
|
13 # include <cstring> |
|
14 # include <boost/static_assert.hpp> |
|
15 # include <boost/detail/workaround.hpp> |
|
16 # include <boost/type_traits/same_traits.hpp> |
|
17 # include <boost/type_traits/broken_compiler_spec.hpp> |
|
18 |
|
19 # ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
|
20 # if defined(__GNUC__) \ |
|
21 && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) \ |
|
22 && !defined(__EDG_VERSION__) |
|
23 # define BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
|
24 # endif |
|
25 # endif |
|
26 |
|
27 namespace boost { namespace python { |
|
28 |
|
29 // for this compiler at least, cross-shared-library type_info |
|
30 // comparisons don't work, so use typeid(x).name() instead. It's not |
|
31 // yet clear what the best default strategy is. |
|
32 # if (defined(__GNUC__) && __GNUC__ >= 3) \ |
|
33 || defined(_AIX) \ |
|
34 || ( defined(__sgi) && defined(__host_mips)) \ |
|
35 || (defined(__hpux) && defined(__HP_aCC)) \ |
|
36 || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) |
|
37 # define BOOST_PYTHON_TYPE_ID_NAME |
|
38 # endif |
|
39 |
|
40 #ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
|
41 // Runtime detection of broken cxxabi::__cxa_demangle versions, |
|
42 // to avoid #ifdef clutter. |
|
43 bool cxxabi_cxa_demangle_is_broken(); |
|
44 #define BOOST_PYTHON_HAVE_CXXABI_CXA_DEMANGLE_IS_BROKEN |
|
45 #endif |
|
46 |
|
47 // type ids which represent the same information as std::type_info |
|
48 // (i.e. the top-level reference and cv-qualifiers are stripped), but |
|
49 // which works across shared libraries. |
|
50 struct type_info : private totally_ordered<type_info> |
|
51 { |
|
52 inline type_info(std::type_info const& = typeid(void)); |
|
53 |
|
54 inline bool operator<(type_info const& rhs) const; |
|
55 inline bool operator==(type_info const& rhs) const; |
|
56 |
|
57 char const* name() const; |
|
58 friend BOOST_PYTHON_DECL std::ostream& operator<<( |
|
59 std::ostream&, type_info const&); |
|
60 |
|
61 private: // data members |
|
62 # ifdef BOOST_PYTHON_TYPE_ID_NAME |
|
63 typedef char const* base_id_t; |
|
64 # else |
|
65 typedef std::type_info const* base_id_t; |
|
66 # endif |
|
67 |
|
68 base_id_t m_base_type; |
|
69 }; |
|
70 |
|
71 # ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS |
|
72 # define BOOST_PYTHON_EXPLICIT_TT_DEF(T) ::boost::type<T>* |
|
73 # else |
|
74 # define BOOST_PYTHON_EXPLICIT_TT_DEF(T) |
|
75 # endif |
|
76 |
|
77 template <class T> |
|
78 inline type_info type_id(BOOST_EXPLICIT_TEMPLATE_TYPE(T)) |
|
79 { |
|
80 return type_info( |
|
81 # if !defined(_MSC_VER) \ |
|
82 || (!BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ |
|
83 && !BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700)) |
|
84 typeid(T) |
|
85 # else // strip the decoration which msvc and Intel mistakenly leave in |
|
86 python::detail::msvc_typeid((boost::type<T>*)0) |
|
87 # endif |
|
88 ); |
|
89 } |
|
90 |
|
91 # if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ |
|
92 || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) |
|
93 // Older EDG-based compilers seems to mistakenly distinguish "int" from |
|
94 // "signed int", etc., but only in typeid() expressions. However |
|
95 // though int == signed int, the "signed" decoration is propagated |
|
96 // down into template instantiations. Explicit specialization stops |
|
97 // that from taking hold. |
|
98 |
|
99 # define BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(T) \ |
|
100 template <> \ |
|
101 inline type_info type_id<T>(BOOST_PYTHON_EXPLICIT_TT_DEF(T)) \ |
|
102 { \ |
|
103 return type_info(typeid(T)); \ |
|
104 } |
|
105 |
|
106 BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(short) |
|
107 BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(int) |
|
108 BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long) |
|
109 // using Python's macro instead of Boost's - we don't seem to get the |
|
110 // config right all the time. |
|
111 # ifdef HAVE_LONG_LONG |
|
112 BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long long) |
|
113 # endif |
|
114 # undef BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID |
|
115 # endif |
|
116 |
|
117 // |
|
118 inline type_info::type_info(std::type_info const& id) |
|
119 : m_base_type( |
|
120 # ifdef BOOST_PYTHON_TYPE_ID_NAME |
|
121 id.name() |
|
122 # else |
|
123 &id |
|
124 # endif |
|
125 ) |
|
126 { |
|
127 } |
|
128 |
|
129 inline bool type_info::operator<(type_info const& rhs) const |
|
130 { |
|
131 # ifdef BOOST_PYTHON_TYPE_ID_NAME |
|
132 return std::strcmp(m_base_type, rhs.m_base_type) < 0; |
|
133 # else |
|
134 return m_base_type->before(*rhs.m_base_type); |
|
135 # endif |
|
136 } |
|
137 |
|
138 inline bool type_info::operator==(type_info const& rhs) const |
|
139 { |
|
140 # ifdef BOOST_PYTHON_TYPE_ID_NAME |
|
141 return !std::strcmp(m_base_type, rhs.m_base_type); |
|
142 # else |
|
143 return *m_base_type == *rhs.m_base_type; |
|
144 # endif |
|
145 } |
|
146 |
|
147 # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
|
148 namespace detail |
|
149 { |
|
150 BOOST_PYTHON_DECL char const* gcc_demangle(char const*); |
|
151 } |
|
152 # endif |
|
153 |
|
154 inline char const* type_info::name() const |
|
155 { |
|
156 char const* raw_name |
|
157 = m_base_type |
|
158 # ifndef BOOST_PYTHON_TYPE_ID_NAME |
|
159 ->name() |
|
160 # endif |
|
161 ; |
|
162 |
|
163 # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
|
164 return detail::gcc_demangle(raw_name); |
|
165 # else |
|
166 return raw_name; |
|
167 # endif |
|
168 } |
|
169 |
|
170 |
|
171 BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_info const&); |
|
172 |
|
173 # if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) |
|
174 template<> |
|
175 inline type_info type_id<void>(BOOST_PYTHON_EXPLICIT_TT_DEF(void)) |
|
176 { |
|
177 return type_info (typeid (void *)); |
|
178 } |
|
179 # ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS |
|
180 template<> |
|
181 inline type_info type_id<const volatile void>(BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile void)) |
|
182 { |
|
183 return type_info (typeid (void *)); |
|
184 } |
|
185 # endif |
|
186 |
|
187 # endif |
|
188 |
|
189 }} // namespace boost::python |
|
190 |
|
191 #endif // TYPE_ID_DWA2002517_HPP |