mirror of
https://github.com/boostorg/type_index.git
synced 2025-07-31 12:57:17 +02:00
Compile time type info implementation added
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
#if (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
|
||||
# include <boost/type_index/stl_type_index.ipp>
|
||||
#else
|
||||
|
||||
# include <boost/type_index/ctti_type_index.ipp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeind {
|
||||
@@ -36,7 +36,7 @@ namespace boost { namespace typeind {
|
||||
#if (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
|
||||
typedef boost::typeind::detail::type_index_base<std::type_info> type_index;
|
||||
#else
|
||||
|
||||
typedef boost::typeind::detail::type_index_base<boost::typeind::detail::ctti_data> type_index;
|
||||
#endif
|
||||
|
||||
typedef type_index::type_info_t type_info;
|
||||
|
134
include/boost/type_index/ctti_type_index.ipp
Normal file
134
include/boost/type_index/ctti_type_index.ipp
Normal file
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// Copyright (c) Antony Polukhin, 2013-2014.
|
||||
//
|
||||
//
|
||||
// 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_CTTI_TYPE_INDEX_IPP
|
||||
#define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_IPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/// \file stl_type_index.ipp
|
||||
/// \brief Contains specialization of boost::type_index_base<std::type_info>.
|
||||
///
|
||||
/// boost::type_index_base<std::type_info> class can be used as a drop-in replacement
|
||||
/// for std::type_index.
|
||||
///
|
||||
/// It is used in situations when RTTI is enabled or typeid() method is available.
|
||||
/// When typeid() is not is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined boost::template_info
|
||||
/// is usually used instead of it (some compilers allow calling typeid(T)
|
||||
/// even if RTTI is disabled, those copilers will continue to use boost::type_info class).
|
||||
|
||||
#include <boost/type_index/type_index_base.hpp>
|
||||
#include <boost/type_index/detail/compile_time_type_info.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#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/detail/no_exceptions_support.hpp>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
|
||||
namespace boost { namespace typeind { namespace detail {
|
||||
|
||||
struct ctti_data {
|
||||
const char* const typename_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline const ctti_data& ctti_construct() BOOST_NOEXCEPT {
|
||||
static const ctti_data result = { boost::detail::ctti<T>::n() };
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
type_index_base<ctti_data> type_index_base<ctti_data>::construct() BOOST_NOEXCEPT {
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
|
||||
return ctti_construct<no_cvr_t>();
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
type_index_base<ctti_data> type_index_base<ctti_data>::construct_with_cvr() BOOST_NOEXCEPT {
|
||||
return ctti_construct<T>();
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
type_index_base<ctti_data> type_index_base<ctti_data>::construct_runtime(T& rtti_val) BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false,
|
||||
"type_id_runtime(T&) and type_index::construct_runtime(T&) require RTTI");
|
||||
|
||||
return ctti_construct<T>();
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
type_index_base<ctti_data> type_index_base<ctti_data>::construct_runtime(T* rtti_val) {
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false,
|
||||
"type_id_runtime(T*) and type_index::construct_runtime(T*) require RTTI");
|
||||
|
||||
return ctti_construct<T>();
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
const char* type_index_base<ctti_data>::raw_name() const BOOST_NOEXCEPT {
|
||||
return data_->typename_;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
const char* type_index_base<ctti_data>::name() const BOOST_NOEXCEPT {
|
||||
return data_->typename_;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string type_index_base<ctti_data>::pretty_name() const {
|
||||
std::size_t len = std::strlen(raw_name() + ctti_skip_size_at_end);
|
||||
while (raw_name()[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces
|
||||
return std::string(raw_name(), len);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool type_index_base<ctti_data>::equal(const type_index_base<ctti_data>& rhs) const BOOST_NOEXCEPT {
|
||||
return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name());
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool type_index_base<ctti_data>::before(const type_index_base<ctti_data>& rhs) const BOOST_NOEXCEPT {
|
||||
return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
std::size_t type_index_base<ctti_data>::hash_code() const BOOST_NOEXCEPT {
|
||||
return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name() + detail::ctti_skip_size_at_end));
|
||||
}
|
||||
|
||||
|
||||
}}} // namespace boost::typeind::detail
|
||||
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_IPP
|
||||
|
139
include/boost/type_index/detail/compile_time_type_info.hpp
Normal file
139
include/boost/type_index/detail/compile_time_type_info.hpp
Normal file
@@ -0,0 +1,139 @@
|
||||
//
|
||||
// Copyright (c) Antony Polukhin, 2012-2014.
|
||||
//
|
||||
//
|
||||
// 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_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
|
||||
#define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
||||
/// \file compile_time_type_info.hpp
|
||||
/// \brief Contains implementation of boost::ctti class.
|
||||
///
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost { namespace typeind { namespace detail {
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE
|
||||
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is used by boost::template_info class to
|
||||
/// deduce the name of a template parameter. If your compiler is not recognized
|
||||
/// by the TypeIndex library and you wish to work with boost::template_info, you may
|
||||
/// define this macro by yourself.
|
||||
///
|
||||
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE must be defined to a compiler specific macro,
|
||||
/// that outputs the WHOLE function signature, including template parameters.
|
||||
///
|
||||
/// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined,
|
||||
/// then a compile-time error will arise at any attempt to use boost::template_info or
|
||||
/// boost::template_index classes.
|
||||
#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP
|
||||
///
|
||||
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE, BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP
|
||||
/// and BOOST_TYPE_INDEX_CTTI_END_SKIP macroses are used for adding a
|
||||
/// support for compilers, that by default are not recognized by TypeIndex library.
|
||||
///
|
||||
/// See Compiler support for more info
|
||||
#define BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP 0
|
||||
|
||||
/// \def BOOST_TYPE_INDEX_CTTI_END_SKIP
|
||||
///
|
||||
/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE, BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP
|
||||
/// and BOOST_TYPE_INDEX_CTTI_END_SKIP macroses are used for adding a
|
||||
/// support for compilers, that by default are not recognized by TypeIndex library.
|
||||
///
|
||||
/// See Compiler support for more info
|
||||
#define BOOST_TYPE_INDEX_CTTI_END_SKIP 0
|
||||
|
||||
#elif defined(BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP) && defined(BOOST_TYPE_INDEX_CTTI_END_SKIP)
|
||||
// skip user specified bytes count
|
||||
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);
|
||||
#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<T>::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
|
||||
|
||||
}}} // namespace boost::typeind::detail
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
/// 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 <class T>
|
||||
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 {
|
||||
#if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
|
||||
return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE + boost::typeind::detail::ctti_skip_size_at_begin;
|
||||
#elif defined(__FUNCSIG__)
|
||||
return __FUNCSIG__ + boost::typeind::detail::ctti_skip_size_at_begin;
|
||||
#elif defined(__PRETTY_FUNCTION__) \
|
||||
|| defined(__GNUC__) \
|
||||
|| (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
|
||||
|| (defined(__ICC) && (__ICC >= 600)) \
|
||||
|| defined(__ghs__) \
|
||||
|| defined(__DMC__)
|
||||
|
||||
return __PRETTY_FUNCTION__ + boost::typeind::detail::ctti_skip_size_at_begin;
|
||||
#else
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
sizeof(T) && false,
|
||||
"TypeIndex library could not detect your compiler. "
|
||||
"Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use "
|
||||
"correct compiler macro for getting the whole function name. "
|
||||
"Do not forget to also define BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP and "
|
||||
"BOOST_TYPE_INDEX_CTTI_END_SKIP."
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Returns raw name
|
||||
static const char* name() BOOST_NOEXCEPT {
|
||||
return this_type::n();
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::detail
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
|
||||
|
@@ -75,7 +75,7 @@ type_index_base<std::type_info> type_index_base<std::type_info>::construct() BOO
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
const type_index_base<std::type_info>& type_index_base<std::type_info>::construct_with_cvr() BOOST_NOEXCEPT {
|
||||
type_index_base<std::type_info> type_index_base<std::type_info>::construct_with_cvr() BOOST_NOEXCEPT {
|
||||
typedef typename boost::mpl::if_c<
|
||||
boost::is_reference<T>::value
|
||||
|| boost::is_const<T>::value
|
||||
@@ -90,7 +90,7 @@ const type_index_base<std::type_info>& type_index_base<std::type_info>::construc
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
type_index_base<std::type_info>& type_index_base<std::type_info>::construct_runtime(T& rtti_val) BOOST_NOEXCEPT {
|
||||
type_index_base<std::type_info> type_index_base<std::type_info>::construct_runtime(T& rtti_val) BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_NO_RTTI
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false,
|
||||
"type_id_runtime(T&) and type_index::construct_runtime(T&) require RTTI");
|
||||
@@ -211,7 +211,7 @@ std::size_t type_index_base<std::type_info>::hash_code() const BOOST_NOEXCEPT {
|
||||
#if _MSC_VER > 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
return data_->hash_code();
|
||||
#else
|
||||
return boost::hash_range(raw_name(), raw_name() + std::strlen(name()));
|
||||
return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -34,6 +34,7 @@ nortti = <toolset>gcc:<cxxflags>-fno-rtti <toolset>clang:<cxxflags>-fno-rtti <to
|
||||
test-suite type_index
|
||||
:
|
||||
[ run type_index_test.cpp $(tlib) ]
|
||||
[ run type_index_test.cpp $(tlib) : : : <rtti>off : type_index_test_no_rtti ]
|
||||
# [ run template_index_test.cpp $(tlib) ]
|
||||
# [ run testing_both.cpp $(tlib) ]
|
||||
# [ run testing_both_no_rtti.cpp $(tlib) : : : <rtti>off ]
|
||||
|
Reference in New Issue
Block a user