diff options
author | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
commit | 08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch) | |
tree | 7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/type_index | |
parent | bb4dd8289b351fae6b55e303f189127a394a1edd (diff) | |
download | boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2 boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip |
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'boost/type_index')
-rw-r--r-- | boost/type_index/ctti_type_index.hpp | 179 | ||||
-rw-r--r-- | boost/type_index/detail/compile_time_type_info.hpp | 143 | ||||
-rw-r--r-- | boost/type_index/detail/ctti_register_class.hpp | 40 | ||||
-rw-r--r-- | boost/type_index/detail/stl_register_class.hpp | 40 | ||||
-rw-r--r-- | boost/type_index/stl_type_index.hpp | 273 | ||||
-rw-r--r-- | boost/type_index/type_index_facade.hpp | 296 |
6 files changed, 971 insertions, 0 deletions
diff --git a/boost/type_index/ctti_type_index.hpp b/boost/type_index/ctti_type_index.hpp new file mode 100644 index 0000000000..ac1e5d290d --- /dev/null +++ b/boost/type_index/ctti_type_index.hpp @@ -0,0 +1,179 @@ +// +// Copyright (c) Antony Polukhin, 2013-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_CTTI_TYPE_INDEX_HPP +#define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP + +/// \file ctti_type_index.hpp +/// \brief Contains boost::typeindex::ctti_type_index class. +/// +/// boost::typeindex::ctti_type_index class can be used as a drop-in replacement +/// for std::type_index. +/// +/// It is used in situations when typeid() method is not available or +/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined. + +#include <boost/type_index/type_index_facade.hpp> +#include <boost/type_index/detail/compile_time_type_info.hpp> + +#include <cstring> +#include <boost/static_assert.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +namespace boost { namespace typeindex { + +namespace detail { + +// That's the most trickiest part of the TypeIndex library: +// 1) we do not want to give user ability to manually construct and compare `struct-that-represents-type` +// 2) we need to distinguish between `struct-that-represents-type` and `const char*` +// 3) we need a thread-safe way to have references to instances `struct-that-represents-type` +// 4) we need a compile-time control to make sure that user does not copy or +// default construct `struct-that-represents-type` +// +// Solution would be the following: + +/// \class ctti_data +/// Standard-layout class with private constructors and assignment operators. +/// +/// You can not work with this class directly. The purpose of this class is to hold type info +/// \b when \b RTTI \b is \b off and allow ctti_type_index construction from itself. +/// +/// \b Example: +/// \code +/// const detail::ctti_data& foo(); +/// ... +/// type_index ti = type_index(foo()); +/// std::cout << ti.pretty_name(); +/// \endcode +class ctti_data { +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS +public: + ctti_data() = delete; + ctti_data(const ctti_data&) = delete; + ctti_data& operator=(const ctti_data&) = delete; +#else +private: + ctti_data(); + ctti_data(const ctti_data&); + ctti_data& operator=(const ctti_data&); +#endif +}; + +} // namespace detail + +/// Helper method for getting detail::ctti_data of a template parameter T. +template <class T> +inline const detail::ctti_data& ctti_construct() BOOST_NOEXCEPT { + // Standard C++11, 5.2.10 Reinterpret cast: + // An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue + // v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast<cv + // T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment + // requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type + // "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment + // requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer + // value. + // + // Alignments are checked in `type_index_test_ctti_alignment.cpp` test. + return *reinterpret_cast<const detail::ctti_data*>(boost::detail::ctti<T>::n()); +} + +/// \class ctti_type_index +/// This class is a wrapper that pretends to work exactly like stl_type_index, but does +/// not require RTTI support. \b For \b description \b of \b functions \b see type_index_facade. +/// +/// This class produces slightly longer type names, so consider using stl_type_index +/// in situations when typeid() is working. +class ctti_type_index: public type_index_facade<ctti_type_index, detail::ctti_data> { + const detail::ctti_data* data_; + + inline std::size_t get_raw_name_length() const BOOST_NOEXCEPT; + +public: + typedef detail::ctti_data type_info_t; + + inline ctti_type_index() BOOST_NOEXCEPT + : data_(&ctti_construct<void>()) + {} + + inline ctti_type_index(const type_info_t& data) BOOST_NOEXCEPT + : data_(&data) + {} + + inline const type_info_t& type_info() const BOOST_NOEXCEPT; + inline const char* raw_name() const BOOST_NOEXCEPT; + inline std::string pretty_name() const; + inline std::size_t hash_code() const BOOST_NOEXCEPT; + + template <class T> + inline static ctti_type_index type_id() BOOST_NOEXCEPT; + + template <class T> + inline static ctti_type_index type_id_with_cvr() BOOST_NOEXCEPT; + + template <class T> + inline static ctti_type_index type_id_runtime(const T& variable) BOOST_NOEXCEPT; +}; + + +inline const ctti_type_index::type_info_t& ctti_type_index::type_info() const BOOST_NOEXCEPT { + return *data_; +} + + +template <class T> +inline ctti_type_index ctti_type_index::type_id() BOOST_NOEXCEPT { + typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t; + typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t; + return ctti_construct<no_cvr_t>(); +} + + + +template <class T> +inline ctti_type_index ctti_type_index::type_id_with_cvr() BOOST_NOEXCEPT { + return ctti_construct<T>(); +} + + +template <class T> +inline ctti_type_index ctti_type_index::type_id_runtime(const T& variable) BOOST_NOEXCEPT { + return variable.boost_type_index_type_id_runtime_(); +} + + +inline const char* ctti_type_index::raw_name() const BOOST_NOEXCEPT { + return reinterpret_cast<const char*>(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(); + while (raw_name()[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces + return std::string(raw_name(), len); +} + + +inline std::size_t ctti_type_index::hash_code() const BOOST_NOEXCEPT { + return boost::hash_range(raw_name(), raw_name() + get_raw_name_length()); +} + + +}} // namespace boost::typeindex + +#endif // BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP + 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 + diff --git a/boost/type_index/detail/ctti_register_class.hpp b/boost/type_index/detail/ctti_register_class.hpp new file mode 100644 index 0000000000..a8cef2c497 --- /dev/null +++ b/boost/type_index/detail/ctti_register_class.hpp @@ -0,0 +1,40 @@ +// +// Copyright (c) Antony Polukhin, 2013-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_CTTI_REGISTER_CLASS_HPP +#define BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP + +/// \file ctti_register_class.hpp +/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::ctti_type_index. +/// Not intended for inclusion from user's code. + +#include <boost/type_index/ctti_type_index.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +namespace boost { namespace typeindex { namespace detail { + +template <class T> +inline const ctti_data& ctti_construct_typeid_ref(const T*) BOOST_NOEXCEPT { + return ctti_construct<T>(); +} + +}}} // namespace boost::typeindex::detail + +/// @cond +#define BOOST_TYPE_INDEX_REGISTER_CLASS \ + virtual const boost::typeindex::detail::ctti_data& boost_type_index_type_id_runtime_() const BOOST_NOEXCEPT { \ + return boost::typeindex::detail::ctti_construct_typeid_ref(this); \ + } \ +/**/ +/// @endcond + +#endif // BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP + diff --git a/boost/type_index/detail/stl_register_class.hpp b/boost/type_index/detail/stl_register_class.hpp new file mode 100644 index 0000000000..95a26f7b0e --- /dev/null +++ b/boost/type_index/detail/stl_register_class.hpp @@ -0,0 +1,40 @@ +// +// Copyright (c) Antony Polukhin, 2013-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_STL_REGISTER_CLASS_HPP +#define BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP + +/// \file stl_register_class.hpp +/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::stl_type_index. +/// Not intended for inclusion from user's code. + +#include <boost/type_index/stl_type_index.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +namespace boost { namespace typeindex { namespace detail { + +template <class T> +inline const stl_type_index::type_info_t& stl_construct_typeid_ref(const T*) BOOST_NOEXCEPT { + return typeid(T); +} + +}}} // namespace boost::typeindex::detail + +/// @cond +#define BOOST_TYPE_INDEX_REGISTER_CLASS \ + virtual const boost::typeindex::stl_type_index::type_info_t& boost_type_index_type_id_runtime_() const BOOST_NOEXCEPT { \ + return boost::typeindex::detail::stl_construct_typeid_ref(this); \ + } \ +/**/ +/// @endcond + +#endif // BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP + diff --git a/boost/type_index/stl_type_index.hpp b/boost/type_index/stl_type_index.hpp new file mode 100644 index 0000000000..1b3b0c4c80 --- /dev/null +++ b/boost/type_index/stl_type_index.hpp @@ -0,0 +1,273 @@ +// +// Copyright (c) Antony Polukhin, 2013-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_STL_TYPE_INDEX_HPP +#define BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP + +/// \file stl_type_index.hpp +/// \brief Contains boost::typeindex::stl_type_index class. +/// +/// boost::typeindex::stl_type_index class can be used as a drop-in replacement +/// for std::type_index. +/// +/// It is used in situations when RTTI is enabled or typeid() method is available. +/// When typeid() is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro +/// is defined boost::typeindex::ctti is usually used instead of boost::typeindex::stl_type_index. + +#include <boost/type_index/type_index_facade.hpp> + +// MSVC is capable of calling typeid(T) even when RTTI is off +#if defined(BOOST_NO_RTTI) && !defined(BOOST_MSVC) +#error "File boost/type_index/stl_type_index.ipp is not usable when typeid() is not available." +#endif + +#include <typeinfo> +#include <cstring> // std::strcmp, std::strlen, std::strstr +#include <stdexcept> +#include <boost/static_assert.hpp> +#include <boost/throw_exception.hpp> +#include <boost/core/demangle.hpp> +#include <boost/type_traits/is_const.hpp> +#include <boost/type_traits/is_reference.hpp> +#include <boost/type_traits/is_volatile.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/or.hpp> +#include <boost/functional/hash_fwd.hpp> + +#if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ + || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) +# include <boost/type_traits/is_signed.hpp> +# include <boost/type_traits/make_signed.hpp> +# include <boost/mpl/identity.hpp> +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +namespace boost { namespace typeindex { + +/// \class stl_type_index +/// This class is a wrapper around std::type_info, that workarounds issues and provides +/// much more rich interface. \b For \b description \b of \b functions \b see type_index_facade. +/// +/// This class requires typeid() to work. For cases when RTTI is disabled see ctti_type_index. +class stl_type_index + : public type_index_facade< + stl_type_index, + #ifdef BOOST_NO_STD_TYPEINFO + type_info + #else + std::type_info + #endif + > +{ +public: +#ifdef BOOST_NO_STD_TYPEINFO + typedef type_info type_info_t; +#else + typedef std::type_info type_info_t; +#endif + +private: + const type_info_t* data_; + +public: + inline stl_type_index() BOOST_NOEXCEPT + : data_(&typeid(void)) + {} + + inline stl_type_index(const type_info_t& data) BOOST_NOEXCEPT + : data_(&data) + {} + + inline const type_info_t& type_info() const BOOST_NOEXCEPT; + + inline const char* raw_name() const BOOST_NOEXCEPT; + inline const char* name() const BOOST_NOEXCEPT; + inline std::string pretty_name() const; + + inline std::size_t hash_code() const BOOST_NOEXCEPT; + inline bool equal(const stl_type_index& rhs) const BOOST_NOEXCEPT; + inline bool before(const stl_type_index& rhs) const BOOST_NOEXCEPT; + + template <class T> + inline static stl_type_index type_id() BOOST_NOEXCEPT; + + template <class T> + inline static stl_type_index type_id_with_cvr() BOOST_NOEXCEPT; + + template <class T> + inline static stl_type_index type_id_runtime(const T& value) BOOST_NOEXCEPT; +}; + +inline const stl_type_index::type_info_t& stl_type_index::type_info() const BOOST_NOEXCEPT { + return *data_; +} + + +inline const char* stl_type_index::raw_name() const BOOST_NOEXCEPT { +#ifdef _MSC_VER + return data_->raw_name(); +#else + return data_->name(); +#endif +} + +inline const char* stl_type_index::name() const BOOST_NOEXCEPT { + return data_->name(); +} + +inline std::string stl_type_index::pretty_name() const { + static const char cvr_saver_name[] = "boost::typeindex::detail::cvr_saver<"; + static BOOST_CONSTEXPR_OR_CONST std::string::size_type cvr_saver_name_len = sizeof(cvr_saver_name) - 1; + + // In case of MSVC demangle() is a no-op, and name() already returns demangled name. + // In case of GCC and Clang (on non-Windows systems) name() returns mangled name and demangle() undecorates it. + const boost::core::scoped_demangled_name demangled_name(data_->name()); + + const char* begin = demangled_name.get(); + if (!begin) { + boost::throw_exception(std::runtime_error("Type name demangling failed")); + } + + const std::string::size_type len = std::strlen(begin); + const char* end = begin + len; + + if (len > cvr_saver_name_len) { + const char* b = std::strstr(begin, cvr_saver_name); + if (b) { + b += cvr_saver_name_len; + + // Trim leading spaces + while (*b == ' ') { // the string is zero terminated, we won't exceed the buffer size + ++ b; + } + + // Skip the closing angle bracket + const char* e = end - 1; + while (e > b && *e != '>') { + -- e; + } + + // Trim trailing spaces + while (e > b && *(e - 1) == ' ') { + -- e; + } + + if (b < e) { + // Parsing seems to have succeeded, the type name is not empty + begin = b; + end = e; + } + } + } + + return std::string(begin, end); +} + + +inline std::size_t stl_type_index::hash_code() const BOOST_NOEXCEPT { +#if _MSC_VER > 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__)) + return data_->hash_code(); +#else + return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name())); +#endif +} + + +/// @cond + +// for this compiler at least, cross-shared-library type_info +// comparisons don't work, so we are using typeid(x).name() instead. +# if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \ + || defined(_AIX) \ + || (defined(__sgi) && defined(__host_mips)) \ + || (defined(__hpux) && defined(__HP_aCC)) \ + || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) +# define BOOST_CLASSINFO_COMPARE_BY_NAMES +# endif + +/// @endcond + +inline bool stl_type_index::equal(const stl_type_index& rhs) const BOOST_NOEXCEPT { +#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name()); +#else + return *data_ == *rhs.data_; +#endif +} + +inline bool stl_type_index::before(const stl_type_index& rhs) const BOOST_NOEXCEPT { +#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0; +#else + return !!data_->before(*rhs.data_); +#endif +} + +#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES +#undef BOOST_CLASSINFO_COMPARE_BY_NAMES +#endif + + + +template <class T> +inline stl_type_index stl_type_index::type_id() BOOST_NOEXCEPT { + typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t; + typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_prefinal_t; + + # if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ + || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) + + // Old EDG-based compilers seem to mistakenly distinguish 'integral' from 'signed integral' + // in typeid() expressions. Full template specialization for 'integral' fixes that issue: + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_signed<no_cvr_prefinal_t>, + boost::make_signed<no_cvr_prefinal_t>, + boost::mpl::identity<no_cvr_prefinal_t> + >::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); +} + +namespace detail { + template <class T> class cvr_saver{}; +} + +template <class T> +inline stl_type_index stl_type_index::type_id_with_cvr() BOOST_NOEXCEPT { + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::mpl::or_<boost::is_reference<T>, boost::is_const<T>, boost::is_volatile<T> >, + detail::cvr_saver<T>, + T + >::type type; + + return typeid(type); +} + + +template <class T> +inline stl_type_index stl_type_index::type_id_runtime(const T& value) BOOST_NOEXCEPT { +#ifdef BOOST_NO_RTTI + return value.boost_type_index_type_id_runtime_(); +#else + return typeid(value); +#endif +} + +}} // namespace boost::typeindex + +#endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP diff --git a/boost/type_index/type_index_facade.hpp b/boost/type_index/type_index_facade.hpp new file mode 100644 index 0000000000..c18ea4bada --- /dev/null +++ b/boost/type_index/type_index_facade.hpp @@ -0,0 +1,296 @@ +// +// Copyright (c) Antony Polukhin, 2013-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_TYPE_INDEX_FACADE_HPP +#define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP + +#include <boost/config.hpp> +#include <boost/functional/hash_fwd.hpp> +#include <string> +#include <cstring> + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include <iosfwd> // for std::basic_ostream +#else +#include <ostream> +#endif +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +namespace boost { namespace typeindex { + +/// \class type_index_facade +/// +/// This class takes care about the comparison operators, hash functions and +/// ostream operators. Use this class as a public base class for defining new +/// type_info-conforming classes. +/// +/// \b Example: +/// \code +/// class stl_type_index: public type_index_facade<stl_type_index, std::type_info> +/// { +/// public: +/// typedef std::type_info type_info_t; +/// private: +/// const type_info_t* data_; +/// +/// public: +/// stl_type_index(const type_info_t& data) noexcept +/// : data_(&data) +/// {} +/// // ... +/// }; +/// \endcode +/// +/// \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 Derived, class TypeInfo> +class type_index_facade { +private: + /// @cond + const Derived & derived() const BOOST_NOEXCEPT { + return *static_cast<Derived const*>(this); + } + /// @endcond +public: + typedef TypeInfo type_info_t; + + /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. + /// \return Name of a type. By default returns Derived::raw_name(). + inline const char* name() const BOOST_NOEXCEPT { + return derived().raw_name(); + } + + /// \b Override: This function \b may be redefined in Derived class. Overrides may throw. + /// \return Human readable type name. By default returns Derived::name(). + inline std::string pretty_name() const { + return derived().name(); + } + + /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. + /// \return True if two types are equal. By default compares types by raw_name(). + inline bool equal(const Derived& rhs) const BOOST_NOEXCEPT { + const char* const left = derived().raw_name(); + const char* const right = rhs.raw_name(); + return left == right || !std::strcmp(left, right); + } + + /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. + /// \return True if rhs is greater than this. By default compares types by raw_name(). + inline bool before(const Derived& rhs) const BOOST_NOEXCEPT { + const char* const left = derived().raw_name(); + const char* const right = rhs.raw_name(); + return left != right && std::strcmp(left, right) < 0; + } + + /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. + /// \return Hash code of a type. By default hashes types by raw_name(). + /// \note <boost/functional/hash.hpp> has to be included if this function is used. + inline std::size_t hash_code() const BOOST_NOEXCEPT { + const char* const name = derived().raw_name(); + return boost::hash_range(name, name + std::strlen(name)); + } + +#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. + /// + /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw. + /// Overrides \b must remove const, volatile && and & modifiers from T. + /// \tparam T Type for which type_index must be created. + /// \return type_index for type T. + template <class T> + static Derived type_id() BOOST_NOEXCEPT; + + /// This is a factory method that is used to create instances of Derived classes. + /// boost::typeindex::type_id_with_cvr() will call this method, if Derived has same type as boost::typeindex::type_index. + /// + /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw. + /// Overrides \b must \b not remove const, volatile && and & modifiers from T. + /// \tparam T Type for which type_index must be created. + /// \return type_index for type T. + template <class T> + static Derived type_id_with_cvr() BOOST_NOEXCEPT; + + /// This is a factory method that is used to create instances of Derived classes. + /// boost::typeindex::type_id_runtime(const T&) will call this method, if Derived has same type as boost::typeindex::type_index. + /// + /// \b Override: This function \b may be redefined and made public in Derived class. + /// \param variable Variable which runtime type will be stored in type_index. + /// \return type_index with runtime type of variable. + template <class T> + static Derived type_id_runtime(const T& variable) BOOST_NOEXCEPT; + +#endif + +}; + +/// @cond +template <class Derived, class TypeInfo> +inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return static_cast<Derived const&>(lhs).equal(static_cast<Derived const&>(rhs)); +} + +template <class Derived, class TypeInfo> +inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return static_cast<Derived const&>(lhs).before(static_cast<Derived const&>(rhs));; +} + + + +template <class Derived, class TypeInfo> +inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return rhs < lhs; +} + +template <class Derived, class TypeInfo> +inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return !(lhs > rhs); +} + +template <class Derived, class TypeInfo> +inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return !(lhs < rhs); +} + +template <class Derived, class TypeInfo> +inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return !(lhs == rhs); +} + +// ######################### COMPARISONS with Derived ############################ // +template <class Derived, class TypeInfo> +inline bool operator == (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return Derived(lhs) == rhs; +} + +template <class Derived, class TypeInfo> +inline bool operator < (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return Derived(lhs) < rhs; +} + +template <class Derived, class TypeInfo> +inline bool operator > (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return rhs < Derived(lhs); +} + +template <class Derived, class TypeInfo> +inline bool operator <= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return !(Derived(lhs) > rhs); +} + +template <class Derived, class TypeInfo> +inline bool operator >= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return !(Derived(lhs) < rhs); +} + +template <class Derived, class TypeInfo> +inline bool operator != (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT { + return !(Derived(lhs) == rhs); +} + + +template <class Derived, class TypeInfo> +inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return lhs == Derived(rhs); +} + +template <class Derived, class TypeInfo> +inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return lhs < Derived(rhs); +} + +template <class Derived, class TypeInfo> +inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return Derived(rhs) < lhs; +} + +template <class Derived, class TypeInfo> +inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return !(lhs > Derived(rhs)); +} + +template <class Derived, class TypeInfo> +inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return !(lhs < Derived(rhs)); +} + +template <class Derived, class TypeInfo> +inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return !(lhs == Derived(rhs)); +} + +// ######################### COMPARISONS with Derived END ############################ // + +/// @endcond + +#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) + +/// noexcept comparison operators for type_index_facade classes. +bool operator ==, !=, <, ... (const type_index_facade& lhs, const type_index_facade& rhs) noexcept; + +/// noexcept comparison operators for type_index_facade and it's TypeInfo classes. +bool operator ==, !=, <, ... (const type_index_facade& lhs, const TypeInfo& rhs) noexcept; + +/// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes. +bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs) noexcept; + +#endif + +#ifndef BOOST_NO_IOSTREAM +#ifdef BOOST_NO_TEMPLATED_IOSTREAMS +/// @cond +/// Ostream operator that will output demangled name +template <class Derived, class TypeInfo> +inline std::ostream& operator<<(std::ostream& ostr, const type_index_facade<Derived, TypeInfo>& ind) { + ostr << static_cast<Derived const&>(ind).pretty_name(); + return ostr; +} +/// @endcond +#else +/// Ostream operator that will output demangled name. +template <class CharT, class TriatT, class Derived, class TypeInfo> +inline std::basic_ostream<CharT, TriatT>& operator<<( + std::basic_ostream<CharT, TriatT>& ostr, + const type_index_facade<Derived, TypeInfo>& ind) +{ + ostr << static_cast<Derived const&>(ind).pretty_name(); + return ostr; +} +#endif // BOOST_NO_TEMPLATED_IOSTREAMS +#endif // BOOST_NO_IOSTREAM + +/// This free function is used by Boost's unordered containers. +/// \note <boost/functional/hash.hpp> has to be included if this function is used. +template <class Derived, class TypeInfo> +inline std::size_t hash_value(const type_index_facade<Derived, TypeInfo>& lhs) BOOST_NOEXCEPT { + return static_cast<Derived const&>(lhs).hash_code(); +} + +}} // namespace boost::typeindex + +#endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP + |