| // Copyright David Abrahams 2002. |
| // Distributed under the Boost Software License, Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| #ifndef TYPE_ID_DWA2002517_HPP |
| # define TYPE_ID_DWA2002517_HPP |
| |
| # include <boost/python/detail/prefix.hpp> |
| |
| # include <boost/python/detail/msvc_typeinfo.hpp> |
| # include <boost/operators.hpp> |
| # include <typeinfo> |
| # include <cstring> |
| # include <ostream> |
| # include <boost/static_assert.hpp> |
| # include <boost/detail/workaround.hpp> |
| # include <boost/type_traits/same_traits.hpp> |
| # include <boost/type_traits/broken_compiler_spec.hpp> |
| |
| # ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
| # if defined(__GNUC__) \ |
| && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) \ |
| && !defined(__EDG_VERSION__) |
| # define BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
| # endif |
| # endif |
| |
| namespace boost { namespace python { |
| |
| // for this compiler at least, cross-shared-library type_info |
| // comparisons don't work, so use typeid(x).name() instead. It's not |
| // yet clear what the best default strategy is. |
| # if (defined(__GNUC__) && __GNUC__ >= 3) \ |
| || defined(_AIX) \ |
| || ( defined(__sgi) && defined(__host_mips)) \ |
| || (defined(__hpux) && defined(__HP_aCC)) \ |
| || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) |
| # define BOOST_PYTHON_TYPE_ID_NAME |
| # endif |
| |
| #ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
| // Runtime detection of broken cxxabi::__cxa_demangle versions, |
| // to avoid #ifdef clutter. |
| bool cxxabi_cxa_demangle_is_broken(); |
| #define BOOST_PYTHON_HAVE_CXXABI_CXA_DEMANGLE_IS_BROKEN |
| #endif |
| |
| // type ids which represent the same information as std::type_info |
| // (i.e. the top-level reference and cv-qualifiers are stripped), but |
| // which works across shared libraries. |
| struct type_info : private totally_ordered<type_info> |
| { |
| inline type_info(std::type_info const& = typeid(void)); |
| |
| inline bool operator<(type_info const& rhs) const; |
| inline bool operator==(type_info const& rhs) const; |
| |
| char const* name() const; |
| friend BOOST_PYTHON_DECL std::ostream& operator<<( |
| std::ostream&, type_info const&); |
| |
| private: // data members |
| # ifdef BOOST_PYTHON_TYPE_ID_NAME |
| typedef char const* base_id_t; |
| # else |
| typedef std::type_info const* base_id_t; |
| # endif |
| |
| base_id_t m_base_type; |
| }; |
| |
| # ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS |
| # define BOOST_PYTHON_EXPLICIT_TT_DEF(T) ::boost::type<T>* |
| # else |
| # define BOOST_PYTHON_EXPLICIT_TT_DEF(T) |
| # endif |
| |
| template <class T> |
| inline type_info type_id(BOOST_EXPLICIT_TEMPLATE_TYPE(T)) |
| { |
| return type_info( |
| # if !defined(_MSC_VER) \ |
| || (!BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ |
| && !BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700)) |
| typeid(T) |
| # else // strip the decoration which msvc and Intel mistakenly leave in |
| python::detail::msvc_typeid((boost::type<T>*)0) |
| # endif |
| ); |
| } |
| |
| # if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ |
| || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) |
| // Older EDG-based compilers seems to mistakenly distinguish "int" from |
| // "signed int", etc., but only in typeid() expressions. However |
| // though int == signed int, the "signed" decoration is propagated |
| // down into template instantiations. Explicit specialization stops |
| // that from taking hold. |
| |
| # define BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(T) \ |
| template <> \ |
| inline type_info type_id<T>(BOOST_PYTHON_EXPLICIT_TT_DEF(T)) \ |
| { \ |
| return type_info(typeid(T)); \ |
| } |
| |
| BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(short) |
| BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(int) |
| BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long) |
| // using Python's macro instead of Boost's - we don't seem to get the |
| // config right all the time. |
| # ifdef HAVE_LONG_LONG |
| BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long long) |
| # endif |
| # undef BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID |
| # endif |
| |
| // |
| inline type_info::type_info(std::type_info const& id) |
| : m_base_type( |
| # ifdef BOOST_PYTHON_TYPE_ID_NAME |
| id.name() |
| # else |
| &id |
| # endif |
| ) |
| { |
| } |
| |
| inline bool type_info::operator<(type_info const& rhs) const |
| { |
| # ifdef BOOST_PYTHON_TYPE_ID_NAME |
| return std::strcmp(m_base_type, rhs.m_base_type) < 0; |
| # else |
| return m_base_type->before(*rhs.m_base_type); |
| # endif |
| } |
| |
| inline bool type_info::operator==(type_info const& rhs) const |
| { |
| # ifdef BOOST_PYTHON_TYPE_ID_NAME |
| return !std::strcmp(m_base_type, rhs.m_base_type); |
| # else |
| return *m_base_type == *rhs.m_base_type; |
| # endif |
| } |
| |
| # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
| namespace detail |
| { |
| BOOST_PYTHON_DECL char const* gcc_demangle(char const*); |
| } |
| # endif |
| |
| inline char const* type_info::name() const |
| { |
| char const* raw_name |
| = m_base_type |
| # ifndef BOOST_PYTHON_TYPE_ID_NAME |
| ->name() |
| # endif |
| ; |
| |
| # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE |
| return detail::gcc_demangle(raw_name); |
| # else |
| return raw_name; |
| # endif |
| } |
| |
| |
| BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_info const&); |
| |
| # if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) |
| template<> |
| inline type_info type_id<void>(BOOST_PYTHON_EXPLICIT_TT_DEF(void)) |
| { |
| return type_info (typeid (void *)); |
| } |
| # ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS |
| template<> |
| inline type_info type_id<const volatile void>(BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile void)) |
| { |
| return type_info (typeid (void *)); |
| } |
| # endif |
| |
| # endif |
| |
| }} // namespace boost::python |
| |
| #endif // TYPE_ID_DWA2002517_HPP |