diff options
Diffstat (limited to 'boost/type_index/detail/compile_time_type_info.hpp')
-rw-r--r-- | boost/type_index/detail/compile_time_type_info.hpp | 193 |
1 files changed, 169 insertions, 24 deletions
diff --git a/boost/type_index/detail/compile_time_type_info.hpp b/boost/type_index/detail/compile_time_type_info.hpp index 635b45d67c..122a2ac013 100644 --- a/boost/type_index/detail/compile_time_type_info.hpp +++ b/boost/type_index/detail/compile_time_type_info.hpp @@ -1,5 +1,5 @@ // -// Copyright (c) Antony Polukhin, 2012-2014. +// Copyright (c) Antony Polukhin, 2012-2016. // // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -16,7 +16,6 @@ #include <boost/config.hpp> #include <boost/static_assert.hpp> #include <boost/mpl/bool.hpp> -#include <algorithm> #ifdef BOOST_HAS_PRAGMA_ONCE # pragma once @@ -30,19 +29,21 @@ 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 */ \ - /**/ + /**/ /// @endcond + #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) /* Nothing to document. All the macro docs are moved to <boost/type_index.hpp> */ #elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING) - # include <boost/preprocessor/facilities/expand.hpp> BOOST_PP_EXPAND( BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING ) - -#elif defined(_MSC_VER) +#elif defined(_MSC_VER) && defined (BOOST_NO_CXX11_NOEXCEPT) // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1 BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 10, false, "") +#elif defined(_MSC_VER) && !defined (BOOST_NO_CXX11_NOEXCEPT) + // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void) noexcept") - 1 + BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 19, false, "") #elif defined(__clang__) && defined(__APPLE__) // Someone made __clang_major__ equal to LLVM version rather than compiler version // on APPLE platform. @@ -54,11 +55,14 @@ // sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1 // note: checked on 3.0 BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 6, false, "") -#elif defined(__clang__) && __clang_major__ == 3 && __clang_minor__ > 0 +#elif defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ > 0)) // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int" // note: checked on 3.1, 3.4 BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ") -#elif defined(__GNUC__) +#elif defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) + // sizeof("static contexpr char boost::detail::ctti<T>::s() [with long unsigned int I = 0ul; T = ") - 1, sizeof("]") - 1 + BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(87, 1, false, "") +#elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR) // sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1 BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "") #else @@ -70,7 +74,7 @@ namespace boost { namespace typeindex { namespace detail { template <bool Condition> - inline void assert_compile_time_legths() BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG( Condition, "TypeIndex library is misconfigured for your compiler. " @@ -78,15 +82,63 @@ namespace boost { namespace typeindex { namespace detail { "'RTTI emulation limitations' of the documentation for more information." ); } - + + template <class T> + BOOST_CXX14_CONSTEXPR inline void failed_to_get_function_name() BOOST_NOEXCEPT { + 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. " + "Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that." + ); + } + template <std::size_t ArrayLength> - inline const char* skip_begining_runtime(const char* begin, boost::mpl::false_) BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::mpl::false_) BOOST_NOEXCEPT { return begin; } + template<class ForwardIterator1, class ForwardIterator2> + BOOST_CXX14_CONSTEXPR inline ForwardIterator1 constexpr_search( + ForwardIterator1 first1, + ForwardIterator1 last1, + ForwardIterator2 first2, + ForwardIterator2 last2) BOOST_NOEXCEPT + { + if (first2 == last2) { + return first1; // specified in C++11 + } + + while (first1 != last1) { + ForwardIterator1 it1 = first1; + ForwardIterator2 it2 = first2; + + while (*it1 == *it2) { + ++it1; + ++it2; + if (it2 == last2) return first1; + if (it1 == last1) return last1; + } + + ++first1; + } + + return last1; + } + + BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp(const char *v1, const char *v2) BOOST_NOEXCEPT { + while (*v1 != '\0' && *v1 == *v2) { + ++v1; + ++v2; + }; + + return static_cast<int>(*v1) - *v2; + } + template <std::size_t ArrayLength> - inline const char* skip_begining_runtime(const char* begin, boost::mpl::true_) BOOST_NOEXCEPT { - const char* const it = std::search( + BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::mpl::true_) BOOST_NOEXCEPT { + const char* const it = constexpr_search( begin, begin + ArrayLength, ctti_skip_until_runtime, ctti_skip_until_runtime + sizeof(ctti_skip_until_runtime) - 1 ); @@ -94,13 +146,54 @@ namespace boost { namespace typeindex { namespace detail { } template <std::size_t ArrayLength> - inline const char* skip_begining(const char* begin) BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR 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<ArrayLength - ctti_skip_size_at_begin>( begin + ctti_skip_size_at_begin, boost::mpl::bool_<ctti_skip_more_at_runtime>() ); } + +#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) + template <std::size_t... I> + struct index_seq {}; + + template <typename Left, typename Right> + struct make_index_sequence_join; + + template <std::size_t... Left, std::size_t... Right> + struct make_index_sequence_join<index_seq<Left...>, index_seq<Right...> > { + typedef index_seq<Left..., Right...> type; + }; + + template <std::size_t C, std::size_t D> + struct make_index_seq_impl { + typedef typename make_index_sequence_join< + typename make_index_seq_impl<C, D / 2>::type, + typename make_index_seq_impl<C + D / 2, (D + 1) / 2>::type + >::type type; + }; + + template <std::size_t C> + struct make_index_seq_impl<C, 0> { + typedef index_seq<> type; + }; + + template <std::size_t C> + struct make_index_seq_impl<C, 1> { + typedef index_seq<C> type; + }; + + template <char... C> + struct cstring { + static constexpr std::size_t size_ = sizeof...(C); + static constexpr char data_[size_] = { C... }; + }; + + template <char... C> + constexpr char cstring<C...>::data_[]; +#endif + }}} // namespace boost::typeindex::detail namespace boost { namespace detail { @@ -110,11 +203,68 @@ namespace boost { namespace detail { /// This name must be as short as possible, to avoid code bloat template <class T> struct ctti { + +#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) + //helper functions + template <std::size_t I> + constexpr static char s() BOOST_NOEXCEPT { // step + constexpr std::size_t offset = + (I >= 10u ? 1u : 0u) + + (I >= 100u ? 1u : 0u) + + (I >= 1000u ? 1u : 0u) + + (I >= 10000u ? 1u : 0u) + + (I >= 100000u ? 1u : 0u) + + (I >= 1000000u ? 1u : 0u) + ; + #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) + return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE[I + offset]; + #elif defined(__FUNCSIG__) + return __FUNCSIG__[I + offset]; + #else + return __PRETTY_FUNCTION__[I + offset]; + #endif + } + + template <std::size_t ...Indexes> + constexpr static const char* impl(::boost::typeindex::detail::index_seq<Indexes...> ) BOOST_NOEXCEPT { + return ::boost::typeindex::detail::cstring<s<Indexes>()...>::data_; + } + + template <std::size_t D = 0> // `D` means `Dummy` + constexpr static const char* n() BOOST_NOEXCEPT { + #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) + constexpr std::size_t size = sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE); + #elif defined(__FUNCSIG__) + constexpr std::size_t size = sizeof(__FUNCSIG__); + #elif defined(__PRETTY_FUNCTION__) \ + || defined(__GNUC__) \ + || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \ + || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \ + || (defined(__ICC) && (__ICC >= 600)) \ + || defined(__ghs__) \ + || defined(__DMC__) + constexpr std::size_t size = sizeof(__PRETTY_FUNCTION__); + #else + boost::typeindex::detail::failed_to_get_function_name(); + #endif + + boost::typeindex::detail::assert_compile_time_legths< + (size > boost::typeindex::detail::ctti_skip_size_at_begin + boost::typeindex::detail::ctti_skip_size_at_end + sizeof("const *") - 1) + >(); + static_assert(!boost::typeindex::detail::ctti_skip_more_at_runtime, "Skipping for GCC in C++14 mode is unsupported"); + + typedef typename boost::typeindex::detail::make_index_seq_impl< + boost::typeindex::detail::ctti_skip_size_at_begin, + size - sizeof("const *") + 1 - boost::typeindex::detail::ctti_skip_size_at_begin + >::type idx_seq; + return impl(idx_seq()); + } +#else /// Returns raw name. Must be as short, as possible, to avoid code bloat - static const char* n() BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR static const char* n() BOOST_NOEXCEPT { #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) - return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE >(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__) \ @@ -124,18 +274,13 @@ struct ctti { || (defined(__ICC) && (__ICC >= 600)) \ || defined(__ghs__) \ || defined(__DMC__) - 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. " - "Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that." - ); + boost::typeindex::detail::failed_to_get_function_name(); + return ""; #endif } +#endif }; }} // namespace boost::detail |