From d66810d2cc5ec75171f8a0a3fc15fd48b96408a7 Mon Sep 17 00:00:00 2001 From: ontoquad Date: Thu, 10 Oct 2013 17:47:30 +0400 Subject: [PATCH] Single type_index.hpp file was split to a few smaller Implementing feature request of Boost.Log maintainer: Now you can choose and include only the RTTI based version or only the CTTI based version. More tests added. --- boost/type_index.hpp | 543 +----------------- boost/type_index/template_index_impl.hpp | 243 ++++++++ boost/type_index/type_index_impl.hpp | 324 +++++++++++ boost/type_index/type_index_minimal.hpp | 34 ++ libs/type_index/test/Jamfile.v2 | 5 +- libs/type_index/test/template_index_test.cpp | 21 + libs/type_index/test/template_index_tests.ipp | 159 +++++ libs/type_index/test/testing_both.cpp | 22 + libs/type_index/test/type_index_test.cpp | 338 +---------- libs/type_index/test/type_index_tests.ipp | 205 +++++++ 10 files changed, 1017 insertions(+), 877 deletions(-) create mode 100644 boost/type_index/template_index_impl.hpp create mode 100644 boost/type_index/type_index_impl.hpp create mode 100644 boost/type_index/type_index_minimal.hpp create mode 100644 libs/type_index/test/template_index_test.cpp create mode 100644 libs/type_index/test/template_index_tests.ipp create mode 100644 libs/type_index/test/testing_both.cpp create mode 100644 libs/type_index/test/type_index_tests.ipp diff --git a/boost/type_index.hpp b/boost/type_index.hpp index 91d3c62..f211119 100644 --- a/boost/type_index.hpp +++ b/boost/type_index.hpp @@ -1,6 +1,5 @@ // -// Copyright (c) Antony Polukhin, 2012. -// +// Copyright (c) Antony Polukhin, 2012-2013. // // 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) @@ -14,543 +13,7 @@ # pragma once #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef BOOST_NO_RTTI -#include -#endif - -#if !defined(BOOST_NO_IOSTREAM) -#if !defined(BOOST_NO_IOSFWD) -#include // for std::basic_ostream -#else -#include -#endif -#endif - -#ifdef __GNUC__ -#include -#endif - -namespace boost { - -namespace detail { -#if defined(BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP) && defined(BOOST_TYPE_INDEX_CTTI_END_SKIP) - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP); // skip user specified bytes count - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = BOOST_TYPE_INDEX_CTTI_END_SKIP); // skip user specified bytes count -#elif defined _MSC_VER - // sizeof("const char *__cdecl boost::detail::ctti<") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 40); - - // sizeof(">::n(void)") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 10); - -#elif defined __clang__ - // sizeof("static const char *boost::detail::ctti<") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 39); - - // == sizeof(">::n()") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 6); -#elif defined __GNUC__ - // sizeof("static const char* boost::detail::ctti::n() [with T = ") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 57); - - // == sizeof("]") - 1 - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 1); - -#else - // TODO: Code for other platforms - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 0); // skip nothing - BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 0); // skip nothing -#endif - - /// Noncopyable type_info that does not require RTTI - /// CTTI == Compile Time Type Info - /// This name must be as short as posible, to avoid code bloat - template - struct ctti { - typedef T template_type; - typedef ctti this_type; - - /// Returns raw name. Must be as short, as possible, to avoid code bloat - static const char* n() BOOST_NOEXCEPT { - return BOOST_CURRENT_FUNCTION + detail::ctti_skip_size_at_begin; - } - - /// Returns raw name - static const char* name() BOOST_NOEXCEPT { - return this_type::n(); - } - - /// Returns true if the type precedes the type of rhs in the collation order. - /// The collation order is just an internal order. - template - static bool before() BOOST_NOEXCEPT { - return std::strcmp(this_type::n(), ctti::n()) < 0; - } - - /// Returns length of demangled name - static std::size_t name_length() BOOST_NOEXCEPT { - return std::strlen(this_type::n() + detail::ctti_skip_size_at_end); - } - - /// Returns user-friendly name - static std::string name_demangled() BOOST_NOEXCEPT { - return std::string(this_type::n(), this_type::name_length()); - } - }; -} // namespace detail - -/// Copyable type_info that does not require RTTI and could store const, -/// volatile and references if constructed via construct_with_cvr() -class template_index { -private: - const char* name_; - - /// @cond - explicit template_index(const char* name) BOOST_NOEXCEPT - : name_(name) - {} - /// @endcond - -public: - /// Default constructor. - template_index() BOOST_NOEXCEPT - : name_(detail::ctti::name()) - {} - - /// Factory method for constructing template_index instance for type T. - /// Strips const, volatile and & modifiers from T - template - static template_index construct(){ - 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 template_index(detail::ctti::name()); - } - - /// Factory method for constructing template_index instance for type T. - /// Does not strips const, volatile and & modifiers from T - template - static template_index construct_with_cvr() { - # 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 template_index(detail::ctti::name()); - } - - - /// Returns true if the type precedes the type of rhs in the collation order. - /// The collation order is just an internal order. - bool before(const template_index& rhs) const BOOST_NOEXCEPT { - return std::strcmp(name(), rhs.name()) < 0; - } - - /// Returns raw name - const char* name() const BOOST_NOEXCEPT { - return name_; - } - - /// Returns user-friendly name - std::string name_demangled() const { - return std::string(name_, std::strlen(name_ + detail::ctti_skip_size_at_end)); - } - - /// @cond - bool operator == (const template_index& rhs) const BOOST_NOEXCEPT { - return !std::strcmp(name_, rhs.name()); - } - - bool operator != (const template_index& rhs) const BOOST_NOEXCEPT { - return !!std::strcmp(name_, rhs.name()); - } - - bool operator < (const template_index& rhs) const BOOST_NOEXCEPT { - return std::strcmp(name_, rhs.name()) < 0; - } - - bool operator > (const template_index& rhs) const BOOST_NOEXCEPT { - return std::strcmp(name_, rhs.name()) > 0; - } - - bool operator <= (const template_index& rhs) const BOOST_NOEXCEPT { - return std::strcmp(name_, rhs.name()) <= 0; - } - - bool operator >= (const template_index& rhs) const BOOST_NOEXCEPT { - return std::strcmp(name_, rhs.name()) >= 0; - } - /// @endcond - - /// Function for getting hash value - std::size_t hash_code() const BOOST_NOEXCEPT { - return boost::hash_range(name_, name_ + std::strlen(name_ + detail::ctti_skip_size_at_end)); - } -}; - -/// Method for constructing template_index instance for type T. -/// Strips const, volatile and & modifiers from T. -template -template_index template_id() BOOST_NOEXCEPT { - return template_index::construct(); -} - -/// Factory method for constructing template_index instance for type T. -/// Does not strips const, volatile and & modifiers from T. -template -template_index template_id_with_cvr() BOOST_NOEXCEPT { - return template_index::construct_with_cvr(); -} - -#ifndef BOOST_NO_RTTI - - -#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED - -// for this compiler at least, cross-shared-library type_info -// comparisons don't work, so use typeid(x).name() instead. It's not -// yet clear what the best default strategy is. -# if (defined(__GNUC__) && __GNUC__ >= 3 && __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 -# define BOOST_CLASSINFO_COMPARISON_NOEXCEPT -#else -# define BOOST_CLASSINFO_COMPARISON_NOEXCEPT BOOST_NOEXCEPT -# endif - -#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED - -/// Copyable type_info class that requires RTTI. -class type_index { -public: - -#ifdef BOOST_NO_STD_TYPEINFO - typedef type_info stl_type_info; -#else - typedef std::type_info stl_type_info; -#endif - -private: - const stl_type_info* pinfo_; - -public: - /// Default constructor. - type_index() - : pinfo_(&typeid(void)) - {} - - /// Constructs type_index from an instance of std::type_info. - explicit type_index(const stl_type_info& inf) BOOST_NOEXCEPT - : pinfo_(&inf) - {} - - /// Factory method for constructing type_index instance for type T. - /// Strips const, volatile and & modifiers from T. - template - static type_index construct() { - 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 type_index(typeid(no_cvr_t)); - } - - /// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. - /// This method available only with RTTI enabled. - template - static type_index construct_rtti_only(T& rtti_val) { - return type_index(typeid(rtti_val)); - } - - /// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. - /// This method available only with RTTI enabled. - template - static type_index construct_rtti_only(T* rtti_val) { - return type_index(typeid(rtti_val)); - } - - /// Returns true if the type precedes the type of rhs in the collation order. - /// The collation order is just an internal order. - bool before(type_index const& rhs) const BOOST_NOEXCEPT { - return !!pinfo_->before(*rhs.pinfo_); - } - - /// Returns raw name - const char* name() const { - #ifdef _MSC_VER - return pinfo_->raw_name(); - #else - return pinfo_->name(); - #endif - } - - /// Returns user-friendly name - std::string name_demangled() const { - #if defined(__GNUC__) - int status = 0 ; - char* demang = abi::__cxa_demangle(pinfo_->name(), NULL, 0, &status); - BOOST_ASSERT(!status); - std::string ret(demang); - free(demang); - return ret; - #else - return pinfo_->name(); - #endif - } - -#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED - bool operator == (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES - return !std::strcmp(pinfo_->name(), rhs.pinfo_->name()); - #else - return *pinfo_ == *rhs.pinfo_; - #endif - } - - bool operator != (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return !(*this == rhs); - } - - bool operator < (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES - return std::strcmp(pinfo_->name(), rhs.pinfo_->name()) < 0; - #else - return before(rhs); - #endif - } - - bool operator > (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return (rhs < *this); - } - - bool operator <= (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return !(*this > rhs); - } - - bool operator >= (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return !(*this < rhs); - } - - bool operator == (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES - return !std::strcmp(pinfo_->name(), rhs.name()); - #else - return *pinfo_ == rhs; - #endif - } - - bool operator != (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return !(*this == rhs); - } - - bool operator < (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES - return std::strcmp(pinfo_->name(), rhs.name()) < 0; - #else - return !!pinfo_->before(rhs); - #endif - } - - bool operator > (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES - return std::strcmp(pinfo_->name(), rhs.name()) > 0; - #else - return !!rhs.before(*pinfo_); - #endif - } - - bool operator <= (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return !(*this > rhs); - } - - bool operator >= (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return !(*this < rhs); - } -#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED - - /// Function for getting hash value - std::size_t hash_code() const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { -#if _MSC_VER >= 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__)) - return pinfo_->hash_code(); -#else - return boost::hash_range(name(), name() + std::strlen(name())); -#endif - } -}; - -#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED - -inline bool operator == (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return rhs == lhs; // Operation is commutative -} - -inline bool operator != (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return rhs != lhs; // Operation is commutative -} - -inline bool operator < (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return rhs > lhs; -} - -inline bool operator > (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return rhs < lhs; -} - -inline bool operator <= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return rhs >= lhs; -} - -inline bool operator >= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { - return rhs <= lhs; -} - -#undef BOOST_CLASSINFO_COMPARISON_NOEXCEPT - -#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED - - - -#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES -#undef BOOST_CLASSINFO_COMPARE_BY_NAMES -#endif - -/// @endcond - -/// Function, to get type_index for a type T. Strips const, volatile and & modifiers from T. -template -type_index type_id() { - return type_index::construct(); -} - -/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. -/// This method available only with RTTI enabled. -template -type_index type_id_rtti_only(T& rtti_val) { - return type_index::construct_rtti_only(rtti_val); -} - -/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. -/// This method available only with RTTI enabled. -template -type_index type_id_rtti_only(T* rtti_val) { - return type_index::construct_rtti_only(rtti_val); -} - -/* *************** type_index free functions ******************* */ - -/// @cond - -#ifndef BOOST_NO_IOSTREAM -#ifdef BOOST_NO_TEMPLATED_IOSTREAMS - -/// Ostream operator that will output demangled name. -inline std::ostream& operator<<(std::ostream& ostr, type_index const& ind) { - ostr << ind.name_demangled(); - return ostr; -} -#else - -/// Ostream operator that will output demangled name. -template -inline std::basic_ostream& operator<<(std::basic_ostream& ostr, type_index const& ind) { - ostr << ind.name_demangled(); - return ostr; -} -#endif - -#endif - -/// hash_value function overload for type_index. -inline std::size_t hash_value(type_index const& v) { - return v.hash_code(); -} - -/// @endcond - -#else -// BOOST_NO_RTTI is defined - -typedef template_index type_index; - -template -type_index type_id() { - return template_index::construct(); -} - -#endif - - -/* *************** template_index free functions ******************* */ - -/// @cond - -#ifndef BOOST_NO_IOSTREAM -#ifdef BOOST_NO_TEMPLATED_IOSTREAMS -/// Ostream operator that will output demangled name -inline std::ostream& operator<<(std::ostream& ostr, template_index const& ind) { - ostr << ind.name_demangled(); - return ostr; -} -#else -/// Ostream operator that will output demangled name -template -inline std::basic_ostream& operator<<(std::basic_ostream& ostr, template_index const& ind) { - ostr << ind.name_demangled(); - return ostr; -} -#endif -#endif - -/// hash_value function overload for template_index -inline std::size_t hash_value(template_index const& v) BOOST_NOEXCEPT { - return v.hash_code(); -} - -/// @endcond - -#ifdef BOOST_TYPE_INDEX_DOXYGEN_INVOKED - -/// Output operators for type_index and template_index -std::basic_ostream& operator<<(std::basic_ostream, template_index/type_index const & rhs); - -/// All possible operators for comparison of std::type_info's and type_index'es. -inline bool operator(type_index/std::type_info const& lhs, type_index/std::type_info const& rhs); - -/// All possible operators for comparison of template_index'es. -inline bool operator(template_index const& lhs, template_index const& rhs); - -/// All possible operators for comparison of type_index'es. -inline bool operator(type_index const& lhs, type_index const& rhs); - -#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED - -} // namespace boost +#include +#include #endif // BOOST_TYPE_INDEX_HPP - diff --git a/boost/type_index/template_index_impl.hpp b/boost/type_index/template_index_impl.hpp new file mode 100644 index 0000000..b7e30fe --- /dev/null +++ b/boost/type_index/template_index_impl.hpp @@ -0,0 +1,243 @@ +// +// Copyright (c) Antony Polukhin, 2012-2013. +// +// +// 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_TEMPLATE_INDEX_IMPL_HPP +#define BOOST_TYPE_INDEX_TEMPLATE_INDEX_IMPL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream +#else +#include +#endif +#endif + + +namespace boost { + +namespace detail { +#if defined(BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP) && defined(BOOST_TYPE_INDEX_CTTI_END_SKIP) + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP); // skip user specified bytes count + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = BOOST_TYPE_INDEX_CTTI_END_SKIP); // skip user specified bytes count +#elif defined _MSC_VER + // sizeof("const char *__cdecl boost::detail::ctti<") - 1 + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 40); + + // sizeof(">::n(void)") - 1 + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 10); + +#elif defined __clang__ + // sizeof("static const char *boost::detail::ctti<") - 1 + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 39); + + // == sizeof(">::n()") - 1 + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 6); +#elif defined __GNUC__ + // sizeof("static const char* boost::detail::ctti::n() [with T = ") - 1 + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 57); + + // == sizeof("]") - 1 + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 1); + +#else + // TODO: Code for other platforms + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_begin = 0); // skip nothing + BOOST_STATIC_CONSTANT(std::size_t, ctti_skip_size_at_end = 0); // skip nothing +#endif + + /// Noncopyable type_info that does not require RTTI + /// CTTI == Compile Time Type Info + /// This name must be as short as posible, to avoid code bloat + template + struct ctti { + typedef T template_type; + typedef ctti this_type; + + /// Returns raw name. Must be as short, as possible, to avoid code bloat + static const char* n() BOOST_NOEXCEPT { + return BOOST_CURRENT_FUNCTION + detail::ctti_skip_size_at_begin; + } + + /// Returns raw name + static const char* name() BOOST_NOEXCEPT { + return this_type::n(); + } + + /// Returns true if the type precedes the type of rhs in the collation order. + /// The collation order is just an internal order. + template + static bool before() BOOST_NOEXCEPT { + return std::strcmp(this_type::n(), ctti::n()) < 0; + } + + /// Returns length of demangled name + static std::size_t name_length() BOOST_NOEXCEPT { + return std::strlen(this_type::n() + detail::ctti_skip_size_at_end); + } + + /// Returns user-friendly name + static std::string name_demangled() BOOST_NOEXCEPT { + return std::string(this_type::n(), this_type::name_length()); + } + }; +} // namespace detail + +/// Copyable type_info that does not require RTTI and could store const, +/// volatile and references if constructed via construct_with_cvr() +class template_index { +private: + const char* name_; + + /// @cond + explicit template_index(const char* name) BOOST_NOEXCEPT + : name_(name) + {} + /// @endcond + +public: + /// Default constructor. + template_index() BOOST_NOEXCEPT + : name_(detail::ctti::name()) + {} + + /// Factory method for constructing template_index instance for type T. + /// Strips const, volatile and & modifiers from T + template + static template_index construct(){ + 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 template_index(detail::ctti::name()); + } + + /// Factory method for constructing template_index instance for type T. + /// Does not strips const, volatile and & modifiers from T + template + static template_index construct_with_cvr() { + # 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 template_index(detail::ctti::name()); + } + + + /// Returns true if the type precedes the type of rhs in the collation order. + /// The collation order is just an internal order. + bool before(const template_index& rhs) const BOOST_NOEXCEPT { + return std::strcmp(name(), rhs.name()) < 0; + } + + /// Returns raw name + const char* name() const BOOST_NOEXCEPT { + return name_; + } + + /// Returns user-friendly name + std::string name_demangled() const { + return std::string(name_, std::strlen(name_ + detail::ctti_skip_size_at_end)); + } + + /// @cond + bool operator == (const template_index& rhs) const BOOST_NOEXCEPT { + return !std::strcmp(name_, rhs.name()); + } + + bool operator != (const template_index& rhs) const BOOST_NOEXCEPT { + return !!std::strcmp(name_, rhs.name()); + } + + bool operator < (const template_index& rhs) const BOOST_NOEXCEPT { + return std::strcmp(name_, rhs.name()) < 0; + } + + bool operator > (const template_index& rhs) const BOOST_NOEXCEPT { + return std::strcmp(name_, rhs.name()) > 0; + } + + bool operator <= (const template_index& rhs) const BOOST_NOEXCEPT { + return std::strcmp(name_, rhs.name()) <= 0; + } + + bool operator >= (const template_index& rhs) const BOOST_NOEXCEPT { + return std::strcmp(name_, rhs.name()) >= 0; + } + /// @endcond + + /// Function for getting hash value + std::size_t hash_code() const BOOST_NOEXCEPT { + return boost::hash_range(name_, name_ + std::strlen(name_ + detail::ctti_skip_size_at_end)); + } +}; + +/// Method for constructing template_index instance for type T. +/// Strips const, volatile and & modifiers from T. +template +template_index template_id() BOOST_NOEXCEPT { + return template_index::construct(); +} + +/// Factory method for constructing template_index instance for type T. +/// Does not strips const, volatile and & modifiers from T. +template +template_index template_id_with_cvr() BOOST_NOEXCEPT { + return template_index::construct_with_cvr(); +} + +/* *************** template_index free functions ******************* */ + +#ifndef BOOST_NO_IOSTREAM +#ifdef BOOST_NO_TEMPLATED_IOSTREAMS +/// Ostream operator that will output demangled name +inline std::ostream& operator<<(std::ostream& ostr, template_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} +#else +/// Ostream operator that will output demangled name +template +inline std::basic_ostream& operator<<(std::basic_ostream& ostr, template_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} +#endif // BOOST_NO_TEMPLATED_IOSTREAMS +#endif // BOOST_NO_IOSTREAM + +/// hash_value function overload for template_index +inline std::size_t hash_value(template_index const& v) BOOST_NOEXCEPT { + return v.hash_code(); +} + +} // namespace boost + +#endif // BOOST_TYPE_INDEX_TEMPLATE_INDEX_IMPL_HPP + diff --git a/boost/type_index/type_index_impl.hpp b/boost/type_index/type_index_impl.hpp new file mode 100644 index 0000000..004d6c4 --- /dev/null +++ b/boost/type_index/type_index_impl.hpp @@ -0,0 +1,324 @@ +// +// Copyright (c) Antony Polukhin, 2012-2013. +// +// +// 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_IMPL_HPP +#define BOOST_TYPE_INDEX_TYPE_INDEX_IMPL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_NO_RTTI +#include +#endif + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream +#else +#include +#endif +#endif + +#ifdef __GNUC__ +#include +#endif + +namespace boost { + +#ifndef BOOST_NO_RTTI + +#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED + +// for this compiler at least, cross-shared-library type_info +// comparisons don't work, so use typeid(x).name() instead. It's not +// yet clear what the best default strategy is. +# if (defined(__GNUC__) && __GNUC__ >= 3 && __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 +# define BOOST_CLASSINFO_COMPARISON_NOEXCEPT +#else +# define BOOST_CLASSINFO_COMPARISON_NOEXCEPT BOOST_NOEXCEPT +# endif + +#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED + +/// Copyable type_info class that requires RTTI. +class type_index { +public: + +#ifdef BOOST_NO_STD_TYPEINFO + typedef type_info stl_type_info; +#else + typedef std::type_info stl_type_info; +#endif + +private: + const stl_type_info* pinfo_; + +public: + /// Default constructor. + type_index() + : pinfo_(&typeid(void)) + {} + + /// Constructs type_index from an instance of std::type_info. + explicit type_index(const stl_type_info& inf) BOOST_NOEXCEPT + : pinfo_(&inf) + {} + + /// Factory method for constructing type_index instance for type T. + /// Strips const, volatile and & modifiers from T. + template + static type_index construct() { + 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 type_index(typeid(no_cvr_t)); + } + + /// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. + /// This method available only with RTTI enabled. + template + static type_index construct_rtti_only(T& rtti_val) { + return type_index(typeid(rtti_val)); + } + + /// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. + /// This method available only with RTTI enabled. + template + static type_index construct_rtti_only(T* rtti_val) { + return type_index(typeid(rtti_val)); + } + + /// Returns true if the type precedes the type of rhs in the collation order. + /// The collation order is just an internal order. + bool before(type_index const& rhs) const BOOST_NOEXCEPT { + return !!pinfo_->before(*rhs.pinfo_); + } + + /// Returns raw name + const char* name() const { + #ifdef _MSC_VER + return pinfo_->raw_name(); + #else + return pinfo_->name(); + #endif + } + + /// Returns user-friendly name + std::string name_demangled() const { + #if defined(__GNUC__) + int status = 0 ; + char* demang = abi::__cxa_demangle(pinfo_->name(), NULL, 0, &status); + BOOST_ASSERT(!status); + std::string ret(demang); + free(demang); + return ret; + #else + return pinfo_->name(); + #endif + } + +#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED + bool operator == (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return !std::strcmp(pinfo_->name(), rhs.pinfo_->name()); + #else + return *pinfo_ == *rhs.pinfo_; + #endif + } + + bool operator != (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return !(*this == rhs); + } + + bool operator < (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return std::strcmp(pinfo_->name(), rhs.pinfo_->name()) < 0; + #else + return before(rhs); + #endif + } + + bool operator > (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return (rhs < *this); + } + + bool operator <= (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return !(*this > rhs); + } + + bool operator >= (type_index const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return !(*this < rhs); + } + + bool operator == (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return !std::strcmp(pinfo_->name(), rhs.name()); + #else + return *pinfo_ == rhs; + #endif + } + + bool operator != (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return !(*this == rhs); + } + + bool operator < (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return std::strcmp(pinfo_->name(), rhs.name()) < 0; + #else + return !!pinfo_->before(rhs); + #endif + } + + bool operator > (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES + return std::strcmp(pinfo_->name(), rhs.name()) > 0; + #else + return !!rhs.before(*pinfo_); + #endif + } + + bool operator <= (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return !(*this > rhs); + } + + bool operator >= (stl_type_info const& rhs) const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return !(*this < rhs); + } +#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED + + /// Function for getting hash value + std::size_t hash_code() const BOOST_CLASSINFO_COMPARISON_NOEXCEPT { +#if _MSC_VER >= 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__)) + return pinfo_->hash_code(); +#else + return boost::hash_range(name(), name() + std::strlen(name())); +#endif + } +}; + +#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED + +/* *************** type_index free functions ******************* */ + +inline bool operator == (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return rhs == lhs; // Operation is commutative +} + +inline bool operator != (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return rhs != lhs; // Operation is commutative +} + +inline bool operator < (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return rhs > lhs; +} + +inline bool operator > (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return rhs < lhs; +} + +inline bool operator <= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return rhs >= lhs; +} + +inline bool operator >= (type_index::stl_type_info const& lhs, type_index const& rhs) BOOST_CLASSINFO_COMPARISON_NOEXCEPT { + return rhs <= lhs; +} + +#undef BOOST_CLASSINFO_COMPARISON_NOEXCEPT + +#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED + +#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES +#undef BOOST_CLASSINFO_COMPARE_BY_NAMES +#endif + +/// @endcond + +/// Function, to get type_index for a type T. Strips const, volatile and & modifiers from T. +template +type_index type_id() { + return type_index::construct(); +} + +/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. +/// This method available only with RTTI enabled. +template +type_index type_id_rtti_only(T& rtti_val) { + return type_index::construct_rtti_only(rtti_val); +} + +/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. +/// This method available only with RTTI enabled. +template +type_index type_id_rtti_only(T* rtti_val) { + return type_index::construct_rtti_only(rtti_val); +} + +/* *************** type_index free functions ******************* */ + +/// @cond + +#ifndef BOOST_NO_IOSTREAM +#ifdef BOOST_NO_TEMPLATED_IOSTREAMS + +/// Ostream operator that will output demangled name. +inline std::ostream& operator<<(std::ostream& ostr, type_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} + +#else + +/// Ostream operator that will output demangled name. +template +inline std::basic_ostream& operator<<(std::basic_ostream& ostr, type_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} + +#endif // BOOST_NO_TEMPLATED_IOSTREAMS +#endif // BOOST_NO_IOSTREAM + +/// hash_value function overload for type_index. +inline std::size_t hash_value(type_index const& v) { + return v.hash_code(); +} + +/// @endcond + +#endif // BOOST_NO_RTTI + +} // namespace boost + +#endif // BOOST_TYPE_INDEX_TYPE_INDEX_IMPL_HPP + diff --git a/boost/type_index/type_index_minimal.hpp b/boost/type_index/type_index_minimal.hpp new file mode 100644 index 0000000..328bcd0 --- /dev/null +++ b/boost/type_index/type_index_minimal.hpp @@ -0,0 +1,34 @@ +// +// Copyright (c) Antony Polukhin, 2012-2013. +// +// +// 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_MINIMAL_HPP +#define BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#ifndef BOOST_NO_RTTI +# include +#else +# include + +typedef template_index type_index; + +template +type_index type_id() { + return template_index::construct(); +} + +#endif // BOOST_NO_RTTI + +} // namespace boost + +#endif // BOOST_TYPE_INDEX_TYPE_INDEX_MINIMAL_HPP + diff --git a/libs/type_index/test/Jamfile.v2 b/libs/type_index/test/Jamfile.v2 index 7f94ba5..dc62f2f 100644 --- a/libs/type_index/test/Jamfile.v2 +++ b/libs/type_index/test/Jamfile.v2 @@ -14,6 +14,9 @@ project ; test-suite type_index - : [ run type_index_test.cpp ] + : + [ run type_index_test.cpp ] + [ run template_index_test.cpp ] + [ run testing_both.cpp ] ; diff --git a/libs/type_index/test/template_index_test.cpp b/libs/type_index/test/template_index_test.cpp new file mode 100644 index 0000000..0b501ac --- /dev/null +++ b/libs/type_index/test/template_index_test.cpp @@ -0,0 +1,21 @@ +// +// Copyright Antony Polukhin, 2012-2013. +// +// 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) + +#define BOOST_TEST_MODULE template_index_test_module +#include + +namespace my_namespace1 { + class my_class{}; +} + + +namespace my_namespace2 { + class my_class{}; +} + +#include "template_index_tests.ipp" + diff --git a/libs/type_index/test/template_index_tests.ipp b/libs/type_index/test/template_index_tests.ipp new file mode 100644 index 0000000..55b8c11 --- /dev/null +++ b/libs/type_index/test/template_index_tests.ipp @@ -0,0 +1,159 @@ +// +// Copyright Antony Polukhin, 2012. +// +// 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) + +#include + +#include +#include + +BOOST_AUTO_TEST_CASE(names_matches_template_id) +{ + using namespace boost; + BOOST_CHECK_EQUAL(template_id().name_demangled(), "int"); + BOOST_CHECK_EQUAL(template_id().name_demangled(), "double"); + + BOOST_CHECK_EQUAL(template_id().name(), template_id().name()); + BOOST_CHECK_NE(template_id().name(), template_id().name()); + BOOST_CHECK_NE(template_id().name(), template_id().name()); + BOOST_CHECK_EQUAL(template_id().name(), template_id().name()); +} + +BOOST_AUTO_TEST_CASE(comparators_template_id) +{ + using namespace boost; + template_index t_int = template_id(); + template_index t_double = template_id(); + + BOOST_CHECK_EQUAL(t_int, t_int); + BOOST_CHECK_LE(t_int, t_int); + BOOST_CHECK_GE(t_int, t_int); + BOOST_CHECK_NE(t_int, t_double); + + BOOST_CHECK_LE(t_double, t_double); + BOOST_CHECK_GE(t_double, t_double); + BOOST_CHECK_NE(t_double, t_int); + + BOOST_CHECK(t_double < t_int || t_int < t_double); + BOOST_CHECK(t_double > t_int || t_int > t_double); +} + +BOOST_AUTO_TEST_CASE(hash_code_template_id) +{ + using namespace boost; + std::size_t t_int1 = template_id().hash_code(); + std::size_t t_double1 = template_id().hash_code(); + + std::size_t t_int2 = template_id().hash_code(); + std::size_t t_double2 = template_id().hash_code(); + + BOOST_CHECK_EQUAL(t_int1, t_int2); + BOOST_CHECK_NE(t_int1, t_double2); + BOOST_CHECK_LE(t_double1, t_double2); +} + +template +static void test_with_modofiers() { + using namespace boost; + + template_index t1 = template_id_with_cvr(); + template_index t2 = template_id_with_cvr(); + + BOOST_CHECK_NE(t2, t1); + BOOST_CHECK(t1 < t2 || t2 < t1); + BOOST_CHECK(t1 > t2 || t2 > t1); + + BOOST_CHECK_EQUAL(t1, template_id_with_cvr()); + BOOST_CHECK_EQUAL(t2, template_id_with_cvr()); + + BOOST_CHECK_EQUAL(t1.hash_code(), template_id_with_cvr().hash_code()); + BOOST_CHECK_EQUAL(t2.hash_code(), template_id_with_cvr().hash_code()); + + BOOST_CHECK_NE(t1.hash_code(), template_id_with_cvr().hash_code()); + BOOST_CHECK_NE(t2.hash_code(), template_id_with_cvr().hash_code()); +} + +BOOST_AUTO_TEST_CASE(template_id_storing_modifiers) +{ + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); + test_with_modofiers(); +} + +BOOST_AUTO_TEST_CASE(template_index_stream_operator_via_lexical_cast_testing) +{ + using namespace boost; + + std::string s_int2 = lexical_cast(template_id()); + BOOST_CHECK_EQUAL(s_int2, "int"); + + std::string s_double2 = lexical_cast(template_id()); + BOOST_CHECK_EQUAL(s_double2, "double"); +} + +BOOST_AUTO_TEST_CASE(template_index_stripping_cvr_test) +{ + using namespace boost; + + BOOST_CHECK_EQUAL(template_id(), template_id()); + BOOST_CHECK_EQUAL(template_id(), template_id()); + BOOST_CHECK_EQUAL(template_id(), template_id()); + + BOOST_CHECK_EQUAL(template_id(), template_id()); + BOOST_CHECK_EQUAL(template_id(), template_id()); + BOOST_CHECK_EQUAL(template_id(), template_id()); + + + BOOST_CHECK_EQUAL(template_id(), template_id()); + BOOST_CHECK_EQUAL(template_id(), template_id()); + BOOST_CHECK_EQUAL(template_id(), template_id()); + + BOOST_CHECK_EQUAL(template_id(), template_id()); + BOOST_CHECK_EQUAL(template_id(), template_id()); + BOOST_CHECK_EQUAL(template_id(), template_id()); +} + + +BOOST_AUTO_TEST_CASE(template_index_user_defined_class_test) +{ + using namespace boost; + + BOOST_CHECK_EQUAL(template_id(), template_id()); + BOOST_CHECK_EQUAL(template_id(), template_id()); + + BOOST_CHECK_NE(template_id(), template_id()); + BOOST_CHECK_NE( + template_id().name_demangled().find("my_namespace1::my_class"), + std::string::npos); +} diff --git a/libs/type_index/test/testing_both.cpp b/libs/type_index/test/testing_both.cpp new file mode 100644 index 0000000..ac8780c --- /dev/null +++ b/libs/type_index/test/testing_both.cpp @@ -0,0 +1,22 @@ +// +// Copyright Antony Polukhin, 2012-2013. +// +// 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) + +#define BOOST_TEST_MODULE testing_both_test_module +#include + +namespace my_namespace1 { + class my_class{}; +} + + +namespace my_namespace2 { + class my_class{}; +} + +#include "type_index_tests.ipp" +#include "template_index_tests.ipp" + diff --git a/libs/type_index/test/type_index_test.cpp b/libs/type_index/test/type_index_test.cpp index 1a4f29e..6959c26 100644 --- a/libs/type_index/test/type_index_test.cpp +++ b/libs/type_index/test/type_index_test.cpp @@ -1,5 +1,5 @@ // -// Copyright Antony Polukhin, 2012. +// Copyright Antony Polukhin, 2012-2013. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -8,268 +8,6 @@ #define BOOST_TEST_MODULE type_index_test_module #include -#include - -#include -#include - -BOOST_AUTO_TEST_CASE(names_matches_type_id) -{ - using namespace boost; - BOOST_CHECK_EQUAL(type_id().name_demangled(), "int"); - BOOST_CHECK_EQUAL(type_id().name_demangled(), "double"); - - BOOST_CHECK_EQUAL(type_id().name(), type_id().name()); - BOOST_CHECK_NE(type_id().name(), type_id().name()); - BOOST_CHECK_NE(type_id().name(), type_id().name()); - BOOST_CHECK_EQUAL(type_id().name(), type_id().name()); -} - -BOOST_AUTO_TEST_CASE(names_matches_template_id) -{ - using namespace boost; - BOOST_CHECK_EQUAL(template_id().name_demangled(), "int"); - BOOST_CHECK_EQUAL(template_id().name_demangled(), "double"); - - BOOST_CHECK_EQUAL(template_id().name(), template_id().name()); - BOOST_CHECK_NE(template_id().name(), template_id().name()); - BOOST_CHECK_NE(template_id().name(), template_id().name()); - BOOST_CHECK_EQUAL(template_id().name(), template_id().name()); -} - -BOOST_AUTO_TEST_CASE(comparators_type_id) -{ - using namespace boost; - type_index t_int = type_id(); - type_index t_double = type_id(); - - BOOST_CHECK_EQUAL(t_int, t_int); - BOOST_CHECK_LE(t_int, t_int); - BOOST_CHECK_GE(t_int, t_int); - BOOST_CHECK_NE(t_int, t_double); - - BOOST_CHECK_LE(t_double, t_double); - BOOST_CHECK_GE(t_double, t_double); - BOOST_CHECK_NE(t_double, t_int); - - BOOST_CHECK(t_double < t_int || t_int < t_double); - BOOST_CHECK(t_double > t_int || t_int > t_double); -} - -BOOST_AUTO_TEST_CASE(comparators_template_id) -{ - using namespace boost; - template_index t_int = template_id(); - template_index t_double = template_id(); - - BOOST_CHECK_EQUAL(t_int, t_int); - BOOST_CHECK_LE(t_int, t_int); - BOOST_CHECK_GE(t_int, t_int); - BOOST_CHECK_NE(t_int, t_double); - - BOOST_CHECK_LE(t_double, t_double); - BOOST_CHECK_GE(t_double, t_double); - BOOST_CHECK_NE(t_double, t_int); - - BOOST_CHECK(t_double < t_int || t_int < t_double); - BOOST_CHECK(t_double > t_int || t_int > t_double); -} - -BOOST_AUTO_TEST_CASE(hash_code_type_id) -{ - using namespace boost; - std::size_t t_int1 = type_id().hash_code(); - std::size_t t_double1 = type_id().hash_code(); - - std::size_t t_int2 = type_id().hash_code(); - std::size_t t_double2 = type_id().hash_code(); - - BOOST_CHECK_EQUAL(t_int1, t_int2); - BOOST_CHECK_NE(t_int1, t_double2); - BOOST_CHECK_LE(t_double1, t_double2); -} - -#ifndef BOOST_NO_RTTI - -BOOST_AUTO_TEST_CASE(comparators_type_id_vs_type_info) -{ - using namespace boost; - type_index t_int = type_id(); - - BOOST_CHECK(t_int == typeid(int)); - BOOST_CHECK(typeid(int) == t_int); - BOOST_CHECK(t_int <= typeid(int)); - BOOST_CHECK(typeid(int) <= t_int); - BOOST_CHECK(t_int >= typeid(int)); - BOOST_CHECK(typeid(int) >= t_int); - - type_index t_double = type_id(); - - BOOST_CHECK(t_double == typeid(double)); - BOOST_CHECK(typeid(double) == t_double); - BOOST_CHECK(t_double <= typeid(double)); - BOOST_CHECK(typeid(double) <= t_double); - BOOST_CHECK(t_double >= typeid(double)); - BOOST_CHECK(typeid(double) >= t_double); - - if (t_double < t_int) { - BOOST_CHECK(t_double < typeid(int)); - BOOST_CHECK(typeid(double) < t_int); - BOOST_CHECK(typeid(int) > t_double); - BOOST_CHECK(t_int > typeid(double)); - - - BOOST_CHECK(t_double <= typeid(int)); - BOOST_CHECK(typeid(double) <= t_int); - BOOST_CHECK(typeid(int) >= t_double); - BOOST_CHECK(t_int >= typeid(double)); - } else { - BOOST_CHECK(t_double > typeid(int)); - BOOST_CHECK(typeid(double) > t_int); - BOOST_CHECK(typeid(int) < t_double); - BOOST_CHECK(t_int < typeid(double)); - - - BOOST_CHECK(t_double >= typeid(int)); - BOOST_CHECK(typeid(double) >= t_int); - BOOST_CHECK(typeid(int) <= t_double); - BOOST_CHECK(t_int <= typeid(double)); - } -} - -#endif // BOOST_NO_RTTI - -BOOST_AUTO_TEST_CASE(hash_code_template_id) -{ - using namespace boost; - std::size_t t_int1 = template_id().hash_code(); - std::size_t t_double1 = template_id().hash_code(); - - std::size_t t_int2 = template_id().hash_code(); - std::size_t t_double2 = template_id().hash_code(); - - BOOST_CHECK_EQUAL(t_int1, t_int2); - BOOST_CHECK_NE(t_int1, t_double2); - BOOST_CHECK_LE(t_double1, t_double2); -} - -template -static void test_with_modofiers() { - using namespace boost; - - template_index t1 = template_id_with_cvr(); - template_index t2 = template_id_with_cvr(); - - BOOST_CHECK_NE(t2, t1); - BOOST_CHECK(t1 < t2 || t2 < t1); - BOOST_CHECK(t1 > t2 || t2 > t1); - - BOOST_CHECK_EQUAL(t1, template_id_with_cvr()); - BOOST_CHECK_EQUAL(t2, template_id_with_cvr()); - - BOOST_CHECK_EQUAL(t1.hash_code(), template_id_with_cvr().hash_code()); - BOOST_CHECK_EQUAL(t2.hash_code(), template_id_with_cvr().hash_code()); - - BOOST_CHECK_NE(t1.hash_code(), template_id_with_cvr().hash_code()); - BOOST_CHECK_NE(t2.hash_code(), template_id_with_cvr().hash_code()); -} - -BOOST_AUTO_TEST_CASE(template_id_storing_modifiers) -{ - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); - test_with_modofiers(); -} - -BOOST_AUTO_TEST_CASE(stream_operator_via_lexical_cast_testing) -{ - using namespace boost; - std::string s_int1 = lexical_cast(type_id()); - BOOST_CHECK_EQUAL(s_int1, "int"); - - std::string s_int2 = lexical_cast(template_id()); - BOOST_CHECK_EQUAL(s_int2, "int"); - - std::string s_double1 = lexical_cast(type_id()); - BOOST_CHECK_EQUAL(s_double1, "double"); - - std::string s_double2 = lexical_cast(template_id()); - BOOST_CHECK_EQUAL(s_double2, "double"); -} - -BOOST_AUTO_TEST_CASE(type_index_stripping_cvr_test) -{ - using namespace boost; - - BOOST_CHECK_EQUAL(type_id(), type_id()); - BOOST_CHECK_EQUAL(type_id(), type_id()); - BOOST_CHECK_EQUAL(type_id(), type_id()); - - BOOST_CHECK_EQUAL(type_id(), type_id()); - BOOST_CHECK_EQUAL(type_id(), type_id()); - BOOST_CHECK_EQUAL(type_id(), type_id()); - - - BOOST_CHECK_EQUAL(type_id(), type_id()); - BOOST_CHECK_EQUAL(type_id(), type_id()); - BOOST_CHECK_EQUAL(type_id(), type_id()); - - BOOST_CHECK_EQUAL(type_id(), type_id()); - BOOST_CHECK_EQUAL(type_id(), type_id()); - BOOST_CHECK_EQUAL(type_id(), type_id()); -} - -BOOST_AUTO_TEST_CASE(template_index_stripping_cvr_test) -{ - using namespace boost; - - BOOST_CHECK_EQUAL(template_id(), template_id()); - BOOST_CHECK_EQUAL(template_id(), template_id()); - BOOST_CHECK_EQUAL(template_id(), template_id()); - - BOOST_CHECK_EQUAL(template_id(), template_id()); - BOOST_CHECK_EQUAL(template_id(), template_id()); - BOOST_CHECK_EQUAL(template_id(), template_id()); - - - BOOST_CHECK_EQUAL(template_id(), template_id()); - BOOST_CHECK_EQUAL(template_id(), template_id()); - BOOST_CHECK_EQUAL(template_id(), template_id()); - - BOOST_CHECK_EQUAL(template_id(), template_id()); - BOOST_CHECK_EQUAL(template_id(), template_id()); - BOOST_CHECK_EQUAL(template_id(), template_id()); -} - - namespace my_namespace1 { class my_class{}; } @@ -279,76 +17,4 @@ namespace my_namespace2 { class my_class{}; } - -BOOST_AUTO_TEST_CASE(template_index_user_defined_class_test) -{ - using namespace boost; - - BOOST_CHECK_EQUAL(template_id(), template_id()); - BOOST_CHECK_EQUAL(template_id(), template_id()); - - BOOST_CHECK_NE(template_id(), template_id()); - BOOST_CHECK_NE( - template_id().name_demangled().find("my_namespace1::my_class"), - std::string::npos); - - BOOST_CHECK_EQUAL(type_id(), type_id()); - BOOST_CHECK_EQUAL(type_id(), type_id()); - -#ifndef BOOST_NO_RTTI - BOOST_CHECK(type_id() == typeid(my_namespace1::my_class)); - BOOST_CHECK(type_id() == typeid(my_namespace2::my_class)); - BOOST_CHECK(typeid(my_namespace1::my_class) == type_id()); - BOOST_CHECK(typeid(my_namespace2::my_class) == type_id()); -#endif - - BOOST_CHECK_NE(type_id(), type_id()); - BOOST_CHECK_NE( - type_id().name_demangled().find("my_namespace1::my_class"), - std::string::npos); -} - - -#ifndef BOOST_NO_RTTI - -class A { public: virtual ~A(){} }; -class B: public A{}; -class C: public B {}; - -BOOST_AUTO_TEST_CASE(comparators_type_id_rtti_only) -{ - C c1; - B b1; - A* pc1 = &c1; - A& rc1 = c1; - A* pb1 = &b1; - A& rb1 = b1; - BOOST_CHECK(typeid(rc1) == typeid(*pc1)); - BOOST_CHECK(typeid(rb1) == typeid(*pb1)); - - BOOST_CHECK(typeid(rc1) != typeid(*pb1)); - BOOST_CHECK(typeid(rb1) != typeid(*pc1)); - - BOOST_CHECK(typeid(&rc1) == typeid(pb1)); - BOOST_CHECK(typeid(&rb1) == typeid(pc1)); - - BOOST_CHECK_EQUAL(boost::type_id_rtti_only(rc1), boost::type_id_rtti_only(*pc1)); - BOOST_CHECK_EQUAL(boost::type_id_rtti_only(rb1), boost::type_id_rtti_only(*pb1)); - - BOOST_CHECK_NE(boost::type_id_rtti_only(rc1), boost::type_id_rtti_only(*pb1)); - BOOST_CHECK_NE(boost::type_id_rtti_only(rb1), boost::type_id_rtti_only(*pc1)); - BOOST_CHECK_EQUAL(boost::type_id_rtti_only(&rc1), boost::type_id_rtti_only(pb1)); - BOOST_CHECK_EQUAL(boost::type_id_rtti_only(&rb1), boost::type_id_rtti_only(pc1)); - - BOOST_CHECK(boost::type_id_rtti_only(rc1) == typeid(*pc1)); - BOOST_CHECK(boost::type_id_rtti_only(rb1) == typeid(*pb1)); - - BOOST_CHECK(boost::type_id_rtti_only(rc1) != typeid(*pb1)); - BOOST_CHECK(boost::type_id_rtti_only(rb1) != typeid(*pc1)); - BOOST_CHECK(boost::type_id_rtti_only(&rc1) == typeid(pb1)); - BOOST_CHECK(boost::type_id_rtti_only(&rb1) == typeid(pc1)); -} - -#endif // BOOST_NO_RTTI - - +#include "type_index_tests.ipp" diff --git a/libs/type_index/test/type_index_tests.ipp b/libs/type_index/test/type_index_tests.ipp new file mode 100644 index 0000000..7fd689f --- /dev/null +++ b/libs/type_index/test/type_index_tests.ipp @@ -0,0 +1,205 @@ +// +// Copyright Antony Polukhin, 2012. +// +// 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) + +#include + +#include +#include + +BOOST_AUTO_TEST_CASE(names_matches_type_id) +{ + using namespace boost; + BOOST_CHECK_EQUAL(type_id().name_demangled(), "int"); + BOOST_CHECK_EQUAL(type_id().name_demangled(), "double"); + + BOOST_CHECK_EQUAL(type_id().name(), type_id().name()); + BOOST_CHECK_NE(type_id().name(), type_id().name()); + BOOST_CHECK_NE(type_id().name(), type_id().name()); + BOOST_CHECK_EQUAL(type_id().name(), type_id().name()); +} + +BOOST_AUTO_TEST_CASE(comparators_type_id) +{ + using namespace boost; + type_index t_int = type_id(); + type_index t_double = type_id(); + + BOOST_CHECK_EQUAL(t_int, t_int); + BOOST_CHECK_LE(t_int, t_int); + BOOST_CHECK_GE(t_int, t_int); + BOOST_CHECK_NE(t_int, t_double); + + BOOST_CHECK_LE(t_double, t_double); + BOOST_CHECK_GE(t_double, t_double); + BOOST_CHECK_NE(t_double, t_int); + + BOOST_CHECK(t_double < t_int || t_int < t_double); + BOOST_CHECK(t_double > t_int || t_int > t_double); +} + +BOOST_AUTO_TEST_CASE(hash_code_type_id) +{ + using namespace boost; + std::size_t t_int1 = type_id().hash_code(); + std::size_t t_double1 = type_id().hash_code(); + + std::size_t t_int2 = type_id().hash_code(); + std::size_t t_double2 = type_id().hash_code(); + + BOOST_CHECK_EQUAL(t_int1, t_int2); + BOOST_CHECK_NE(t_int1, t_double2); + BOOST_CHECK_LE(t_double1, t_double2); +} + +#ifndef BOOST_NO_RTTI + +BOOST_AUTO_TEST_CASE(comparators_type_id_vs_type_info) +{ + using namespace boost; + type_index t_int = type_id(); + + BOOST_CHECK(t_int == typeid(int)); + BOOST_CHECK(typeid(int) == t_int); + BOOST_CHECK(t_int <= typeid(int)); + BOOST_CHECK(typeid(int) <= t_int); + BOOST_CHECK(t_int >= typeid(int)); + BOOST_CHECK(typeid(int) >= t_int); + + type_index t_double = type_id(); + + BOOST_CHECK(t_double == typeid(double)); + BOOST_CHECK(typeid(double) == t_double); + BOOST_CHECK(t_double <= typeid(double)); + BOOST_CHECK(typeid(double) <= t_double); + BOOST_CHECK(t_double >= typeid(double)); + BOOST_CHECK(typeid(double) >= t_double); + + if (t_double < t_int) { + BOOST_CHECK(t_double < typeid(int)); + BOOST_CHECK(typeid(double) < t_int); + BOOST_CHECK(typeid(int) > t_double); + BOOST_CHECK(t_int > typeid(double)); + + + BOOST_CHECK(t_double <= typeid(int)); + BOOST_CHECK(typeid(double) <= t_int); + BOOST_CHECK(typeid(int) >= t_double); + BOOST_CHECK(t_int >= typeid(double)); + } else { + BOOST_CHECK(t_double > typeid(int)); + BOOST_CHECK(typeid(double) > t_int); + BOOST_CHECK(typeid(int) < t_double); + BOOST_CHECK(t_int < typeid(double)); + + + BOOST_CHECK(t_double >= typeid(int)); + BOOST_CHECK(typeid(double) >= t_int); + BOOST_CHECK(typeid(int) <= t_double); + BOOST_CHECK(t_int <= typeid(double)); + } +} + +#endif // BOOST_NO_RTTI + +BOOST_AUTO_TEST_CASE(type_index_stream_operator_via_lexical_cast_testing) +{ + using namespace boost; + std::string s_int1 = lexical_cast(type_id()); + BOOST_CHECK_EQUAL(s_int1, "int"); + + std::string s_double1 = lexical_cast(type_id()); + BOOST_CHECK_EQUAL(s_double1, "double"); +} + +BOOST_AUTO_TEST_CASE(type_index_stripping_cvr_test) +{ + using namespace boost; + + BOOST_CHECK_EQUAL(type_id(), type_id()); + BOOST_CHECK_EQUAL(type_id(), type_id()); + BOOST_CHECK_EQUAL(type_id(), type_id()); + + BOOST_CHECK_EQUAL(type_id(), type_id()); + BOOST_CHECK_EQUAL(type_id(), type_id()); + BOOST_CHECK_EQUAL(type_id(), type_id()); + + + BOOST_CHECK_EQUAL(type_id(), type_id()); + BOOST_CHECK_EQUAL(type_id(), type_id()); + BOOST_CHECK_EQUAL(type_id(), type_id()); + + BOOST_CHECK_EQUAL(type_id(), type_id()); + BOOST_CHECK_EQUAL(type_id(), type_id()); + BOOST_CHECK_EQUAL(type_id(), type_id()); +} + + + +BOOST_AUTO_TEST_CASE(type_index_user_defined_class_test) +{ + using namespace boost; + + BOOST_CHECK_EQUAL(type_id(), type_id()); + BOOST_CHECK_EQUAL(type_id(), type_id()); + +#ifndef BOOST_NO_RTTI + BOOST_CHECK(type_id() == typeid(my_namespace1::my_class)); + BOOST_CHECK(type_id() == typeid(my_namespace2::my_class)); + BOOST_CHECK(typeid(my_namespace1::my_class) == type_id()); + BOOST_CHECK(typeid(my_namespace2::my_class) == type_id()); +#endif + + BOOST_CHECK_NE(type_id(), type_id()); + BOOST_CHECK_NE( + type_id().name_demangled().find("my_namespace1::my_class"), + std::string::npos); +} + + +#ifndef BOOST_NO_RTTI + +class A { public: virtual ~A(){} }; +class B: public A{}; +class C: public B {}; + +BOOST_AUTO_TEST_CASE(comparators_type_id_rtti_only) +{ + C c1; + B b1; + A* pc1 = &c1; + A& rc1 = c1; + A* pb1 = &b1; + A& rb1 = b1; + BOOST_CHECK(typeid(rc1) == typeid(*pc1)); + BOOST_CHECK(typeid(rb1) == typeid(*pb1)); + + BOOST_CHECK(typeid(rc1) != typeid(*pb1)); + BOOST_CHECK(typeid(rb1) != typeid(*pc1)); + + BOOST_CHECK(typeid(&rc1) == typeid(pb1)); + BOOST_CHECK(typeid(&rb1) == typeid(pc1)); + + BOOST_CHECK_EQUAL(boost::type_id_rtti_only(rc1), boost::type_id_rtti_only(*pc1)); + BOOST_CHECK_EQUAL(boost::type_id_rtti_only(rb1), boost::type_id_rtti_only(*pb1)); + + BOOST_CHECK_NE(boost::type_id_rtti_only(rc1), boost::type_id_rtti_only(*pb1)); + BOOST_CHECK_NE(boost::type_id_rtti_only(rb1), boost::type_id_rtti_only(*pc1)); + BOOST_CHECK_EQUAL(boost::type_id_rtti_only(&rc1), boost::type_id_rtti_only(pb1)); + BOOST_CHECK_EQUAL(boost::type_id_rtti_only(&rb1), boost::type_id_rtti_only(pc1)); + + BOOST_CHECK(boost::type_id_rtti_only(rc1) == typeid(*pc1)); + BOOST_CHECK(boost::type_id_rtti_only(rb1) == typeid(*pb1)); + + BOOST_CHECK(boost::type_id_rtti_only(rc1) != typeid(*pb1)); + BOOST_CHECK(boost::type_id_rtti_only(rb1) != typeid(*pc1)); + BOOST_CHECK(boost::type_id_rtti_only(&rc1) == typeid(pb1)); + BOOST_CHECK(boost::type_id_rtti_only(&rb1) == typeid(pc1)); +} + +#endif // BOOST_NO_RTTI + +