forked from boostorg/type_index
Now type_index class can store cvr modifiers too.
This commit is contained in:
@@ -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<T>()`.
|
||||
template <class T>
|
||||
template_index template_id_with_cvr() BOOST_NOEXCEPT {
|
||||
return template_index::construct_with_cvr<T>();
|
||||
|
@@ -26,8 +26,12 @@
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/type_traits/is_volatile.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
@@ -67,6 +71,10 @@ namespace boost {
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
namespace detail {
|
||||
template <class T> 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<T>()`.
|
||||
template <class T>
|
||||
static type_index construct_with_cvr() BOOST_NOEXCEPT {
|
||||
typedef typename boost::mpl::if_c<
|
||||
boost::is_reference<T>::value
|
||||
|| boost::is_const<T>::value
|
||||
|| boost::is_volatile<T>::value,
|
||||
detail::cvr_saver<T>,
|
||||
T
|
||||
>::type type;
|
||||
return construct<type>();
|
||||
}
|
||||
|
||||
/// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
|
||||
/// This method available only with RTTI enabled.
|
||||
template <class T>
|
||||
@@ -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<T>();
|
||||
}
|
||||
|
||||
/// 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<T>()`.
|
||||
template <class T>
|
||||
type_index type_id_with_cvr() BOOST_NOEXCEPT {
|
||||
return type_index::construct_with_cvr<T>();
|
||||
}
|
||||
|
||||
/// Function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
|
||||
/// This method available only with RTTI enabled.
|
||||
template <class T>
|
||||
|
@@ -34,6 +34,11 @@ type_index type_id() {
|
||||
return template_index::construct<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
type_index type_id_with_cvr() {
|
||||
return template_index::construct_with_cvr<T>();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NO_RTTI
|
||||
|
@@ -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 <boost/type_index.hpp>
|
||||
|
@@ -109,6 +109,32 @@ BOOST_AUTO_TEST_CASE(template_id_storing_modifiers)
|
||||
test_with_modofiers<int&, const volatile int&>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void test_storing_nonstoring_modifiers_templ() {
|
||||
using namespace boost;
|
||||
|
||||
template_index t1 = template_id_with_cvr<T>();
|
||||
template_index t2 = template_id<T>();
|
||||
|
||||
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<int>();
|
||||
test_storing_nonstoring_modifiers_templ<my_namespace1::my_class>();
|
||||
test_storing_nonstoring_modifiers_templ<my_namespace2::my_class>();
|
||||
|
||||
boost::template_index t1 = boost::template_id_with_cvr<const int>();
|
||||
boost::template_index t2 = boost::template_id<int>();
|
||||
BOOST_CHECK_NE(t2, t1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_index_stream_operator_via_lexical_cast_testing)
|
||||
{
|
||||
using namespace boost;
|
||||
|
@@ -103,6 +103,88 @@ BOOST_AUTO_TEST_CASE(comparators_type_id_vs_type_info)
|
||||
|
||||
#endif // BOOST_NO_RTTI
|
||||
|
||||
template <class T1, class T2>
|
||||
static void test_with_modofiers_type_id() {
|
||||
using namespace boost;
|
||||
|
||||
type_index t1 = type_id_with_cvr<T1>();
|
||||
type_index t2 = type_id_with_cvr<T2>();
|
||||
|
||||
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<T1>());
|
||||
BOOST_CHECK_EQUAL(t2, type_id_with_cvr<T2>());
|
||||
|
||||
BOOST_CHECK_EQUAL(t1.hash_code(), type_id_with_cvr<T1>().hash_code());
|
||||
BOOST_CHECK_EQUAL(t2.hash_code(), type_id_with_cvr<T2>().hash_code());
|
||||
|
||||
BOOST_CHECK_NE(t1.hash_code(), type_id_with_cvr<T2>().hash_code());
|
||||
BOOST_CHECK_NE(t2.hash_code(), type_id_with_cvr<T1>().hash_code());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_id_storing_modifiers)
|
||||
{
|
||||
test_with_modofiers_type_id<int, const int>();
|
||||
test_with_modofiers_type_id<int, const int&>();
|
||||
test_with_modofiers_type_id<int, int&>();
|
||||
test_with_modofiers_type_id<int, volatile int>();
|
||||
test_with_modofiers_type_id<int, volatile int&>();
|
||||
test_with_modofiers_type_id<int, const volatile int>();
|
||||
test_with_modofiers_type_id<int, const volatile int&>();
|
||||
|
||||
test_with_modofiers_type_id<const int, int>();
|
||||
test_with_modofiers_type_id<const int, const int&>();
|
||||
test_with_modofiers_type_id<const int, int&>();
|
||||
test_with_modofiers_type_id<const int, volatile int>();
|
||||
test_with_modofiers_type_id<const int, volatile int&>();
|
||||
test_with_modofiers_type_id<const int, const volatile int>();
|
||||
test_with_modofiers_type_id<const int, const volatile int&>();
|
||||
|
||||
test_with_modofiers_type_id<const int&, int>();
|
||||
test_with_modofiers_type_id<const int&, const int>();
|
||||
test_with_modofiers_type_id<const int&, int&>();
|
||||
test_with_modofiers_type_id<const int&, volatile int>();
|
||||
test_with_modofiers_type_id<const int&, volatile int&>();
|
||||
test_with_modofiers_type_id<const int&, const volatile int>();
|
||||
test_with_modofiers_type_id<const int&, const volatile int&>();
|
||||
|
||||
test_with_modofiers_type_id<int&, const int>();
|
||||
test_with_modofiers_type_id<int&, const int&>();
|
||||
test_with_modofiers_type_id<int&, int>();
|
||||
test_with_modofiers_type_id<int&, volatile int>();
|
||||
test_with_modofiers_type_id<int&, volatile int&>();
|
||||
test_with_modofiers_type_id<int&, const volatile int>();
|
||||
test_with_modofiers_type_id<int&, const volatile int&>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void test_storing_nonstoring_modifiers() {
|
||||
using namespace boost;
|
||||
|
||||
type_index t1 = type_id_with_cvr<T>();
|
||||
type_index t2 = type_id<T>();
|
||||
|
||||
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<int>();
|
||||
test_storing_nonstoring_modifiers<my_namespace1::my_class>();
|
||||
test_storing_nonstoring_modifiers<my_namespace2::my_class>();
|
||||
|
||||
boost::type_index t1 = boost::type_id_with_cvr<const int>();
|
||||
boost::type_index t2 = boost::type_id<int>();
|
||||
BOOST_CHECK_NE(t2, t1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_index_stream_operator_via_lexical_cast_testing)
|
||||
{
|
||||
using namespace boost;
|
||||
|
Reference in New Issue
Block a user