diff --git a/boost/type_index/template_index_impl.hpp b/boost/type_index/template_index_impl.hpp index 7167107..456f5b9 100644 --- a/boost/type_index/template_index_impl.hpp +++ b/boost/type_index/template_index_impl.hpp @@ -213,6 +213,8 @@ template_index template_id() BOOST_NOEXCEPT { /// Factory method for constructing template_index instance for type T. /// Does not strips const, volatile and & modifiers from T. +/// If T has no const, volatile, & and && modifiers, then returns exactly +/// the same result as in case of calling `template_id()`. template template_index template_id_with_cvr() BOOST_NOEXCEPT { return template_index::construct_with_cvr(); diff --git a/boost/type_index/type_index_impl.hpp b/boost/type_index/type_index_impl.hpp index cd9aa2b..e3b8cf2 100644 --- a/boost/type_index/type_index_impl.hpp +++ b/boost/type_index/type_index_impl.hpp @@ -26,8 +26,12 @@ #include #include #include +#include +#include +#include #include #include +#include #include #include #include @@ -67,6 +71,10 @@ namespace boost { #endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED +namespace detail { + template class cvr_saver{}; +} + /// Copyable type_info class that requires RTTI. class type_index { public: @@ -107,6 +115,22 @@ public: return type_index(typeid(no_cvr_t)); } + /// Factory method for constructing type_index instance for type T. + /// Does not strips const, volatile, & and && modifiers from T. + /// If T has no const, volatile, & and && modifiers, then returns exactly + /// the same result as in case of calling `construct()`. + template + static 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, + detail::cvr_saver, + T + >::type type; + return construct(); + } + /// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. /// This method available only with RTTI enabled. template @@ -140,7 +164,7 @@ public: std::string name_demangled() const { #if defined(__GNUC__) std::string ret; - int status = 0 ; + int status = 0; char* demang = abi::__cxa_demangle(pinfo_->name(), NULL, 0, &status); BOOST_ASSERT(!status); @@ -152,10 +176,26 @@ public: } BOOST_CATCH_END free(demang); - return ret; #else - return pinfo_->name(); + std::string ret = pinfo_->name(); #endif + std::string::size_type pos = ret.find("boost::detail::cvr_saver<"); + if (pos == std::string::npos) { + return ret; + } + + pos += sizeof("boost::detail::cvr_saver<"); + while (ret[pos] == ' ') { + ++ pos; + } + std::string::size_type end = ret.rfind(">"); + BOOST_ASSERT(end != std::string::npos); + -- end; + while (ret[end] == ' ') { + -- end; + } + + return ret.substr(pos, end - pos); } #ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED @@ -280,6 +320,15 @@ type_index type_id() BOOST_NOEXCEPT { return type_index::construct(); } +/// Function for constructing type_index instance for type T. +/// Does not strips const, volatile, & and && modifiers from T. +/// If T has no const, volatile, & and && modifiers, then returns exactly +/// the same result as in case of calling `type_id()`. +template +type_index type_id_with_cvr() BOOST_NOEXCEPT { + return type_index::construct_with_cvr(); +} + /// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. /// This method available only with RTTI enabled. template diff --git a/boost/type_index/type_index_minimal.hpp b/boost/type_index/type_index_minimal.hpp index f4690f7..52662af 100644 --- a/boost/type_index/type_index_minimal.hpp +++ b/boost/type_index/type_index_minimal.hpp @@ -34,6 +34,11 @@ type_index type_id() { return template_index::construct(); } +template +type_index type_id_with_cvr() { + return template_index::construct_with_cvr(); +} + } // namespace boost #endif // BOOST_NO_RTTI diff --git a/libs/type_index/examples/exact_types_match.cpp b/libs/type_index/examples/exact_types_match.cpp index 41f2ba1..3bb40ee 100644 --- a/libs/type_index/examples/exact_types_match.cpp +++ b/libs/type_index/examples/exact_types_match.cpp @@ -10,7 +10,7 @@ Example works with and without RTTI. In this example we'll create a class, that stores pointer to function and remembers the exact type of a parameter that function accepts. - When an attempt to call the stored function will be made, type of input parameter will be checked for exact match with initail/erased type of function. + When an attempt to call the stored function will be made, type of input parameter will be checked for exact match with initaily erased type of function. */ #include diff --git a/libs/type_index/test/template_index_tests.ipp b/libs/type_index/test/template_index_tests.ipp index fefc531..9d4efda 100644 --- a/libs/type_index/test/template_index_tests.ipp +++ b/libs/type_index/test/template_index_tests.ipp @@ -109,6 +109,32 @@ BOOST_AUTO_TEST_CASE(template_id_storing_modifiers) test_with_modofiers(); } +template +static void test_storing_nonstoring_modifiers_templ() { + using namespace boost; + + template_index t1 = template_id_with_cvr(); + template_index t2 = template_id(); + + BOOST_CHECK_EQUAL(t2, t1); + BOOST_CHECK_EQUAL(t1, t2); + BOOST_CHECK(t1 <= t2); + BOOST_CHECK(t1 >= t2); + BOOST_CHECK(t2 <= t1); + BOOST_CHECK(t2 >= t1); +} + +BOOST_AUTO_TEST_CASE(template_id_storing_modifiers_vs_nonstoring) +{ + test_storing_nonstoring_modifiers_templ(); + test_storing_nonstoring_modifiers_templ(); + test_storing_nonstoring_modifiers_templ(); + + boost::template_index t1 = boost::template_id_with_cvr(); + boost::template_index t2 = boost::template_id(); + BOOST_CHECK_NE(t2, t1); +} + BOOST_AUTO_TEST_CASE(template_index_stream_operator_via_lexical_cast_testing) { using namespace boost; diff --git a/libs/type_index/test/type_index_tests.ipp b/libs/type_index/test/type_index_tests.ipp index 203f77c..748ab44 100644 --- a/libs/type_index/test/type_index_tests.ipp +++ b/libs/type_index/test/type_index_tests.ipp @@ -103,6 +103,88 @@ BOOST_AUTO_TEST_CASE(comparators_type_id_vs_type_info) #endif // BOOST_NO_RTTI +template +static void test_with_modofiers_type_id() { + using namespace boost; + + type_index t1 = type_id_with_cvr(); + type_index t2 = type_id_with_cvr(); + + BOOST_CHECK_NE(t2, t1); + BOOST_CHECK(t1 < t2 || t2 < t1); + BOOST_CHECK(t1 > t2 || t2 > t1); + + BOOST_CHECK_EQUAL(t1, type_id_with_cvr()); + BOOST_CHECK_EQUAL(t2, type_id_with_cvr()); + + BOOST_CHECK_EQUAL(t1.hash_code(), type_id_with_cvr().hash_code()); + BOOST_CHECK_EQUAL(t2.hash_code(), type_id_with_cvr().hash_code()); + + BOOST_CHECK_NE(t1.hash_code(), type_id_with_cvr().hash_code()); + BOOST_CHECK_NE(t2.hash_code(), type_id_with_cvr().hash_code()); +} + +BOOST_AUTO_TEST_CASE(type_id_storing_modifiers) +{ + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); + test_with_modofiers_type_id(); +} + +template +static void test_storing_nonstoring_modifiers() { + using namespace boost; + + type_index t1 = type_id_with_cvr(); + type_index t2 = type_id(); + + BOOST_CHECK_EQUAL(t2, t1); + BOOST_CHECK_EQUAL(t1, t2); + BOOST_CHECK(t1 <= t2); + BOOST_CHECK(t1 >= t2); + BOOST_CHECK(t2 <= t1); + BOOST_CHECK(t2 >= t1); +} + +BOOST_AUTO_TEST_CASE(type_id_storing_modifiers_vs_nonstoring) +{ + test_storing_nonstoring_modifiers(); + test_storing_nonstoring_modifiers(); + test_storing_nonstoring_modifiers(); + + boost::type_index t1 = boost::type_id_with_cvr(); + boost::type_index t2 = boost::type_id(); + BOOST_CHECK_NE(t2, t1); +} + BOOST_AUTO_TEST_CASE(type_index_stream_operator_via_lexical_cast_testing) { using namespace boost;