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