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 | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/boost/type_index/detail/compile_time_type_info.hpp b/boost/type_index/detail/compile_time_type_info.hpp new file mode 100644 index 0000000000..8ee4c66e39 --- /dev/null +++ b/boost/type_index/detail/compile_time_type_info.hpp @@ -0,0 +1,143 @@ +// +// Copyright (c) Antony Polukhin, 2012-2014. +// +// +// 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_DETAIL_COMPILE_TIME_TYPE_INFO_HPP +#define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP + +/// \file compile_time_type_info.hpp +/// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index. +/// Not intended for inclusion from user's code. + +#include <boost/config.hpp> +#include <boost/static_assert.hpp> +#include <boost/mpl/bool.hpp> +#include <algorithm> + +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +/// @cond +#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 */ \ + /**/ +/// @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) + // 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__) && defined(__APPLE__) + // Someone made __clang_major__ equal to LLVM version rather than compiler version + // on APPLE platform. + // + // Using less efficient solution because there is no good way to detect real version of Clang. + // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "???????????>::n() [T = int" + BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = "); +#elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ == 0)) + // 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 + // 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__) + // 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 + // 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 <bool Condition> + 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_USER_DEFINED_PARSING to correct values. See section " + "'RTTI emulation limitations' of the documentation for more information." + ); + } + + template <std::size_t ArrayLength> + inline const char* skip_begining_runtime(const char* begin, boost::mpl::false_) BOOST_NOEXCEPT { + return begin; + } + + 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( + 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 <std::size_t ArrayLength> + 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>() + ); + } +}}} // namespace boost::typeindex::detail + +namespace boost { namespace detail { + +/// Noncopyable type_info that does not require RTTI. +/// CTTI == Compile Time Type Info. +/// This name must be as short as possible, to avoid code bloat +template <class T> +struct ctti { + + /// 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::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 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." + ); + #endif + } +}; + +}} // namespace boost::detail + +#endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP + |