diff --git a/doc/type_index.qbk b/doc/type_index.qbk index 69e39a8..6a5b90c 100644 --- a/doc/type_index.qbk +++ b/doc/type_index.qbk @@ -301,6 +301,7 @@ i TypeIndex has been tested and successfully work on many compilers. +[\ -DB_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(1, 1, false, "")' ] If `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE` macro is not defined or `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` are defined to zero then you are using a compiler that was not tested with this library. diff --git a/include/boost/type_index/ctti_type_index.hpp b/include/boost/type_index/ctti_type_index.hpp index 9bafae7..385eb9e 100644 --- a/include/boost/type_index/ctti_type_index.hpp +++ b/include/boost/type_index/ctti_type_index.hpp @@ -97,9 +97,7 @@ inline const detail::ctti_data& ctti_construct() BOOST_NOEXCEPT { class ctti_type_index: public type_index_facade { const detail::ctti_data* data_; - inline std::size_t get_raw_name_length() const BOOST_NOEXCEPT { - return std::strlen(raw_name() + detail::ctti_skip_size_at_end); - } + inline std::size_t get_raw_name_length() const BOOST_NOEXCEPT; public: typedef detail::ctti_data type_info_t; @@ -158,6 +156,10 @@ inline const char* ctti_type_index::raw_name() const BOOST_NOEXCEPT { return reinterpret_cast(data_); } +inline std::size_t ctti_type_index::get_raw_name_length() const BOOST_NOEXCEPT { + return std::strlen(raw_name() + detail::ctti_skip_size_at_end); +} + inline std::string ctti_type_index::pretty_name() const { std::size_t len = get_raw_name_length(); diff --git a/include/boost/type_index/detail/compile_time_type_info.hpp b/include/boost/type_index/detail/compile_time_type_info.hpp index ad53863..3ce4cf1 100644 --- a/include/boost/type_index/detail/compile_time_type_info.hpp +++ b/include/boost/type_index/detail/compile_time_type_info.hpp @@ -17,12 +17,21 @@ /// \file compile_time_type_info.hpp /// \brief Contains implementation of boost::ctti class. -/// #include #include +#include +#include + +#define BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(begin_skip, end_skip, runtime_skip, runtime_skip_until) \ + namespace boost { namespace typeindex { namespace detail { \ + BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_begin = begin_skip; \ + BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_end = end_skip; \ + BOOST_STATIC_CONSTEXPR bool ctti_skip_more_at_runtime = runtime_skip; \ + BOOST_STATIC_CONSTEXPR char ctti_skip_until_runtime[] = runtime_skip_until; \ + }}} /* namespace boost::typeindex::detail */ \ + /**/ -namespace boost { namespace typeindex { namespace detail { #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) @@ -36,59 +45,73 @@ namespace boost { namespace typeindex { namespace detail { /// that outputs the WHOLE function signature, including template parameters. /// /// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined, -/// then a compile-time error will arise at any attempt to use boost::template_info or -/// boost::template_index classes. +/// then a compile-time error will arise at any attempt to use boost::typeindex::ctti_type_index classes. #define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION -/// \def BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP +/// \def BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING /// /// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE, BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP /// and BOOST_TYPE_INDEX_CTTI_END_SKIP macroses are used for adding a /// support for compilers, that by default are not recognized by TypeIndex library. /// /// See Compiler support for more info -#define BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP 0 - -/// \def BOOST_TYPE_INDEX_CTTI_END_SKIP -/// -/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE, BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP -/// and BOOST_TYPE_INDEX_CTTI_END_SKIP macroses are used for adding a -/// support for compilers, that by default are not recognized by TypeIndex library. -/// -/// See Compiler support for more info -#define BOOST_TYPE_INDEX_CTTI_END_SKIP 0 - -#elif defined(BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP) && defined(BOOST_TYPE_INDEX_CTTI_END_SKIP) - // skip user specified bytes count - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP); - // skip user specified bytes count - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = BOOST_TYPE_INDEX_CTTI_END_SKIP); -#elif defined _MSC_VER - // sizeof("const char *__cdecl boost::detail::ctti<") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 40); - - // sizeof(">::n(void)") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 10); - -#elif defined __clang__ - // sizeof("static const char *boost::detail::ctti<") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 39); - - // == sizeof(">::n()") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 6); -#elif defined __GNUC__ - // sizeof("static const char* boost::detail::ctti::n() [with T = ") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 57); - - // == sizeof("]") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 1); +#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(0, 0, false, ""); +#elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING) + BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING +#elif defined(_MSC_VER) + // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1 + BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 10, false, ""); +#elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 4)) + // sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1 + BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 6, false, ""); +#elif defined(__clang__) && __clang_major__ == 3 && __clang_minor__ >= 4 + // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int" + BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = "); +#elif defined(__GNUC__) + // sizeof("static const char* boost::detail::ctti::n() [with T = ") - 1, sizeof("]") - 1 + BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, ""); #else - // TODO: Code for other platforms - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 0); // skip nothing - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 0); // skip nothing + // Deafult code for other platforms... Just skip nothing! + BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(0, 0, false, ""); #endif +#undef BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS + +namespace boost { namespace typeindex { namespace detail { + template + inline void assert_compile_time_legths() BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT_MSG( + Condition, + "TypeIndex library is misconfigured for your compiler. " + "Please define BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP and " + "BOOST_TYPE_INDEX_CTTI_END_SKIP to correct values. See section " + "'RTTI emulation limitations' of the documentation." + ); + } + + template + inline const char* skip_begining_runtime(const char* begin, boost::mpl::false_) BOOST_NOEXCEPT { + return begin; + } + + template + inline const char* skip_begining_runtime(const char* begin, boost::mpl::true_) BOOST_NOEXCEPT { + const char* const it = std::search( + begin, begin + ArrayLength, + ctti_skip_until_runtime, ctti_skip_until_runtime + sizeof(ctti_skip_until_runtime) - 1 + ); + return (it == begin + ArrayLength ? begin : it + sizeof(ctti_skip_until_runtime) - 1); + } + + template + inline const char* skip_begining(const char* begin) BOOST_NOEXCEPT { + assert_compile_time_legths<(ArrayLength > ctti_skip_size_at_begin + ctti_skip_size_at_end)>(); + return skip_begining_runtime( + begin + ctti_skip_size_at_begin, + boost::mpl::bool_() + ); + } }}} // namespace boost::typeindex::detail namespace boost { namespace detail { @@ -98,38 +121,31 @@ namespace boost { namespace detail { /// This name must be as short as posible, to avoid code bloat template struct ctti { - typedef T template_type; - typedef ctti this_type; /// Returns raw name. Must be as short, as possible, to avoid code bloat static const char* n() BOOST_NOEXCEPT { - #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) - return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE + boost::typeindex::detail::ctti_skip_size_at_begin; - #elif defined(__FUNCSIG__) - return __FUNCSIG__ + boost::typeindex::detail::ctti_skip_size_at_begin; - #elif defined(__PRETTY_FUNCTION__) \ - || defined(__GNUC__) \ - || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \ - || (defined(__ICC) && (__ICC >= 600)) \ - || defined(__ghs__) \ - || defined(__DMC__) + #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) + return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE >(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE); + #elif defined(__FUNCSIG__) + return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__FUNCSIG__); + #elif defined(__PRETTY_FUNCTION__) \ + || defined(__GNUC__) \ + || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \ + || (defined(__ICC) && (__ICC >= 600)) \ + || defined(__ghs__) \ + || defined(__DMC__) - return __PRETTY_FUNCTION__ + boost::typeindex::detail::ctti_skip_size_at_begin; - #else - BOOST_STATIC_ASSERT_MSG( - sizeof(T) && false, - "TypeIndex library could not detect your compiler. " - "Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use " - "correct compiler macro for getting the whole function name. " - "Do not forget to also define BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP and " - "BOOST_TYPE_INDEX_CTTI_END_SKIP." - ); - #endif - } - - /// Returns raw name - static const char* name() BOOST_NOEXCEPT { - return this_type::n(); + return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__); + #else + BOOST_STATIC_ASSERT_MSG( + sizeof(T) && false, + "TypeIndex library could not detect your compiler. " + "Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use " + "correct compiler macro for getting the whole function name. " + "Do not forget to also define BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP and " + "BOOST_TYPE_INDEX_CTTI_END_SKIP." + ); + #endif } };