diff options
Diffstat (limited to 'contrib/src/boost/type_index')
-rw-r--r-- | contrib/src/boost/type_index/ctti_type_index.hpp | 212 | ||||
-rw-r--r-- | contrib/src/boost/type_index/detail/compile_time_type_info.hpp | 289 | ||||
-rw-r--r-- | contrib/src/boost/type_index/detail/ctti_register_class.hpp | 40 | ||||
-rw-r--r-- | contrib/src/boost/type_index/detail/stl_register_class.hpp | 40 | ||||
-rw-r--r-- | contrib/src/boost/type_index/stl_type_index.hpp | 272 | ||||
-rw-r--r-- | contrib/src/boost/type_index/type_index_facade.hpp | 300 |
6 files changed, 1153 insertions, 0 deletions
diff --git a/contrib/src/boost/type_index/ctti_type_index.hpp b/contrib/src/boost/type_index/ctti_type_index.hpp new file mode 100644 index 0000000..611ad92 --- /dev/null +++ b/contrib/src/boost/type_index/ctti_type_index.hpp @@ -0,0 +1,212 @@ +// +// Copyright (c) Antony Polukhin, 2013-2016. +// +// +// 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 that is constexpr if C++14 constexpr is supported by compiler. +/// +/// 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 on C++14 compatible compilers has following functions marked as constexpr: +/// * default constructor +/// * copy constructors and assignemnt operations +/// * class methods: name(), before(const ctti_type_index& rhs), equal(const ctti_type_index& rhs) +/// * static methods type_id<T>(), type_id_with_cvr<T>() +/// * comparison operators +/// +/// 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 char* data_; + + inline std::size_t get_raw_name_length() const BOOST_NOEXCEPT; + + BOOST_CXX14_CONSTEXPR inline explicit ctti_type_index(const char* data) BOOST_NOEXCEPT + : data_(data) + {} + +public: + typedef detail::ctti_data type_info_t; + + BOOST_CXX14_CONSTEXPR inline ctti_type_index() BOOST_NOEXCEPT + : data_(boost::detail::ctti<void>::n()) + {} + + inline ctti_type_index(const type_info_t& data) BOOST_NOEXCEPT + : data_(reinterpret_cast<const char*>(&data)) + {} + + inline const type_info_t& type_info() const BOOST_NOEXCEPT; + BOOST_CXX14_CONSTEXPR inline const char* raw_name() const BOOST_NOEXCEPT; + BOOST_CXX14_CONSTEXPR inline const char* name() const BOOST_NOEXCEPT; + inline std::string pretty_name() const; + inline std::size_t hash_code() const BOOST_NOEXCEPT; + + BOOST_CXX14_CONSTEXPR inline bool equal(const ctti_type_index& rhs) const BOOST_NOEXCEPT; + BOOST_CXX14_CONSTEXPR inline bool before(const ctti_type_index& rhs) const BOOST_NOEXCEPT; + + template <class T> + BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id() BOOST_NOEXCEPT; + + template <class T> + BOOST_CXX14_CONSTEXPR 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 *reinterpret_cast<const detail::ctti_data*>(data_); +} + + +BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::equal(const ctti_type_index& rhs) const BOOST_NOEXCEPT { + const char* const left = raw_name(); + const char* const right = rhs.raw_name(); + return /*left == right ||*/ !boost::typeindex::detail::constexpr_strcmp(left, right); +} + +BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::before(const ctti_type_index& rhs) const BOOST_NOEXCEPT { + const char* const left = raw_name(); + const char* const right = rhs.raw_name(); + return /*left != right &&*/ boost::typeindex::detail::constexpr_strcmp(left, right) < 0; +} + + +template <class T> +BOOST_CXX14_CONSTEXPR 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_type_index(boost::detail::ctti<no_cvr_t>::n()); +} + + + +template <class T> +BOOST_CXX14_CONSTEXPR inline ctti_type_index ctti_type_index::type_id_with_cvr() BOOST_NOEXCEPT { + return ctti_type_index(boost::detail::ctti<T>::n()); +} + + +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_(); +} + + +BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::raw_name() const BOOST_NOEXCEPT { + return data_; +} + + +BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::name() const BOOST_NOEXCEPT { + return 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/contrib/src/boost/type_index/detail/compile_time_type_info.hpp b/contrib/src/boost/type_index/detail/compile_time_type_info.hpp new file mode 100644 index 0000000..a2a89ae --- /dev/null +++ b/contrib/src/boost/type_index/detail/compile_time_type_info.hpp @@ -0,0 +1,289 @@ +// +// Copyright (c) Antony Polukhin, 2012-2016. +// +// +// 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> + +#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) && 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. + // + // 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__ >= 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__) && !defined(BOOST_NO_CXX14_CONSTEXPR) + // sizeof("static contexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0u; T = ") - 1, sizeof("]") - 1 + BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(81, 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 + // 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> + BOOST_CXX14_CONSTEXPR 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 <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 <unsigned int ArrayLength> + 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 <unsigned int ArrayLength> + 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 + ); + return (it == begin + ArrayLength ? begin : it + sizeof(ctti_skip_until_runtime) - 1); + } + + template <unsigned int ArrayLength> + 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 <unsigned int... I> + struct index_seq {}; + + template <typename Left, typename Right> + struct make_index_sequence_join; + + template <unsigned int... Left, unsigned int... Right> + struct make_index_sequence_join<index_seq<Left...>, index_seq<Right...> > { + typedef index_seq<Left..., Right...> type; + }; + + template <unsigned int C, unsigned int 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 <unsigned int C> + struct make_index_seq_impl<C, 0> { + typedef index_seq<> type; + }; + + template <unsigned int C> + struct make_index_seq_impl<C, 1> { + typedef index_seq<C> type; + }; + + template <char... C> + struct cstring { + static constexpr unsigned int 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 { + +/// 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 { + +#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) + //helper functions + template <unsigned int I> + constexpr static char s() BOOST_NOEXCEPT { // step + constexpr unsigned int 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 <unsigned int ...Indexes> + constexpr static const char* impl(::boost::typeindex::detail::index_seq<Indexes...> ) BOOST_NOEXCEPT { + return ::boost::typeindex::detail::cstring<s<Indexes>()...>::data_; + } + + template <unsigned int D = 0> // `D` means `Dummy` + constexpr static const char* n() BOOST_NOEXCEPT { + #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) + constexpr unsigned int size = sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE); + #elif defined(__FUNCSIG__) + constexpr unsigned int 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 unsigned int 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 + 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); + #elif defined(__FUNCSIG__) + return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__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__) + return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__); + #else + boost::typeindex::detail::failed_to_get_function_name(); + return ""; + #endif + } +#endif +}; + +}} // namespace boost::detail + +#endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP + diff --git a/contrib/src/boost/type_index/detail/ctti_register_class.hpp b/contrib/src/boost/type_index/detail/ctti_register_class.hpp new file mode 100644 index 0000000..a8cef2c --- /dev/null +++ b/contrib/src/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/contrib/src/boost/type_index/detail/stl_register_class.hpp b/contrib/src/boost/type_index/detail/stl_register_class.hpp new file mode 100644 index 0000000..95a26f7 --- /dev/null +++ b/contrib/src/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/contrib/src/boost/type_index/stl_type_index.hpp b/contrib/src/boost/type_index/stl_type_index.hpp new file mode 100644 index 0000000..a5add88 --- /dev/null +++ b/contrib/src/boost/type_index/stl_type_index.hpp @@ -0,0 +1,272 @@ +// +// Copyright (c) Antony Polukhin, 2013-2015. +// +// +// 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> + +#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/contrib/src/boost/type_index/type_index_facade.hpp b/contrib/src/boost/type_index/type_index_facade.hpp new file mode 100644 index 0000000..dd35df2 --- /dev/null +++ b/contrib/src/boost/type_index/type_index_facade.hpp @@ -0,0 +1,300 @@ +// +// Copyright (c) Antony Polukhin, 2013-2015. +// +// +// 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 <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 + +// Forward declaration from #include <boost/functional/hash_fwd.hpp> +namespace boost { + template <class It> std::size_t hash_range(It, It); +} + +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 + BOOST_CXX14_CONSTEXPR 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_raw = derived().raw_name(); + return boost::hash_range(name_raw, name_raw + std::strlen(name_raw)); + } + +#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> +BOOST_CXX14_CONSTEXPR 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> +BOOST_CXX14_CONSTEXPR 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> +BOOST_CXX14_CONSTEXPR 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> +BOOST_CXX14_CONSTEXPR 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> +BOOST_CXX14_CONSTEXPR 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> +BOOST_CXX14_CONSTEXPR 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 + |