From cf4096d3170baf0ce33adf7d17ad270d50ddbdab Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sat, 26 Oct 2013 19:47:31 +0400 Subject: [PATCH] Some more modifications. --- boost/type_index/type_index.hpp | 320 +++++++++++++++++++++++++++++--- 1 file changed, 292 insertions(+), 28 deletions(-) diff --git a/boost/type_index/type_index.hpp b/boost/type_index/type_index.hpp index 255d4cf..72a1b95 100644 --- a/boost/type_index/type_index.hpp +++ b/boost/type_index/type_index.hpp @@ -1,70 +1,334 @@ // // Copyright (c) Antony Polukhin, 2012-2013. // -// // 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 BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP -#define BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP +#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_HPP +#define BOOST_TYPE_INDEX_TYPE_INDEX_HPP // MS compatible compilers support #pragma once #if defined(_MSC_VER) # pragma once #endif -/// \file type_index_minimal.hpp -/// \brief This is the header that required for ussage of boost::type_index with/without RTTI. +/// \file type_index.hpp +/// \brief Contains implementation of boost::type_index class. /// -/// It includes only the minamally required headers and does the 'typedef template_index type_index;' -/// when RTTI is disabled. +/// boost::type_index class is used in situations when RTTI is enabled. -#include +#include -#if !defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY) -# include +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream #else -# include -# include +#include +#endif +#endif namespace boost { -typedef template_index type_index; +/// Copyable type_index class that requires RTTI. +class type_index { +public: + typedef boost::type_info stl_type_info; +private: + const stl_type_info* pinfo_; + +public: + /// Default constructor. + type_index() BOOST_NOEXCEPT + : pinfo_(&typeid(void)) + {} + + /// Constructs type_index from an instance of std::type_info. + explicit type_index(const stl_type_info& inf) BOOST_NOEXCEPT + : pinfo_(&inf) + {} + + /// Factory method for constructing type_index instance for type T. + /// Strips const, volatile and & modifiers from T. + template + static type_index construct() BOOST_NOEXCEPT { + typedef BOOST_DEDUCED_TYPENAME boost::remove_reference::type no_ref_t; + typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cvr_t; + + # if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ + || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) + BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic::type::value + , "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions."); + #endif + + return type_index(typeid(no_cvr_t)); + } + + /// Factory method for constructing type_index instance for type T. + /// Does not strip const, volatile, & and && modifiers from T. + /// If T has no const, volatile, & and && modifiers, then returns exactly + /// the same result as in case of calling `construct()`. + template + static type_index construct_with_cvr() BOOST_NOEXCEPT { + typedef typename boost::mpl::if_c< + boost::is_reference::value + || boost::is_const::value + || boost::is_volatile::value, + detail::cvr_saver, + T + >::type type; + return construct(); + } + + /// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. + /// This method available only with RTTI enabled. + template + static type_index construct_rtti_only(T& rtti_val) { + return type_index(typeid(rtti_val)); + } + + /// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. + /// This method available only with RTTI enabled. + template + static type_index construct_rtti_only(T* rtti_val) { + return type_index(typeid(rtti_val)); + } + + /// Returns true if the type precedes the type of rhs in the collation order. + /// The collation order is just an internal order. + bool before(type_index const& rhs) const BOOST_NOEXCEPT { + return !!pinfo_->before(*rhs.pinfo_); + } + + /// Returns raw name + const char* name() const BOOST_NOEXCEPT { + #ifdef _MSC_VER + return pinfo_->raw_name(); + #else + return pinfo_->name(); + #endif + } + + /// Returns user-friendly name + std::string name_demangled() const { + #if defined(__GNUC__) + std::string ret; + int status = 0; + char* demang = abi::__cxa_demangle(pinfo_->name(), NULL, 0, &status); + BOOST_ASSERT(!status); + + BOOST_TRY { + ret = demang; // may throw out of memory exception + } BOOST_CATCH (...) { + free(demang); + BOOST_RETHROW; + } BOOST_CATCH_END + + free(demang); + #else + std::string ret = pinfo_->name(); + #endif + std::string::size_type pos = ret.find("boost::detail::cvr_saver<"); + if (pos == std::string::npos) { + return ret; + } + + pos += sizeof("boost::detail::cvr_saver<") - 1; + while (ret[pos] == ' ') { + ++ pos; + } + std::string::size_type end = ret.rfind(">"); + BOOST_ASSERT(end != std::string::npos); + while (ret[end] == ' ') { + -- end; + } + + return ret.substr(pos, end - pos); + } + +#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED + bool operator == (type_index const& rhs) const BOOST_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return !std::strcmp(pinfo_->name(), rhs.pinfo_->name()); + #else + return *pinfo_ == *rhs.pinfo_; + #endif + } + + bool operator != (type_index const& rhs) const BOOST_NOEXCEPT { + return !(*this == rhs); + } + + bool operator < (type_index const& rhs) const BOOST_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return std::strcmp(pinfo_->name(), rhs.pinfo_->name()) < 0; + #else + return before(rhs); + #endif + } + + bool operator > (type_index const& rhs) const BOOST_NOEXCEPT { + return (rhs < *this); + } + + bool operator <= (type_index const& rhs) const BOOST_NOEXCEPT { + return !(*this > rhs); + } + + bool operator >= (type_index const& rhs) const BOOST_NOEXCEPT { + return !(*this < rhs); + } + + bool operator == (stl_type_info const& rhs) const BOOST_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return !std::strcmp(pinfo_->name(), rhs.name()); + #else + return *pinfo_ == rhs; + #endif + } + + bool operator != (stl_type_info const& rhs) const BOOST_NOEXCEPT { + return !(*this == rhs); + } + + bool operator < (stl_type_info const& rhs) const BOOST_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return std::strcmp(pinfo_->name(), rhs.name()) < 0; + #else + return !!pinfo_->before(rhs); + #endif + } + + bool operator > (stl_type_info const& rhs) const BOOST_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return std::strcmp(pinfo_->name(), rhs.name()) > 0; + #else + return !!rhs.before(*pinfo_); + #endif + } + + bool operator <= (stl_type_info const& rhs) const BOOST_NOEXCEPT { + return !(*this > rhs); + } + + bool operator >= (stl_type_info const& rhs) const BOOST_NOEXCEPT { + return !(*this < rhs); + } +#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED + + /// Function for getting hash value + std::size_t hash_code() const BOOST_NOEXCEPT { +#if _MSC_VER >= 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__)) + return pinfo_->hash_code(); +#else + return boost::hash_range(name(), name() + std::strlen(name())); +#endif + } +}; + +#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED + +/* *************** type_index free functions ******************* */ + +inline bool operator == (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT { + return rhs == lhs; // Operation is commutative +} + +inline bool operator != (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT { + return rhs != lhs; // Operation is commutative +} + +inline bool operator < (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT { + return rhs > lhs; +} + +inline bool operator > (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT { + return rhs < lhs; +} + +inline bool operator <= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT { + return rhs >= lhs; +} + +inline bool operator >= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_NOEXCEPT { + return rhs <= lhs; +} + +#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED + +#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES +#undef BOOST_CLASSINFO_COMPARE_BY_NAMES +#endif + +/// @endcond + +/// Function, to get type_index for a type T. Strips const, volatile and & modifiers from T. template inline type_index type_id() BOOST_NOEXCEPT { - return template_index::construct(); + return type_index::construct(); } +/// Function for constructing type_index instance for type T. +/// Does not strip const, volatile, & and && modifiers from T. +/// If T has no const, volatile, & and && modifiers, then returns exactly +/// the same result as in case of calling `type_id()`. template inline type_index type_id_with_cvr() BOOST_NOEXCEPT { - return template_index::construct_with_cvr(); + return type_index::construct_with_cvr(); } +/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. +/// This method available only with RTTI enabled. Without RTTI support it won't compile, +/// producing a compile-time error with message: "boost::type_id_rtti_only(T&) requires RTTI" template inline type_index type_id_rtti_only(T& rtti_val) BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T&) requires RTTI"); - return type_index(); + return type_index::construct_rtti_only(rtti_val); } +/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. +/// This method available only with RTTI enabled. Without RTTI support it won't compile, +/// producing a compile-time error with message: "boost::type_id_rtti_only(T*) requires RTTI" template inline type_index type_id_rtti_only(T* rtti_val) { - BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T*) requires RTTI"); - return type_index(); + return type_index::construct_rtti_only(rtti_val); } -} // namespace boost +/* *************** type_index free functions ******************* */ + +/// @cond + +#ifndef BOOST_NO_IOSTREAM +#ifdef BOOST_NO_TEMPLATED_IOSTREAMS + +/// Ostream operator that will output demangled name. +inline std::ostream& operator<<(std::ostream& ostr, type_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} + +#else + +/// Ostream operator that will output demangled name. +template +inline std::basic_ostream& operator<<(std::basic_ostream& ostr, type_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} + +#endif // BOOST_NO_TEMPLATED_IOSTREAMS +#endif // BOOST_NO_IOSTREAM + +/// hash_value function overload for type_index. +inline std::size_t hash_value(type_index const& v) BOOST_NOEXCEPT { + return v.hash_code(); +} + +/// @endcond #endif // BOOST_NO_RTTI -#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) -/// \def BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY -/// Define the BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY macro if you are mixing objects -/// compiled with different RTTI flags. This will force the usage of boost::template_index -/// class instead of boost::type_index. -#define BOOST_TYPE_INDEX_FORCE_NORTTI_COMPATIBILITY -#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED +} // namespace boost -#endif // BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP +#endif // BOOST_TYPE_INDEX_TYPE_INDEX_HPP