diff --git a/doc/type_index.qbk b/doc/type_index.qbk index 4dc531f..69e39a8 100644 --- a/doc/type_index.qbk +++ b/doc/type_index.qbk @@ -1,6 +1,6 @@ [library Boost.TypeIndex [quickbook 1.6] - [version 3.0] + [version 4.0] [copyright 2012-2014 Antony Polukhin] [category Language Features Emulation] [license @@ -25,8 +25,6 @@ Boost.TypeIndex library was designed to work around all those issues. [note `T` means type here. Think of it as of `T` in `template ` ] -[warning Version 3.0 of this library is waitning for Boost mini-review. ] - [endsect] [section Getting started] diff --git a/include/boost/type_index/stl_type_index.hpp b/include/boost/type_index/stl_type_index.hpp index 807dcb0..b2821b6 100644 --- a/include/boost/type_index/stl_type_index.hpp +++ b/include/boost/type_index/stl_type_index.hpp @@ -45,13 +45,15 @@ #if !defined(BOOST_MSVC) # include -# include -# include // std::free +# include // std::free +# include // std::find, std::search #endif #if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) -# include +# include +# include +# include #endif #ifdef BOOST_HAS_PRAGMA_ONCE @@ -131,41 +133,69 @@ inline const char* stl_type_index::name() const BOOST_NOEXCEPT { return data_->name(); } +namespace detail { + class free_at_scope_exit { + char* to_free_; + + public: + explicit free_at_scope_exit(char* to_free) BOOST_NOEXCEPT + : to_free_(to_free) + {} + + ~free_at_scope_exit() BOOST_NOEXCEPT { + std::free(to_free_); + } + }; +} + inline std::string stl_type_index::pretty_name() const { + static const char cvr_saver_name[] = "boost::typeindex::detail::cvr_saver<"; + #if defined(_MSC_VER) std::string ret = data_->name(); -#else - std::string ret; - int status = 0; - char* demang = abi::__cxa_demangle(raw_name(), NULL, 0, &status); - BOOST_ASSERT(!status); - - BOOST_TRY { - ret = demang; // may throw out of memory exception - } BOOST_CATCH (...) { - std::free(demang); - BOOST_RETHROW; - } BOOST_CATCH_END - - std::free(demang); -#endif - - std::string::size_type pos = ret.find("boost::typeindex::detail::cvr_saver<"); - if (pos == std::string::npos) { + std::string::size_type pos_beg = ret.find(cvr_saver_name); + if (pos_beg == std::string::npos) { return ret; } - pos += sizeof("boost::typeindex::detail::cvr_saver<") - 1; - while (ret[pos] == ' ') { - ++ pos; + const char* begin = ret.c_str() + pos_beg + sizeof(cvr_saver_name) - 1; + const char* end = ret.c_str() + ret.size() - 1; +#else + int status = 0; + char* demang = abi::__cxa_demangle(raw_name(), NULL, 0, &status); + detail::free_at_scope_exit scope(demang); + BOOST_ASSERT(!status); + const std::size_t length = std::strlen(demang); + const char* begin = std::search( + demang, demang + length, + cvr_saver_name, cvr_saver_name + sizeof(cvr_saver_name) - 1 + ); + + if (begin == demang + length) { + return std::string(demang, demang + length); + } + begin += sizeof(cvr_saver_name) - 1; + const char* end = demang + length - 1; +#endif + while (*begin == ' ') { // begin is zero terminated + ++ begin; } - std::string::size_type end = ret.rfind(">"); - while (ret[end - 1] == ' ') { + while (end != begin && *end != '>') { -- end; } - return ret.substr(pos, end - pos); + // we have cvr_saver_name somewhere at the start of the end + while (end != begin && *(end - 1) == ' ') { + -- end; + } + + if (begin >= end) { + // Some strange error in demangled name parsing + return begin; + } + + return std::string(begin, end); } @@ -217,12 +247,22 @@ inline bool stl_type_index::before(const stl_type_index& rhs) const BOOST_NOEXCE template inline stl_type_index stl_type_index::type_id() BOOST_NOEXCEPT { typedef BOOST_DEDUCED_TYPENAME boost::remove_reference::type no_ref_t; - typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cvr_t; + typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cvr_prefinal_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."); + + // Old EDG-based compilers seem to mistakenly distinguish 'integral' from 'signed integral' + // in typeid() expressions. Full temaplte specialization for 'integral' fixes that issue: + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_signed, + boost::make_signed, + boost::mpl::identity + >::type no_cvr_prefinal_lazy_t; + + typedef BOOST_DEDUCED_TYPENAME no_cvr_prefinal_t::type no_cvr_t; + #else + typedef no_cvr_prefinal_t no_cvr_t; #endif return typeid(no_cvr_t); diff --git a/include/boost/type_index/type_index_facade.hpp b/include/boost/type_index/type_index_facade.hpp index f050e73..355464c 100644 --- a/include/boost/type_index/type_index_facade.hpp +++ b/include/boost/type_index/type_index_facade.hpp @@ -53,6 +53,11 @@ namespace boost { namespace typeindex { /// /// \tparam Derived Class derived from type_index_facade. /// \tparam TypeInfo Class that will be used as a base type_info class. +/// \note Take a look at the protected methods. They are \b not \b defined in type_index_facade. +/// Protected member functions raw_name() \b must be defined in Derived class. All the other +/// methods are mandatory. +/// \see 'Making a custom type_index' section for more information about +/// creating your own type_index using type_index_facade. template class type_index_facade { private: @@ -64,16 +69,6 @@ private: public: typedef TypeInfo type_info_t; -#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) - /// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw. - /// \return Const reference to underlying low level type_info_t. - inline const type_info_t& type_info() const BOOST_NOEXCEPT; - - /// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw. - /// \return Pointer to unredable/raw type name. - inline const char* raw_name() const BOOST_NOEXCEPT; -#endif - /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. /// \return Name of a type. By default retuns Derived::raw_name(). inline const char* name() const BOOST_NOEXCEPT { @@ -112,6 +107,14 @@ public: #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) protected: + /// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw. + /// \return Pointer to unredable/raw type name. + inline const char* raw_name() const BOOST_NOEXCEPT; + + /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. + /// \return Const reference to underlying low level type_info_t. + inline const type_info_t& type_info() const BOOST_NOEXCEPT; + /// This is a factory method that is used to create instances of Derived classes. /// boost::typeindex::type_id() will call this method, if Derived has same type as boost::typeindex::type_index. /// diff --git a/test/type_index_test.cpp b/test/type_index_test.cpp index 45cbf09..60e7f73 100644 --- a/test/type_index_test.cpp +++ b/test/type_index_test.cpp @@ -1,5 +1,5 @@ // -// Copyright Antony Polukhin, 2012-2013. +// Copyright Antony Polukhin, 2012-2014. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at