From 683dab93a2cbebffaf71d3238fe4404693a4c1a6 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Fri, 7 Feb 2014 13:32:24 +0400 Subject: [PATCH] Reimplement and simplify design using type_index_facade class --- include/boost/type_index.hpp | 20 +- ...tti_type_index.ipp => ctti_type_index.hpp} | 80 ++++--- ...{stl_type_index.ipp => stl_type_index.hpp} | 190 +++++++++------- include/boost/type_index/type_index_base.hpp | 193 ----------------- .../boost/type_index/type_index_facade.hpp | 204 ++++++++++++++++++ 5 files changed, 382 insertions(+), 305 deletions(-) rename include/boost/type_index/{ctti_type_index.ipp => ctti_type_index.hpp} (53%) rename include/boost/type_index/{stl_type_index.ipp => stl_type_index.hpp} (65%) delete mode 100644 include/boost/type_index/type_index_base.hpp create mode 100644 include/boost/type_index/type_index_facade.hpp diff --git a/include/boost/type_index.hpp b/include/boost/type_index.hpp index 68385a0..e1994ee 100644 --- a/include/boost/type_index.hpp +++ b/include/boost/type_index.hpp @@ -27,18 +27,22 @@ #include -#if (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) -# include +#if defined(BOOST_TYPE_INDEX_USER_TYPEINFO) && defined(BOOST_TYPE_INDEX_USER_TYPEINFO_NAME) +# include BOOST_TYPE_INDEX_USER_TYPEINFO +#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) +# include #else -# include +# include #endif namespace boost { namespace typeind { -#if (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) - typedef boost::typeind::detail::type_index_base type_index; +#if defined(BOOST_TYPE_INDEX_USER_TYPEINFO) && defined(BOOST_TYPE_INDEX_USER_TYPEINFO_NAME) + typedef boost::typeind::detail::type_index_base type_index; +#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) + typedef boost::typeind::detail::stl_type_index type_index; #else - typedef boost::typeind::detail::type_index_base type_index; + typedef boost::typeind::detail::ctti_type_index type_index; #endif typedef type_index::type_info_t type_info; @@ -66,13 +70,13 @@ inline type_index type_id_with_cvr() BOOST_NOEXCEPT { /// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. template -inline type_index type_id_runtime(T& runtime_val) BOOST_NOEXCEPT { +inline type_index type_id_runtime(const T& runtime_val) BOOST_NOEXCEPT { return type_index::construct_runtime(runtime_val); } /// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info. template -inline type_index type_id_runtime(T* runtime_val) { +inline type_index type_id_runtime(const T* runtime_val) { return type_index::construct_runtime(runtime_val); } diff --git a/include/boost/type_index/ctti_type_index.ipp b/include/boost/type_index/ctti_type_index.hpp similarity index 53% rename from include/boost/type_index/ctti_type_index.ipp rename to include/boost/type_index/ctti_type_index.hpp index 56d8b26..241d8cc 100644 --- a/include/boost/type_index/ctti_type_index.ipp +++ b/include/boost/type_index/ctti_type_index.hpp @@ -6,8 +6,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_IPP -#define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_IPP +#ifndef BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP +#define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP // MS compatible compilers support #pragma once #if defined(_MSC_VER) @@ -25,7 +25,7 @@ /// is usually used instead of it (some compilers allow calling typeid(T) /// even if RTTI is disabled, those copilers will continue to use boost::type_info class). -#include +#include #include #include @@ -37,7 +37,7 @@ namespace boost { namespace typeind { namespace detail { struct ctti_data { - const char* const typename_; + const char* typename_; }; template @@ -47,75 +47,99 @@ inline const ctti_data& ctti_construct() BOOST_NOEXCEPT { } -template <> +class ctti_type_index: public type_index_facade { + const ctti_data* data_; + +public: + typedef ctti_data type_info_t; + + 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 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 ctti_type_index& rhs) const BOOST_NOEXCEPT; + inline bool before(const ctti_type_index& rhs) const BOOST_NOEXCEPT; + + template + inline static ctti_type_index construct() BOOST_NOEXCEPT; + + template + inline static ctti_type_index construct_with_cvr() BOOST_NOEXCEPT; + + template + inline static ctti_type_index construct_runtime(const T* variable) BOOST_NOEXCEPT; + + template + inline static ctti_type_index construct_runtime(const T& variable) BOOST_NOEXCEPT; +}; + + template -inline type_index_base type_index_base::construct() BOOST_NOEXCEPT { +inline ctti_type_index ctti_type_index::construct() BOOST_NOEXCEPT { typedef BOOST_DEDUCED_TYPENAME boost::remove_reference::type no_ref_t; typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cvr_t; return ctti_construct(); } -template <> + template -inline type_index_base type_index_base::construct_with_cvr() BOOST_NOEXCEPT { +inline ctti_type_index ctti_type_index::construct_with_cvr() BOOST_NOEXCEPT { return ctti_construct(); } -template <> template -inline type_index_base type_index_base::construct_runtime(T& rtti_val) BOOST_NOEXCEPT { +inline ctti_type_index ctti_type_index::construct_runtime(const T* rtti_val) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, - "type_id_runtime(T&) and type_index::construct_runtime(T&) require RTTI"); - + "type_id_runtime(const T*) and type_index::construct_runtime(const T*) require RTTI"); + return ctti_construct(); } - -template <> template -inline type_index_base type_index_base::construct_runtime(T* rtti_val) { +inline ctti_type_index ctti_type_index::construct_runtime(const T& rtti_val) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, - "type_id_runtime(T*) and type_index::construct_runtime(T*) require RTTI"); + "type_id_runtime(const T&) and type_index::construct_runtime(const T&) require RTTI"); return ctti_construct(); } -template <> -inline const char* type_index_base::raw_name() const BOOST_NOEXCEPT { +inline const char* ctti_type_index::raw_name() const BOOST_NOEXCEPT { return data_->typename_; } -template <> -inline const char* type_index_base::name() const BOOST_NOEXCEPT { +inline const char* ctti_type_index::name() const BOOST_NOEXCEPT { return data_->typename_; } -template <> -inline std::string type_index_base::pretty_name() const { +inline std::string ctti_type_index::pretty_name() const { std::size_t len = std::strlen(raw_name() + ctti_skip_size_at_end); while (raw_name()[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces return std::string(raw_name(), len); } -template <> -inline bool type_index_base::equal(const type_index_base& rhs) const BOOST_NOEXCEPT { +inline bool ctti_type_index::equal(const ctti_type_index& rhs) const BOOST_NOEXCEPT { return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name()); } -template <> -inline bool type_index_base::before(const type_index_base& rhs) const BOOST_NOEXCEPT { +inline bool ctti_type_index::before(const ctti_type_index& rhs) const BOOST_NOEXCEPT { return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0; } -template <> -inline std::size_t type_index_base::hash_code() const BOOST_NOEXCEPT { +inline std::size_t ctti_type_index::hash_code() const BOOST_NOEXCEPT { return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name() + detail::ctti_skip_size_at_end)); } diff --git a/include/boost/type_index/stl_type_index.ipp b/include/boost/type_index/stl_type_index.hpp similarity index 65% rename from include/boost/type_index/stl_type_index.ipp rename to include/boost/type_index/stl_type_index.hpp index 9c81d8f..e57ea98 100644 --- a/include/boost/type_index/stl_type_index.ipp +++ b/include/boost/type_index/stl_type_index.hpp @@ -6,8 +6,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef BOOST_TYPE_INDEX_STL_TYPE_INDEX_IPP -#define BOOST_TYPE_INDEX_STL_TYPE_INDEX_IPP +#ifndef BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP +#define BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP // MS compatible compilers support #pragma once #if defined(_MSC_VER) @@ -25,7 +25,7 @@ /// is usually used instead of it (some compilers allow calling typeid(T) /// even if RTTI is disabled, those copilers will continue to use boost::type_info class). -#include +#include // MSVC is capable of calling typeid(T) even when RTTI is off @@ -46,7 +46,7 @@ #ifdef __GNUC__ -#include +# include // abi::__cxa_demangle #endif #if !defined(BOOST_MSVC) @@ -61,62 +61,60 @@ namespace boost { namespace typeind { namespace detail { -template <> -template -inline type_index_base type_index_base::construct() BOOST_NOEXCEPT { - typedef BOOST_DEDUCED_TYPENAME boost::remove_reference::type no_ref_t; - typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cvr_t; - - # if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ - || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) - BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic::type::value - , "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions."); - #endif - - return typeid(no_cvr_t); -} - - -template <> -template -inline type_index_base type_index_base::construct_with_cvr() BOOST_NOEXCEPT { - typedef typename boost::mpl::if_c< - boost::is_reference::value - || boost::is_const::value - || boost::is_volatile::value, - detail::cvr_saver, - T - >::type type; - - return typeid(type); -} - - -template <> -template -inline type_index_base type_index_base::construct_runtime(T& rtti_val) BOOST_NOEXCEPT { -#ifdef BOOST_NO_RTTI - BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, - "type_id_runtime(T&) and type_index::construct_runtime(T&) require RTTI"); +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 - - return typeid(rtti_val); + +private: + const type_info_t* data_; + +public: + 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 + inline static stl_type_index construct() BOOST_NOEXCEPT; + + template + inline static stl_type_index construct_with_cvr() BOOST_NOEXCEPT; + + template + inline static stl_type_index construct_runtime(const T* variable); + + template + inline static stl_type_index construct_runtime(const T& value) BOOST_NOEXCEPT; +}; + +inline const stl_type_index::type_info_t& stl_type_index::type_info() const BOOST_NOEXCEPT { + return *data_; } -template <> -template -inline type_index_base type_index_base::construct_runtime(T* rtti_val) { -#ifdef BOOST_NO_RTTI - BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, - "type_id_runtime(T*) and type_index::construct_runtime(T*) require RTTI"); -#endif - return typeid(rtti_val); -} - - -template <> -inline const char* type_index_base::raw_name() const BOOST_NOEXCEPT { +inline const char* stl_type_index::raw_name() const BOOST_NOEXCEPT { #ifdef _MSC_VER return data_->raw_name(); #else @@ -124,14 +122,11 @@ inline const char* type_index_base::raw_name() const BOOST_NOEXC #endif } - -template <> -inline const char* type_index_base::name() const BOOST_NOEXCEPT { +inline const char* stl_type_index::name() const BOOST_NOEXCEPT { return data_->name(); } -template <> -inline std::string type_index_base::pretty_name() const { +inline std::string stl_type_index::pretty_name() const { #if defined(_MSC_VER) std::string ret = data_->name(); #else @@ -169,6 +164,15 @@ inline std::string type_index_base::pretty_name() const { } +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 @@ -183,9 +187,7 @@ inline std::string type_index_base::pretty_name() const { /// @endcond - -template <> -inline bool type_index_base::equal(const type_index_base& rhs) const BOOST_NOEXCEPT { +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 @@ -193,9 +195,7 @@ inline bool type_index_base::equal(const type_index_base -inline bool type_index_base::before(const type_index_base& rhs) const BOOST_NOEXCEPT { +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 @@ -203,24 +203,62 @@ inline bool type_index_base::before(const type_index_base -inline std::size_t type_index_base::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 + +template +inline stl_type_index stl_type_index::construct() BOOST_NOEXCEPT { + typedef BOOST_DEDUCED_TYPENAME boost::remove_reference::type no_ref_t; + typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cvr_t; + + # if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ + || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) + BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic::type::value + , "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions."); + #endif + + return typeid(no_cvr_t); } +template class cvr_saver{}; + + +template +inline stl_type_index stl_type_index::construct_with_cvr() BOOST_NOEXCEPT { + typedef typename boost::mpl::if_c< + boost::is_reference::value + || boost::is_const::value + || boost::is_volatile::value, + cvr_saver, + T + >::type type; + + return typeid(type); +} + +template +inline stl_type_index stl_type_index::construct_runtime(const T* rtti_val) { +#ifdef BOOST_NO_RTTI + BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, + "type_id_runtime(const T*) and type_index::construct_runtime(const T*) require RTTI"); +#endif + return typeid(rtti_val); +} + +template +inline stl_type_index stl_type_index::construct_runtime(const T& value) BOOST_NOEXCEPT { +#ifdef BOOST_NO_RTTI + BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, + "type_id_runtime(const T&) and type_index::construct_runtime(const T&) require RTTI"); +#endif + return typeid(value); +} }}} // namespace boost::typeind::detail -#endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_IPP +#endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP diff --git a/include/boost/type_index/type_index_base.hpp b/include/boost/type_index/type_index_base.hpp deleted file mode 100644 index ed49f11..0000000 --- a/include/boost/type_index/type_index_base.hpp +++ /dev/null @@ -1,193 +0,0 @@ -// -// 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_BASE_HPP -#define BOOST_TYPE_INDEX_TYPE_INDEX_BASE_HPP - -// MS compatible compilers support #pragma once -#if defined(_MSC_VER) -# pragma once -#endif - -#include -#include - -#if !defined(BOOST_NO_IOSTREAM) -#if !defined(BOOST_NO_IOSFWD) -#include // for std::basic_ostream -#else -#include -#endif -#endif - -namespace boost { namespace typeind { namespace detail { - -template class cvr_saver{}; - -template -class type_index_base { - const TypeInfo* data_; - -public: - typedef TypeInfo type_info_t; - typedef type_index_base this_type; - - type_index_base(const TypeInfo& info) BOOST_NOEXCEPT - : data_(&info) - {} - - const type_info_t& type_info() const BOOST_NOEXCEPT { - return *data_; - } - - // All of the following methods must be explicitly specialized for each type_index_base. - const char* raw_name() const BOOST_NOEXCEPT; - const char* name() const BOOST_NOEXCEPT; - std::string pretty_name() const; - std::size_t hash_code() const BOOST_NOEXCEPT; - bool equal(const this_type& rhs) const BOOST_NOEXCEPT; - bool before(const this_type& rhs) const BOOST_NOEXCEPT; - - template - static this_type construct() BOOST_NOEXCEPT; - template - static this_type construct_with_cvr() BOOST_NOEXCEPT; - template - static this_type construct_runtime(T&) BOOST_NOEXCEPT; - template - static this_type construct_runtime(T* rtti_val); -}; - - -template -inline bool operator == (const type_index_base& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return lhs.equal(rhs); -} - -template -inline bool operator < (const type_index_base& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return lhs.before(rhs); -} - - - -template -inline bool operator > (const type_index_base& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return rhs < lhs; -} - -template -inline bool operator <= (const type_index_base& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return !(lhs > rhs); -} - -template -inline bool operator >= (const type_index_base& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return !(lhs < rhs); -} - -template -inline bool operator != (const type_index_base& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return !(lhs == rhs); -} - -// ######################### COMPARISONS with TypeInfo ############################ // -template -inline bool operator == (const TypeInfo& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return type_index_base(lhs) == rhs; -} - -template -inline bool operator < (const TypeInfo& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return type_index_base(lhs) < rhs; -} - -template -inline bool operator > (const TypeInfo& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return rhs < type_index_base(lhs); -} - -template -inline bool operator <= (const TypeInfo& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return !(type_index_base(lhs) > rhs); -} - -template -inline bool operator >= (const TypeInfo& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return !(type_index_base(lhs) < rhs); -} - -template -inline bool operator != (const TypeInfo& lhs, const type_index_base& rhs) BOOST_NOEXCEPT { - return !(type_index_base(lhs) == rhs); -} - - -template -inline bool operator == (const type_index_base& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return lhs == type_index_base(rhs); -} - -template -inline bool operator < (const type_index_base& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return lhs < type_index_base(rhs); -} - -template -inline bool operator > (const type_index_base& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return type_index_base(rhs) < lhs; -} - -template -inline bool operator <= (const type_index_base& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return !(lhs > type_index_base(rhs)); -} - -template -inline bool operator >= (const type_index_base& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return !(lhs < type_index_base(rhs)); -} - -template -inline bool operator != (const type_index_base& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return !(lhs == type_index_base(rhs)); -} - -// ######################### COMPARISONS with TypeInfo END ############################ // - - -#ifndef BOOST_NO_IOSTREAM -#ifdef BOOST_NO_TEMPLATED_IOSTREAMS -/// Ostream operator that will output demangled name -template -inline std::ostream& operator<<(std::ostream& ostr, const type_index_base& ind) { - ostr << ind.pretty_name(); - return ostr; -} -#else -/// Ostream operator that will output demangled name -template -inline std::basic_ostream& operator<<( - std::basic_ostream& ostr, - const type_index_base& ind) -{ - ostr << ind.pretty_name(); - return ostr; -} -#endif // BOOST_NO_TEMPLATED_IOSTREAMS -#endif // BOOST_NO_IOSTREAM - -template -inline std::size_t hash_value(const type_index_base& lhs) BOOST_NOEXCEPT { - return lhs.hash_code(); -} - -}}} // namespace boost::typeind::detail - -#endif // BOOST_TYPE_INDEX_TYPE_INDEX_BASE_HPP - diff --git a/include/boost/type_index/type_index_facade.hpp b/include/boost/type_index/type_index_facade.hpp new file mode 100644 index 0000000..577bcb5 --- /dev/null +++ b/include/boost/type_index/type_index_facade.hpp @@ -0,0 +1,204 @@ +// +// 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 + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream +#else +#include +#endif +#endif + +namespace boost { namespace typeind { namespace detail { + +/// type_index_facade - use as a public base class for defining new +/// standard-conforming iterators. +/// +template +class type_index_facade { +private: + Derived& derived() BOOST_NOEXCEPT { + return *static_cast(this); + } + + const Derived & derived() const BOOST_NOEXCEPT { + return *static_cast(this); + } + +public: + typedef TypeInfo type_info_t; + typedef type_index_facade this_type; + + const type_info_t& type_info() const BOOST_NOEXCEPT { + return derived().type_info(); + } + + inline const char* raw_name() const BOOST_NOEXCEPT { + return derived().raw_name(); + } + + inline const char* name() const BOOST_NOEXCEPT { + return derived().name(); + } + + inline std::string pretty_name() const { + return derived().pretty_name(); + } + + inline std::size_t hash_code() const BOOST_NOEXCEPT { + return derived().hash_code(); + } + + inline bool equal(const this_type& rhs) const BOOST_NOEXCEPT { + return derived().equal(rhs.derived()); + } + + inline bool before(const this_type& rhs) const BOOST_NOEXCEPT { + return derived().before(rhs.derived()); + } +}; + + +template +inline bool operator == (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return lhs.equal(rhs); +} + +template +inline bool operator < (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return lhs.before(rhs); +} + + + +template +inline bool operator > (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return rhs < lhs; +} + +template +inline bool operator <= (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return !(lhs > rhs); +} + +template +inline bool operator >= (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return !(lhs < rhs); +} + +template +inline bool operator != (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return !(lhs == rhs); +} + +// ######################### COMPARISONS with Derived ############################ // +template +inline bool operator == (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return Derived(lhs) == rhs; +} + +template +inline bool operator < (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return Derived(lhs) < rhs; +} + +template +inline bool operator > (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return rhs < Derived(lhs); +} + +template +inline bool operator <= (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return !(Derived(lhs) > rhs); +} + +template +inline bool operator >= (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return !(Derived(lhs) < rhs); +} + +template +inline bool operator != (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { + return !(Derived(lhs) == rhs); +} + + +template +inline bool operator == (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return lhs == Derived(rhs); +} + +template +inline bool operator < (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return lhs < Derived(rhs); +} + +template +inline bool operator > (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return Derived(rhs) < lhs; +} + +template +inline bool operator <= (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return !(lhs > Derived(rhs)); +} + +template +inline bool operator >= (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return !(lhs < Derived(rhs)); +} + +template +inline bool operator != (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { + return !(lhs == Derived(rhs)); +} + +// ######################### COMPARISONS with Derived END ############################ // + + +#ifndef BOOST_NO_IOSTREAM +#ifdef BOOST_NO_TEMPLATED_IOSTREAMS +/// Ostream operator that will output demangled name +template +inline std::ostream& operator<<(std::ostream& ostr, const type_index_facade& ind) { + ostr << ind.pretty_name(); + return ostr; +} +#else +/// Ostream operator that will output demangled name +template +inline std::basic_ostream& operator<<( + std::basic_ostream& ostr, + const type_index_facade& ind) +{ + ostr << ind.pretty_name(); + return ostr; +} +#endif // BOOST_NO_TEMPLATED_IOSTREAMS +#endif // BOOST_NO_IOSTREAM + +template +inline std::size_t hash_value(const type_index_facade& lhs) BOOST_NOEXCEPT { + return lhs.hash_code(); +} + +}}} // namespace boost::typeind::detail + +#endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP +