Make code thread safe even on antique/broken compilers. Improve examples and add more tests

This commit is contained in:
Antony Polukhin
2014-02-21 12:52:07 +04:00
parent 2ebd172f4e
commit 40f6ae1ede
7 changed files with 75 additions and 19 deletions

View File

@@ -49,15 +49,16 @@ namespace my_namespace { namespace detail {
// my_typeinfo structure is used to save type number
struct my_typeinfo {
// type_[0] will hold a type number
// type_[1] will be '\0', to have a zero terminated raw type name
char type_[2];
const char* const type_;
};
const my_typeinfo infos[5] = {
{"void"}, {"my_class"}, {"my_struct"}, {"my_classes"}, {"my_string"}
};
template <class T>
inline const my_typeinfo& my_typeinfo_construct() {
static const my_typeinfo ret = {{ static_cast<char>(typenum<T>::value), '\0' }};
return ret;
return infos[typenum<T>::value];
}
}} // my_namespace::detail
@@ -97,13 +98,7 @@ public:
}
inline std::string pretty_name() const {
// Must be in sync with detail::typenum<T>::value
static const char* names[] = {
"void", "my_class", "my_struct", "my_classes", "my_string"
};
const std::size_t indx = static_cast<std::size_t>(data_->type_[0]);
return names[indx];
return data_->type_;
}
template <class T>

View File

@@ -61,6 +61,8 @@ namespace boost { namespace typeind {
///
/// Could be a std::type_info, boost::typeind::detail::ctti_data or
/// some user defined class.
///
/// type_info \b is \b not copyable or default constructible. It is \b not assignable too!
typedef type_index::type_info_t type_info;
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)

View File

@@ -35,17 +35,25 @@ namespace boost { namespace typeind {
namespace detail {
struct ctti_data {
const char* typename_;
};
// That's the most trickiest part of the TypeIndex library:
// 1) we do not whant to give user ability to manually construct and compare `struct-that-represents-type`
// 2) we need to distinguish beteween `struct-that-represents-type` and `const char*`
// 3) we need a thread-safe way to have references to instances `struct-that-represents-type`
// 4) we need a compile-time control to make shure that user does not copy or
// default construct `struct-that-represents-type`
//
// Solution would be a forward declared structure.
struct ctti_data;
} // namespace detail
/// Helper method for getting detail::ctti_data of a tempalte patameter T.
template <class T>
inline const detail::ctti_data& ctti_construct() BOOST_NOEXCEPT {
static const detail::ctti_data result = { boost::detail::ctti<T>::n() };
return result;
// Standard C++11, 5.2.10 Reinterpret cast: Converting a prvalue of type “pointer to T1” to the
// type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no
// stricter than those of T1) and back to its original type yields the original pointer value.
return *reinterpret_cast<const detail::ctti_data*>(boost::detail::ctti<T>::n());
}
/// \class ctti_type_index
@@ -111,7 +119,7 @@ inline ctti_type_index ctti_type_index::type_id_runtime(const T& variable) BOOST
inline const char* ctti_type_index::raw_name() const BOOST_NOEXCEPT {
return data_->typename_;
return reinterpret_cast<const char*>(data_);
}

View File

@@ -38,7 +38,9 @@ test-suite type_index
[ run type_index_test.cpp $(tlib) : : : <rtti>off : type_index_test_no_rtti ]
[ run testing_crossmodule.cpp test_lib_rtti $(tlib) ]
[ run testing_crossmodule.cpp test_lib_nortti $(tlib) : : : <rtti>off : testing_crossmodule_no_rtti ]
[ compile-fail type_index_test_ctti_copy_fail.cpp ]
[ compile-fail type_index_test_ctti_construct_fail.cpp ]
# Mixing RTTI on and off
[ link-fail testing_crossmodule.cpp $(tlib) test_lib_rtti : $(nortti) : link_fail_nortti_rtti ]
# MSVC sometimes overrides the /GR-, that's why the following tests is disabled

View File

@@ -100,11 +100,30 @@ static void test_with_modofiers() {
type_index t2 = type_id_with_cvr<T2>();
BOOST_CHECK_NE(t2, t1);
BOOST_CHECK(t2 != t1.type_info());
BOOST_CHECK(t2.type_info() != t1);
BOOST_CHECK(t1 < t2 || t2 < t1);
BOOST_CHECK(t1 > t2 || t2 > t1);
BOOST_CHECK(t1.type_info() < t2 || t2.type_info() < t1);
BOOST_CHECK(t1.type_info() > t2 || t2.type_info() > t1);
BOOST_CHECK(t1 < t2.type_info() || t2 < t1.type_info());
BOOST_CHECK(t1 > t2.type_info() || t2 > t1.type_info());
// Chaecking that comparisom operators overloads compile
BOOST_CHECK(t1 <= t2 || t2 <= t1);
BOOST_CHECK(t1 >= t2 || t2 >= t1);
BOOST_CHECK(t1.type_info() <= t2 || t2.type_info() <= t1);
BOOST_CHECK(t1.type_info() >= t2 || t2.type_info() >= t1);
BOOST_CHECK(t1 <= t2.type_info() || t2 <= t1.type_info());
BOOST_CHECK(t1 >= t2.type_info() || t2 >= t1.type_info());
BOOST_CHECK_EQUAL(t1, type_id_with_cvr<T1>());
BOOST_CHECK_EQUAL(t2, type_id_with_cvr<T2>());
BOOST_CHECK(t1 == type_id_with_cvr<T1>().type_info());
BOOST_CHECK(t2 == type_id_with_cvr<T2>().type_info());
BOOST_CHECK(t1.type_info() == type_id_with_cvr<T1>());
BOOST_CHECK(t2.type_info() == 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());

View File

@@ -0,0 +1,15 @@
//
// 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)
#include <boost/type_index/ctti_type_index.hpp>
int main() {
using namespace boost::typeind;
ctti_type_index::type_info_t t;
(void)t;
}

View File

@@ -0,0 +1,15 @@
//
// 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)
#include <boost/type_index/ctti_type_index.hpp>
int main() {
using namespace boost::typeind;
ctti_type_index::type_info_t t = ctti_type_index::type_id<int>().type_info();
(void)t;
}