From a83bd35fee62901195c55bef6427927d88c235b1 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 3 Jun 2012 14:13:40 +0400 Subject: [PATCH] Initial commit --- boost/type_index.hpp | 404 +++++++++++++++++++++++ libs/type_index/doc/Jamfile.v2 | 17 + libs/type_index/doc/type_index.qbk | 123 +++++++ libs/type_index/test/Jamfile.v2 | 19 ++ libs/type_index/test/type_index_test.cpp | 259 +++++++++++++++ 5 files changed, 822 insertions(+) create mode 100644 boost/type_index.hpp create mode 100644 libs/type_index/doc/Jamfile.v2 create mode 100644 libs/type_index/doc/type_index.qbk create mode 100644 libs/type_index/test/Jamfile.v2 create mode 100644 libs/type_index/test/type_index_test.cpp diff --git a/boost/type_index.hpp b/boost/type_index.hpp new file mode 100644 index 0000000..4feaa20 --- /dev/null +++ b/boost/type_index.hpp @@ -0,0 +1,404 @@ +// +// Copyright (c) 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) +// + +#ifndef BOOST_TYPE_INDEX_HPP +#define BOOST_TYPE_INDEX_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 { + +namespace detail { +#ifdef _MSC_VER + // sizeof("const char *__cdecl boost::detail::template_info<") - 1 + BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_begin = 49); + + // sizeof(">::name(void)") - 1 + BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_end = 13); + +#elif defined __clang__ + // sizeof("static const char *boost::detail::template_info<") - 1 + BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_begin = 48); + + // == sizeof(">::name()") - 1 + BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_end = 9); +#elif defined __GNUC__ + // sizeof("static const char* boost::detail::template_info::name() [with T = ") - 1 + BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_begin = 69); + + // == sizeof("]") - 1 + BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_end = 1); + +#else + // TODO: Code for other platforms + BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_begin = 0); // skip nothing + BOOST_STATIC_CONSTANT(std::size_t, template_info_skip_size_at_end = 0); // skip nothing + +#endif + + + /// Noncopyable type_info that does not require RTTI + template + struct template_info { + typedef T template_type; + typedef template_info this_type; + + /// Retrurns raw name + static const char* name() { + return BOOST_CURRENT_FUNCTION + detail::template_info_skip_size_at_begin; + } + + /// 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() { + return std::strcmp(this_type::name(), template_info::name_begin()) < 0; + } + + /// Returns length of demangled name + static std::size_t name_length() { + return std::strlen(this_type::name()) - detail::template_info_skip_size_at_end; + } + + /// Retrurns user-friendly name + static std::string name_demangled() { + return std::string(this_type::name(), this_type::name_length()); + } + }; +} // namespace detail + + +/// Copyable type_info that does not require RTTI +class template_index { + const char* name_; + + explicit template_index(const char* name) + : name_(name) + {} + +public: + + /// 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::template_info::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::template_info::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 { + return std::strcmp(name(), rhs.name()) < 0; + } + + /// Retrurns raw name + const char* name() const { + return name_; + } + + /// Retrurns user-friendly name + std::string name_demangled() const { + return std::string(name_, std::strlen(name_) - detail::template_info_skip_size_at_end); + } + + bool operator == (const template_index& rhs) const { + return !std::strcmp(name_, rhs.name()); + } + + bool operator != (const template_index& rhs) const { + return !!std::strcmp(name_, rhs.name()); + } + + bool operator < (const template_index& rhs) const { + return std::strcmp(name_, rhs.name()) < 0; + } + + bool operator > (const template_index& rhs) const { + return std::strcmp(name_, rhs.name()) > 0; + } + + bool operator <= (const template_index& rhs) const { + return std::strcmp(name_, rhs.name()) <= 0; + } + + bool operator >= (const template_index& rhs) const { + return std::strcmp(name_, rhs.name()) >= 0; + } + + std::size_t hash_code() const { + return boost::hash_range(name_, name_ + std::strlen(name_)); + } +}; + +#ifndef BOOST_NO_IOSTREAM +#ifdef BOOST_NO_TEMPLATED_IOSTREAMS +inline std::ostream& operator<<(std::ostream& ostr, template_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} +#else +template +inline std::basic_ostream& operator<<(std::basic_ostream& ostr, template_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} +#endif +#endif + +inline std::size_t hash_value(template_index const& v) { + return v.hash_code(); +} + +template <> +struct hash : public std::unary_function { + + std::size_t operator()(template_index const& v) const { + return boost::hash_value(v); + } +}; + +/// Method for constructing template_index instance for type T +/// Strips const, volatile and & modifiers from T +template +template_index template_id() { + 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() { + return template_index::construct_with_cvr(); +} + + +#ifndef BOOST_NO_RTTI + +// 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) \ + || 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 + +/// Copyable type_info class that requires RTTI +class type_index { +public: + +#ifdef BOOST_NO_STD_TYPEINFO + typedef type_info stl_type_index; +#else + typedef std::type_info stl_type_index; +#endif + + const stl_type_index* pinfo_; + + explicit type_index(const stl_type_index& inf) + : pinfo_(&inf) + {} + +public: + + /// 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)); + } + + /// 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 { + return !!pinfo_->before(*rhs.pinfo_); + } + + /// Retrurns raw name + const char* name() const { + #ifdef _MSC_VER + return pinfo_->raw_name(); + #else + return pinfo_->name(); + #endif + } + + /// Retrurns 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 + } + + + bool operator == (type_index const& rhs) const { + #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 { + return !(*this == rhs); + } + + bool operator < (type_index const& rhs) const { + #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 { + return (rhs < *this); + } + + bool operator <= (type_index const& rhs) const { + return !(*this > rhs); + } + + bool operator >= (type_index const& rhs) const { + return !(*this < rhs); + } + + std::size_t hash_code() const { + return boost::hash_range(name(), name() + std::strlen(name())); + } +}; + +#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES +#undef BOOST_CLASSINFO_COMPARE_BY_NAMES +#endif + +#ifndef BOOST_NO_IOSTREAM +#ifdef BOOST_NO_TEMPLATED_IOSTREAMS +inline std::ostream& operator<<(std::ostream& ostr, type_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} +#else +template +inline std::basic_ostream& operator<<(std::basic_ostream& ostr, type_index const& ind) { + ostr << ind.name_demangled(); + return ostr; +} +#endif + +#endif + +inline std::size_t hash_value(type_index const& v) { + return v.hash_code(); +} + +template <> +struct hash : public std::unary_function { + + std::size_t operator()(type_index const& v) const { + return boost::hash_value(v); + } +}; + +/// Function, to get class_index for a type T +/// Strips const, volatile and & modifiers from T +template +type_index type_id() { + return type_index::construct(); +} + +#else +// BOOST_NO_RTTI is defined + +/// Default copyable type_info like class +typedef template_index type_index; + +/// Function, to get class_index for a type T +/// Strips const, volatile and & modifiers from T +template +type_index type_id() { + return template_index::construct(); +} + +#endif + +} // namespace boost + +#endif // BOOST_TYPE_INDEX_HPP + diff --git a/libs/type_index/doc/Jamfile.v2 b/libs/type_index/doc/Jamfile.v2 new file mode 100644 index 0000000..497b7da --- /dev/null +++ b/libs/type_index/doc/Jamfile.v2 @@ -0,0 +1,17 @@ +# Copyright Antony Polukhin 2011. +# Use, modification, and distribution are +# subject to 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) + +using quickbook ; +import boostbook : boostbook ; + +xml type_index : type_index.qbk ; +boostbook standalone + : + type_index + : + boost.root=../../../.. + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html + ; + diff --git a/libs/type_index/doc/type_index.qbk b/libs/type_index/doc/type_index.qbk new file mode 100644 index 0000000..74da46e --- /dev/null +++ b/libs/type_index/doc/type_index.qbk @@ -0,0 +1,123 @@ +[library Boost.TypeIndex + [quickbook 1.5] + [version 1.0] + [copyright 2012 Antony Polukhin] + [category Language Features Emulation] + [license + 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]) + ] +] + +[section Motivation] +Sometimes getting and storing at runtime information about template type is required. For such cases usually used a construction like `&typeid(T)` or C++11 class `std::type_index`. And that is the point, where problems strat: +* `typeid(T)` and `std::type_index` require Run Time Type Info (RTTI) +* `typeid(T)` strips const, volatile and references from type +* some compilers have bugs and do not correctly compare `std::type_info` across shared libraries +* some implementations of `typeid(T)` do not strip const, volatile and references +* only a few STLs have `std::type_index` implementation +* no easy way to store type info without stripping const, volatile and references +* no nice and portable way to get human readable type name + +Boost.TypeIndex was designed to work around those issues. + +[endsect] + +[section Getting started] + +In short: +Just replace `&typeid(T)`, `typeid(T)` with `boost::type_id()` and `const std::type_info&`, `std::type_index` with `boost::type_index`. That's all, you are now using Boost.TypeIndex. + +To get nice human readable name, use `name_demangled()` member function: +`` +type_index ti = type_id(); +std::string nice_name = ti.name_demangled(); +... +std::string nice_name_with_const_volatile_ref = template_id_with_cvr().name_demangled(); +`` + +`template_index` and `type_index` have full set of comparison operators, hashing functions and ostream operators. Thay can be used with any container class. + +If you need to save `const`, `volatile` and references, use `boost::template_index` instead of `boost::type_index`; `boost::template_id_with_cvr()` instead of `boost::type_id()`. + +[endsect] + + +[section Examples] +All the code in examples will work with and without RTTI support. + +Class that allows to register type only once. +`` +class types_registry { + unordered_set types_; + +public: + template + void add_type() { + type_index ti = type_id(); + std::cout << "Adding type " << ti << " to registry \n"; + if (!types_.insert(ti).second) + throw std::logic_error("Type " + ti.name_demangled() + " already in registry"); + } + + template + bool has_type() const { + return types_.cend() != types_.find(type_id()); + } +}; + +int main () { + types_registry tr; + tr.add_type(); + tr.add_type(); + + std::cout << "Has type int: " << tr.has_type() + << "\nHas type std::string: " << tr.has_type() + << '\n'; +} + +`` + +This will output: +`` +Adding type int to registry +Adding type float to registry +Has type int: 1 +Has type std::string: 0 +`` + +Another example (this time checking for exact parameter match). +`my_unary_function` is a class, that stroes function with result type `ResultT` and any input parameter type. In `opertaor()`, it checks for input parameter match and then executes the stored function: + +`` +template +class my_unary_function { + void* function_ptr_; + template_index exact_param_t_; + ... + + template + ResultT operator()(ParamT& v) { + BOOST_ASSERT(exact_param_t_ == template_id_with_cvr()); + return (static_cast(function_ptr_))(v); + } +}; +`` + +[endsect] + +[section Reference] + +TODO: + +[endsect] + + +[section Performance] + +`type_index` and `template_index` classes hold a single pointer, so they are easy and fast to copy. Calls to `const char* name()` do not require dynamic memory allocation and usually just return a pointer to an array of chars in read-only section of binary file. Comparison operators are optimized as much as possible, and in worst case only execute `std::strcmp`. Calls to `std::string name_demangled()` for `type_index` do usually require dynamic memory allocation and some computations, so they are not recomended for usage in performance critical sections. Calls to `std::string name_demangled()` for `template_index` require only `std::strlen` call and are much faster than `std::string name_demangled()` for `type_index`. + +`template_index` uses `BOOST_CURRENT_FUNCTION` macro, which could lead to code bloat. So if you do not need to save `const`, `volatile` and references, use `type_index`. + +[endsect] diff --git a/libs/type_index/test/Jamfile.v2 b/libs/type_index/test/Jamfile.v2 new file mode 100644 index 0000000..7f94ba5 --- /dev/null +++ b/libs/type_index/test/Jamfile.v2 @@ -0,0 +1,19 @@ +# Copyright (C) 2012 Antony Polukhin +# +# 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) +# + +import testing ; +import feature ; + +project + : requirements + /boost/test//boost_unit_test_framework + static + ; + +test-suite type_index + : [ run type_index_test.cpp ] + ; + diff --git a/libs/type_index/test/type_index_test.cpp b/libs/type_index/test/type_index_test.cpp new file mode 100644 index 0000000..c7a5e1a --- /dev/null +++ b/libs/type_index/test/type_index_test.cpp @@ -0,0 +1,259 @@ +// +// 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) + +#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); +} + +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{}; +} + + +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()); + + BOOST_CHECK_NE(type_id(), type_id()); + BOOST_CHECK_NE( + type_id().name_demangled().find("my_namespace1::my_class"), + std::string::npos); +} + + + + + + +