forked from boostorg/type_index
Started the work on new interface
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) Antony Polukhin, 2012-2013.
|
||||
// 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)
|
||||
@ -25,10 +25,57 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/type_index/type_info.hpp>
|
||||
#include <boost/type_index/type_index.hpp>
|
||||
#include <boost/type_index/template_info.hpp>
|
||||
#include <boost/type_index/template_index.hpp>
|
||||
#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
|
||||
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
#endif
|
||||
|
||||
typedef type_index::type_info_t type_info;
|
||||
|
||||
// TODO:
|
||||
// inline bool is_equal(const type_info&, const type_info&) BOOST_NOEXCEPT;
|
||||
// inline bool is_before(const type_info&, const type_info&) BOOST_NOEXCEPT;
|
||||
|
||||
|
||||
/// Function to get boost::type_index for a type T.
|
||||
/// Strips const, volatile and & modifiers from T.
|
||||
template <class T>
|
||||
inline type_index type_id() BOOST_NOEXCEPT {
|
||||
return type_index::construct<T>();
|
||||
}
|
||||
|
||||
/// Function for constructing boost::type_index instance for type T.
|
||||
/// Does not strip 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>
|
||||
inline 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.
|
||||
template <class T>
|
||||
inline type_index type_id_runtime(T& runtime_val) BOOST_NOEXCEPT {
|
||||
return type_index::construct_runtime(runtime_val);
|
||||
}
|
||||
|
||||
/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info.
|
||||
template <class T>
|
||||
inline type_index type_id_runtime(T* runtime_val) {
|
||||
return type_index::construct_runtime(runtime_val);
|
||||
}
|
||||
|
||||
}} // namespace boost::typeind
|
||||
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_HPP
|
||||
|
||||
|
223
include/boost/type_index/stl_type_index.ipp
Normal file
223
include/boost/type_index/stl_type_index.ipp
Normal file
@ -0,0 +1,223 @@
|
||||
//
|
||||
// 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_STL_TYPE_INDEX_IPP
|
||||
#define BOOST_TYPE_INDEX_STL_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>
|
||||
|
||||
|
||||
// MSVC is capable of calling typeid(T) even when RTTI is off
|
||||
#if defined(BOOST_NO_RTTI) && !defined(BOOST_MSVC)
|
||||
#error "File boost/type_index/stl_type_index.ipp is not usable when typeid() is not available."
|
||||
#endif
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
|
||||
#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 {
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
type_index_base<std::type_info> type_index_base<std::type_info>::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;
|
||||
|
||||
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|
||||
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
|
||||
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<no_cvr_t>::type::value
|
||||
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
|
||||
#endif
|
||||
|
||||
return typeid(no_cvr_t);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
const 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
|
||||
|| boost::is_volatile<T>::value,
|
||||
detail::cvr_saver<T>,
|
||||
T
|
||||
>::type type;
|
||||
|
||||
return typeid(type);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
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");
|
||||
#endif
|
||||
|
||||
return typeid(rtti_val);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
type_index_base<std::type_info> type_index_base<std::type_info>::construct_runtime(T* rtti_val) {
|
||||
#ifdef BOOST_NO_RTTI
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false,
|
||||
"type_id_runtime(T*) and type_index::construct_runtime(T*) require RTTI");
|
||||
#endif
|
||||
return typeid(rtti_val);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
const char* type_index_base<std::type_info>::raw_name() const BOOST_NOEXCEPT {
|
||||
#ifdef _MSC_VER
|
||||
return data_->raw_name();
|
||||
#else
|
||||
return data_->name();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
const char* type_index_base<std::type_info>::name() const BOOST_NOEXCEPT {
|
||||
return data_->name();
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string type_index_base<std::type_info>::pretty_name() const {
|
||||
#if defined(_MSC_VER)
|
||||
std::string ret = data_->name();
|
||||
#else
|
||||
std::string ret;
|
||||
int status = 0;
|
||||
char* demang = abi::__cxa_demangle(raw_name(), NULL, 0, &status);
|
||||
BOOST_ASSERT(!status);
|
||||
|
||||
BOOST_TRY {
|
||||
ret = demang; // may throw out of memory exception
|
||||
} BOOST_CATCH (...) {
|
||||
free(demang);
|
||||
BOOST_RETHROW;
|
||||
} BOOST_CATCH_END
|
||||
|
||||
free(demang);
|
||||
#endif
|
||||
|
||||
std::string::size_type pos = ret.find("boost::typeind::detail::cvr_saver<");
|
||||
if (pos == std::string::npos) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pos += sizeof("boost::typeind::detail::cvr_saver<") - 1;
|
||||
while (ret[pos] == ' ') {
|
||||
++ pos;
|
||||
}
|
||||
|
||||
std::string::size_type end = ret.rfind(">");
|
||||
BOOST_ASSERT(end != std::string::npos);
|
||||
while (ret[end - 1] == ' ') {
|
||||
-- end;
|
||||
}
|
||||
|
||||
return ret.substr(pos, end - pos);
|
||||
}
|
||||
|
||||
|
||||
/// @cond
|
||||
|
||||
// for this compiler at least, cross-shared-library type_info
|
||||
// comparisons don't work, so we are using typeid(x).name() instead.
|
||||
# if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \
|
||||
|| 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
|
||||
|
||||
/// @endcond
|
||||
|
||||
|
||||
template <>
|
||||
bool type_index_base<std::type_info>::equal(const type_index_base<std::type_info>& rhs) const BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name());
|
||||
#else
|
||||
return *data_ == *rhs.data_;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool type_index_base<std::type_info>::before(const type_index_base<std::type_info>& rhs) const BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0;
|
||||
#else
|
||||
return !!data_->before(*rhs.data_);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
#undef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
#endif
|
||||
|
||||
|
||||
template <>
|
||||
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()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}}} // namespace boost::typeind::detail
|
||||
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_IPP
|
||||
|
125
include/boost/type_index/type_index_base.hpp
Normal file
125
include/boost/type_index/type_index_base.hpp
Normal file
@ -0,0 +1,125 @@
|
||||
//
|
||||
// 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_TYPE_INDEX_BASE_HPP
|
||||
#define BOOST_TYPE_INDEX_TYPE_INDEX_BASE_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
|
||||
#if !defined(BOOST_NO_IOSTREAM)
|
||||
#if !defined(BOOST_NO_IOSFWD)
|
||||
#include <iosfwd> // for std::basic_ostream
|
||||
#else
|
||||
#include <ostream>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost { namespace typeind { namespace detail {
|
||||
|
||||
template <class T> class cvr_saver{};
|
||||
|
||||
template <class TypeInfo>
|
||||
class type_index_base {
|
||||
const TypeInfo* data_;
|
||||
|
||||
public:
|
||||
typedef TypeInfo type_info_t;
|
||||
typedef type_index_base<TypeInfo> this_type;
|
||||
|
||||
type_index_base(const TypeInfo& info) BOOST_NOEXCEPT
|
||||
: data_(&info)
|
||||
{}
|
||||
|
||||
const type_info_t& type_info() const BOOST_NOEXCEPT {
|
||||
return *data_;
|
||||
}
|
||||
|
||||
// All of the following methods must be explicitly specialized for each type_index_base.
|
||||
const char* raw_name() const BOOST_NOEXCEPT;
|
||||
const char* name() const BOOST_NOEXCEPT;
|
||||
std::string pretty_name() const;
|
||||
std::size_t hash_code() const BOOST_NOEXCEPT;
|
||||
bool equal(const this_type& rhs) const BOOST_NOEXCEPT;
|
||||
bool before(const this_type& rhs) const BOOST_NOEXCEPT;
|
||||
|
||||
template <class T>
|
||||
static this_type construct() BOOST_NOEXCEPT;
|
||||
template <class T>
|
||||
static this_type construct_with_cvr() BOOST_NOEXCEPT;
|
||||
template <class T>
|
||||
static this_type construct_runtime(T&) BOOST_NOEXCEPT;
|
||||
template <class T>
|
||||
static this_type construct_runtime(T* rtti_val);
|
||||
};
|
||||
|
||||
|
||||
template <class TypeInfo>
|
||||
inline bool operator == (const type_index_base<TypeInfo>& lhs, const type_index_base<TypeInfo>& rhs) BOOST_NOEXCEPT {
|
||||
return lhs.equal(rhs);
|
||||
}
|
||||
|
||||
template <class TypeInfo>
|
||||
inline bool operator < (const type_index_base<TypeInfo>& lhs, const type_index_base<TypeInfo>& rhs) BOOST_NOEXCEPT {
|
||||
return lhs.before(rhs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class TypeInfo>
|
||||
inline bool operator > (const type_index_base<TypeInfo>& lhs, const type_index_base<TypeInfo>& rhs) BOOST_NOEXCEPT {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template <class TypeInfo>
|
||||
inline bool operator <= (const type_index_base<TypeInfo>& lhs, const type_index_base<TypeInfo>& rhs) BOOST_NOEXCEPT {
|
||||
return !(lhs > rhs);
|
||||
}
|
||||
|
||||
template <class TypeInfo>
|
||||
inline bool operator >= (const type_index_base<TypeInfo>& lhs, const type_index_base<TypeInfo>& rhs) BOOST_NOEXCEPT {
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template <class TypeInfo>
|
||||
inline bool operator != (const type_index_base<TypeInfo>& lhs, const type_index_base<TypeInfo>& rhs) BOOST_NOEXCEPT {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
|
||||
/// Ostream operator that will output demangled name
|
||||
template <class TypeInfo>
|
||||
inline std::ostream& operator<<(std::ostream& ostr, const type_index_base<TypeInfo>& ind) {
|
||||
ostr << ind.pretty_name();
|
||||
return ostr;
|
||||
}
|
||||
#else
|
||||
/// Ostream operator that will output demangled name
|
||||
template <class CharT, class TriatT, class TypeInfo>
|
||||
inline std::basic_ostream<CharT, TriatT>& operator<<(
|
||||
std::basic_ostream<CharT, TriatT>& ostr,
|
||||
const type_index_base<TypeInfo>& ind)
|
||||
{
|
||||
ostr << ind.pretty_name();
|
||||
return ostr;
|
||||
}
|
||||
#endif // BOOST_NO_TEMPLATED_IOSTREAMS
|
||||
#endif // BOOST_NO_IOSTREAM
|
||||
|
||||
|
||||
}}} // namespace boost::typeind::detail
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_TYPE_INDEX_BASE_HPP
|
||||
|
@ -1,373 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_TYPE_INFO_HPP
|
||||
#define BOOST_TYPE_INDEX_TYPE_INFO_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/// \file type_info.hpp
|
||||
/// \brief Contains implementation of boost::type_info class.
|
||||
///
|
||||
/// boost::type_info class can be used as a drop-in replacement for std::type_info, but unlike std::type_info
|
||||
/// this class has a name_demangled() function for getting human-readable type names.
|
||||
///
|
||||
/// boost::type_info class is used in situations when RTTI is enabled.
|
||||
/// When RTTI 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/config.hpp>
|
||||
|
||||
|
||||
// MSVC is capable of calling typeid(T) even when RTTI is off
|
||||
#if (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <boost/config.hpp>
|
||||
#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>
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
/// @cond
|
||||
|
||||
// for this compiler at least, cross-shared-library type_info
|
||||
// comparisons don't work, so we are using typeid(x).name() instead.
|
||||
# if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \
|
||||
|| 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
|
||||
|
||||
/// @endcond
|
||||
|
||||
namespace detail {
|
||||
#ifdef BOOST_NO_STD_TYPEINFO
|
||||
typedef type_info stl_type_info;
|
||||
#else
|
||||
typedef std::type_info stl_type_info;
|
||||
#endif
|
||||
|
||||
template <class T> class cvr_saver{};
|
||||
}
|
||||
|
||||
/// boost::type_info is a class that can be used as a drop-in replacement for std::type_info.
|
||||
///
|
||||
/// boost::type_info class is used in situations when RTTI is enabled.
|
||||
/// When RTTI is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined boost::template_info
|
||||
/// is used instead of it.
|
||||
///
|
||||
/// Unlike std::type_info this class:
|
||||
/// * has a name_demangled() function for getting human-readable type names
|
||||
/// * name() function always noexcept and returns simple mangled name as character a character array
|
||||
/// * contains workarounds for some compiler issues
|
||||
///
|
||||
/// boost::type_info is not copyable and is not default constructible. Use boost::type_id* functions
|
||||
/// to get const references to instances of boost::type_info objects.
|
||||
class type_info: public detail::stl_type_info {
|
||||
#ifndef BOOST_NO_DELETED_FUNCTIONS
|
||||
type_info() = delete;
|
||||
type_info(const type_info&) = delete;
|
||||
#else
|
||||
type_info();
|
||||
type_info(const type_info&);
|
||||
#endif
|
||||
public:
|
||||
typedef detail::stl_type_info stl_type_info;
|
||||
|
||||
/// Factory method for constructing boost::type_info instance for type T.
|
||||
/// Strips const, volatile and & modifiers from T.
|
||||
///
|
||||
/// Works exactly like boost::type_id().
|
||||
template <class T>
|
||||
static const boost::type_info& 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;
|
||||
|
||||
# if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
|
||||
|| (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
|
||||
BOOST_STATIC_ASSERT_MSG( !boost::is_arithmetic<no_cvr_t>::type::value
|
||||
, "Your EDG-based compiler seems to mistakenly distinguish 'int' from 'signed int', in typeid() expressions.");
|
||||
#endif
|
||||
|
||||
return static_cast<const boost::type_info&>(typeid(no_cvr_t));
|
||||
}
|
||||
|
||||
/// Factory method for constructing boost::type_info instance for type T.
|
||||
/// Does not strip 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>()`.
|
||||
///
|
||||
/// Works exactly like boost::type_id_with_cvr().
|
||||
template <class T>
|
||||
static const boost::type_info& 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 static_cast<const boost::type_info&>(typeid(type));
|
||||
}
|
||||
|
||||
/// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info.
|
||||
/// This method available only with RTTI enabled.
|
||||
///
|
||||
/// Same as boost::type_id_rtti_only().
|
||||
template <class T>
|
||||
static const type_info& construct_rtti_only(T& rtti_val) BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_NO_RTTI
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false,
|
||||
"boost::type_id_rtti_only(T&) and boost::type_info::construct_rtti_only(T&) require RTTI");
|
||||
#endif
|
||||
return static_cast<const boost::type_info&>(typeid(rtti_val));
|
||||
}
|
||||
|
||||
/// Factory function, that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info.
|
||||
/// This method available only with RTTI enabled.
|
||||
///
|
||||
/// Same as boost::type_id_rtti_only().
|
||||
template <class T>
|
||||
static const type_info& construct_rtti_only(T* rtti_val) {
|
||||
#ifdef BOOST_NO_RTTI
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false,
|
||||
"boost::type_id_rtti_only(T*) and boost::type_info::construct_rtti_only(T*) require RTTI");
|
||||
#endif
|
||||
return static_cast<const boost::type_info&>(typeid(rtti_val));
|
||||
}
|
||||
|
||||
/// Returns mangled type name.
|
||||
const char* name() const BOOST_NOEXCEPT {
|
||||
#ifdef _MSC_VER
|
||||
return stl_type_info::raw_name();
|
||||
#else
|
||||
return stl_type_info::name();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Returns user-friendly name
|
||||
std::string name_demangled() const {
|
||||
#if defined(_MSC_VER)
|
||||
std::string ret = stl_type_info::name();
|
||||
#else
|
||||
std::string ret;
|
||||
int status = 0;
|
||||
char* demang = abi::__cxa_demangle(name(), NULL, 0, &status);
|
||||
BOOST_ASSERT(!status);
|
||||
|
||||
BOOST_TRY {
|
||||
ret = demang; // may throw out of memory exception
|
||||
} BOOST_CATCH (...) {
|
||||
free(demang);
|
||||
BOOST_RETHROW;
|
||||
} BOOST_CATCH_END
|
||||
|
||||
free(demang);
|
||||
#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<") - 1;
|
||||
while (ret[pos] == ' ') {
|
||||
++ pos;
|
||||
}
|
||||
std::string::size_type end = ret.rfind(">");
|
||||
BOOST_ASSERT(end != std::string::npos);
|
||||
while (ret[end - 1] == ' ') {
|
||||
-- end;
|
||||
}
|
||||
|
||||
return ret.substr(pos, end - pos);
|
||||
}
|
||||
|
||||
bool operator == (type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
return name() == rhs.name() || !std::strcmp(name(), rhs.name());
|
||||
#else
|
||||
return static_cast<const stl_type_info&>(*this) == static_cast<const stl_type_info&>(rhs);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool operator != (type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool operator == (stl_type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
return *this == static_cast<const boost::type_info&>(rhs);
|
||||
}
|
||||
|
||||
bool operator != (stl_type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/// Returns true if the type precedes the type of rhs in the collation order.
|
||||
/// The collation order is just an internal order.
|
||||
/// Works exactly like operator <
|
||||
bool before(type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
return name() != rhs.name() && std::strcmp(name(), rhs.name()) < 0;
|
||||
#else
|
||||
return !!stl_type_info::before(rhs);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Returns true if the type precedes the type of rhs in the collation order.
|
||||
/// The collation order is just an internal order.
|
||||
/// Works exactly like operator <
|
||||
bool before(stl_type_info const& rhs) const BOOST_NOEXCEPT {
|
||||
return before(static_cast<const boost::type_info&>(rhs));
|
||||
}
|
||||
|
||||
/// Function for getting hash value
|
||||
std::size_t hash_code() const BOOST_NOEXCEPT {
|
||||
#if _MSC_VER > 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
return stl_type_info::hash_code();
|
||||
#else
|
||||
return boost::hash_range(name(), name() + std::strlen(name()));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
#undef BOOST_CLASSINFO_COMPARE_BY_NAMES
|
||||
#endif
|
||||
|
||||
/// Function to get boost::type_info for a type T.
|
||||
/// Strips const, volatile and & modifiers from T.
|
||||
template <class T>
|
||||
inline const type_info& type_id() BOOST_NOEXCEPT {
|
||||
return type_info::construct<T>();
|
||||
}
|
||||
|
||||
/// Function for constructing boost::type_info instance for type T.
|
||||
/// Does not strip 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>
|
||||
inline const type_info& type_id_with_cvr() BOOST_NOEXCEPT {
|
||||
return type_info::construct_with_cvr<T>();
|
||||
}
|
||||
|
||||
/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info.
|
||||
/// This method available only with RTTI enabled. Without RTTI support it won't compile,
|
||||
/// producing a compile-time error with message: "boost::type_id_rtti_only(T&) requires RTTI"
|
||||
template <class T>
|
||||
inline const type_info& type_id_rtti_only(T& rtti_val) BOOST_NOEXCEPT {
|
||||
#ifdef BOOST_NO_RTTI
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T&) requires RTTI");
|
||||
#endif
|
||||
return static_cast<const type_info&>(typeid(rtti_val));
|
||||
}
|
||||
|
||||
/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_info.
|
||||
/// This method available only with RTTI enabled. Without RTTI support it won't compile,
|
||||
/// producing a compile-time error with message: "boost::type_id_rtti_only(T*) requires RTTI"
|
||||
template <class T>
|
||||
inline const type_info& type_id_rtti_only(T* rtti_val) {
|
||||
#ifdef BOOST_NO_RTTI
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T*) requires RTTI");
|
||||
#endif
|
||||
return static_cast<const type_info&>(typeid(rtti_val));
|
||||
}
|
||||
|
||||
/* *************** type_info free functions ******************* */
|
||||
|
||||
#ifndef BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
inline bool operator == (detail::stl_type_info const& lhs, type_info const& rhs) BOOST_NOEXCEPT {
|
||||
return rhs == static_cast<const boost::type_info&>(lhs);
|
||||
}
|
||||
|
||||
inline bool operator != (detail::stl_type_info const& lhs, type_info const& rhs) BOOST_NOEXCEPT {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
#else // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
inline bool operator == (std::type_info const& lhs, type_info const& rhs) BOOST_NOEXCEPT;
|
||||
inline bool operator != (std::type_info const& lhs, type_info const& rhs) BOOST_NOEXCEPT;
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
/// hash_value function overload for boost::type_info.
|
||||
inline std::size_t hash_value(type_info const& v) BOOST_NOEXCEPT {
|
||||
return v.hash_code();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#else // !defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)
|
||||
# include <boost/type_index/template_info.hpp>
|
||||
# include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
typedef template_info type_info;
|
||||
|
||||
template <class T>
|
||||
inline const type_info& type_id() BOOST_NOEXCEPT {
|
||||
return template_info::construct<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline const type_info& type_id_with_cvr() BOOST_NOEXCEPT {
|
||||
return template_info::construct_with_cvr<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline const type_info& type_id_rtti_only(T& rtti_val) BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T&) requires RTTI");
|
||||
return template_info::construct_with_cvr<void>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline const type_info& type_id_rtti_only(T* rtti_val) {
|
||||
BOOST_STATIC_ASSERT_MSG(sizeof(T) && false, "boost::type_id_rtti_only(T*) requires RTTI");
|
||||
return template_info::construct_with_cvr<void>();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined (BOOST_MSVC)
|
||||
|
||||
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
|
||||
/// \def BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
|
||||
/// Define the BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro if you are mixing objects
|
||||
/// compiled with different RTTI flags. This will force the usage of boost::template_index
|
||||
/// class instead of boost::type_index.
|
||||
#define BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
|
||||
#endif // BOOST_TYPE_INDEX_DOXYGEN_INVOKED
|
||||
|
||||
#endif // BOOST_TYPE_INDEX_TYPE_INFO_HPP
|
||||
|
@ -18,45 +18,45 @@ compat = <define>BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY ;
|
||||
nortti = <toolset>gcc:<cxxflags>-fno-rtti <toolset>clang:<cxxflags>-fno-rtti <toolset>msvc:<cxxflags>/GR- ;
|
||||
|
||||
|
||||
# Making libraries that CANNOT work between rtti-on/rtti-off modules
|
||||
obj test_lib_nortti-obj : test_lib.cpp : <link>shared <rtti>off ;
|
||||
obj test_lib_rtti-obj : test_lib.cpp : <link>shared ;
|
||||
lib test_lib_rtti : test_lib_rtti-obj : <link>shared ;
|
||||
lib test_lib_nortti : test_lib_nortti-obj : <link>shared <rtti>off ;
|
||||
## Making libraries that CANNOT work between rtti-on/rtti-off modules
|
||||
#obj test_lib_nortti-obj : test_lib.cpp : <link>shared <rtti>off ;
|
||||
#obj test_lib_rtti-obj : test_lib.cpp : <link>shared ;
|
||||
#lib test_lib_rtti : test_lib_rtti-obj : <link>shared ;
|
||||
#lib test_lib_nortti : test_lib_nortti-obj : <link>shared <rtti>off ;
|
||||
|
||||
# Making libraries that can work between rtti-on/rtti-off modules
|
||||
obj test_lib_nortti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
|
||||
obj test_lib_rtti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
|
||||
lib test_lib_nortti_compat : test_lib_nortti_compat-obj : <link>shared $(nortti) $(compat) ;
|
||||
lib test_lib_rtti_compat : test_lib_rtti_compat-obj : <link>shared $(nortti) $(compat) ;
|
||||
## Making libraries that can work between rtti-on/rtti-off modules
|
||||
#obj test_lib_nortti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
|
||||
#obj test_lib_rtti_compat-obj : test_lib.cpp : <link>shared $(nortti) $(compat) ;
|
||||
#lib test_lib_nortti_compat : test_lib_nortti_compat-obj : <link>shared $(nortti) $(compat) ;
|
||||
#lib test_lib_rtti_compat : test_lib_rtti_compat-obj : <link>shared $(nortti) $(compat) ;
|
||||
|
||||
|
||||
test-suite type_index
|
||||
:
|
||||
[ run type_index_test.cpp $(tlib) ]
|
||||
[ run template_index_test.cpp $(tlib) ]
|
||||
[ run testing_both.cpp $(tlib) ]
|
||||
[ run testing_both_no_rtti.cpp $(tlib) : : : <rtti>off ]
|
||||
[ run testing_crossmodule.cpp test_lib_rtti $(tlib) ]
|
||||
[ run testing_crossmodule.cpp test_lib_nortti $(tlib) : : : <rtti>off : testing_crossmodule_no_rtti ]
|
||||
# [ run template_index_test.cpp $(tlib) ]
|
||||
# [ run testing_both.cpp $(tlib) ]
|
||||
# [ run testing_both_no_rtti.cpp $(tlib) : : : <rtti>off ]
|
||||
# [ run testing_crossmodule.cpp test_lib_rtti $(tlib) ]
|
||||
# [ run testing_crossmodule.cpp test_lib_nortti $(tlib) : : : <rtti>off : testing_crossmodule_no_rtti ]
|
||||
|
||||
# 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
|
||||
#[ link-fail testing_crossmodule.cpp $(tlib) test_lib_nortti : : link_fail_rtti_nortti ]
|
||||
[ run testing_crossmodule.cpp $(tlib) test_lib_rtti_compat : : : $(nortti) $(compat) : testing_crossmodule_nortti_rtti_compat ]
|
||||
[ run testing_crossmodule.cpp $(tlib) test_lib_nortti_compat : : : $(compat) : testing_crossmodule_rtti_nortti_compat ]
|
||||
|
||||
# Examples that must work even with RTTI disabled
|
||||
[ run ../examples/registry.cpp : : : <rtti>off : registry_no_rtti ]
|
||||
[ run ../examples/exact_types_match.cpp : : : <rtti>off : exact_types_match_no_rtti ]
|
||||
[ run ../examples/demangled_names.cpp : : : <rtti>off : demangled_names_no_rtti ]
|
||||
[ compile-fail ../examples/inheritance.cpp : <rtti>off : failing_inheritance_example ]
|
||||
# # 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
|
||||
# #[ link-fail testing_crossmodule.cpp $(tlib) test_lib_nortti : : link_fail_rtti_nortti ]
|
||||
# [ run testing_crossmodule.cpp $(tlib) test_lib_rtti_compat : : : $(nortti) $(compat) : testing_crossmodule_nortti_rtti_compat ]
|
||||
# [ run testing_crossmodule.cpp $(tlib) test_lib_nortti_compat : : : $(compat) : testing_crossmodule_rtti_nortti_compat ]
|
||||
#
|
||||
# # Examples that must work even with RTTI disabled
|
||||
# [ run ../examples/registry.cpp : : : <rtti>off : registry_no_rtti ]
|
||||
# [ run ../examples/exact_types_match.cpp : : : <rtti>off : exact_types_match_no_rtti ]
|
||||
# [ run ../examples/demangled_names.cpp : : : <rtti>off : demangled_names_no_rtti ]
|
||||
# [ compile-fail ../examples/inheritance.cpp : <rtti>off : failing_inheritance_example ]
|
||||
;
|
||||
|
||||
# Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite.
|
||||
for local p in [ glob ../examples/*.cpp ]
|
||||
{
|
||||
type_index += [ run $(p) ] ;
|
||||
}
|
||||
#for local p in [ glob ../examples/*.cpp ]
|
||||
#{
|
||||
# type_index += [ run $(p) ] ;
|
||||
#}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define BOOST_TEST_MODULE template_index_test_module
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <boost/type_index/template_index.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
|
@ -5,195 +5,4 @@
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_CASE(names_matches_template_id)
|
||||
{
|
||||
using namespace boost;
|
||||
BOOST_CHECK_EQUAL(template_id<int>().name_demangled(), "int");
|
||||
BOOST_CHECK_EQUAL(template_id<double>().name_demangled(), "double");
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<int>().name(), template_id<int>().name());
|
||||
BOOST_CHECK_NE(template_id<int>().name(), template_id<double>().name());
|
||||
BOOST_CHECK_NE(template_id<double>().name(), template_id<int>().name());
|
||||
BOOST_CHECK_EQUAL(template_id<double>().name(), template_id<double>().name());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(comparators_template_id)
|
||||
{
|
||||
using namespace boost;
|
||||
template_index t_int = template_id<int>();
|
||||
template_index t_double = template_id<double>();
|
||||
|
||||
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_template_id)
|
||||
{
|
||||
using namespace boost;
|
||||
std::size_t t_int1 = template_id<int>().hash_code();
|
||||
std::size_t t_double1 = template_id<double>().hash_code();
|
||||
|
||||
std::size_t t_int2 = template_id<int>().hash_code();
|
||||
std::size_t t_double2 = template_id<double>().hash_code();
|
||||
|
||||
BOOST_CHECK_EQUAL(t_int1, t_int2);
|
||||
BOOST_CHECK_NE(t_int1, t_double2);
|
||||
BOOST_CHECK_LE(t_double1, t_double2);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
static void test_with_modofiers() {
|
||||
using namespace boost;
|
||||
|
||||
template_index t1 = template_id_with_cvr<T1>();
|
||||
template_index t2 = template_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, template_id_with_cvr<T1>());
|
||||
BOOST_CHECK_EQUAL(t2, template_id_with_cvr<T2>());
|
||||
|
||||
BOOST_CHECK_EQUAL(t1.hash_code(), template_id_with_cvr<T1>().hash_code());
|
||||
BOOST_CHECK_EQUAL(t2.hash_code(), template_id_with_cvr<T2>().hash_code());
|
||||
|
||||
BOOST_CHECK_NE(t1.hash_code(), template_id_with_cvr<T2>().hash_code());
|
||||
BOOST_CHECK_NE(t2.hash_code(), template_id_with_cvr<T1>().hash_code());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_id_storing_modifiers)
|
||||
{
|
||||
test_with_modofiers<int, const int>();
|
||||
test_with_modofiers<int, const int&>();
|
||||
test_with_modofiers<int, int&>();
|
||||
test_with_modofiers<int, volatile int>();
|
||||
test_with_modofiers<int, volatile int&>();
|
||||
test_with_modofiers<int, const volatile int>();
|
||||
test_with_modofiers<int, const volatile int&>();
|
||||
|
||||
test_with_modofiers<const int, int>();
|
||||
test_with_modofiers<const int, const int&>();
|
||||
test_with_modofiers<const int, int&>();
|
||||
test_with_modofiers<const int, volatile int>();
|
||||
test_with_modofiers<const int, volatile int&>();
|
||||
test_with_modofiers<const int, const volatile int>();
|
||||
test_with_modofiers<const int, const volatile int&>();
|
||||
|
||||
test_with_modofiers<const int&, int>();
|
||||
test_with_modofiers<const int&, const int>();
|
||||
test_with_modofiers<const int&, int&>();
|
||||
test_with_modofiers<const int&, volatile int>();
|
||||
test_with_modofiers<const int&, volatile int&>();
|
||||
test_with_modofiers<const int&, const volatile int>();
|
||||
test_with_modofiers<const int&, const volatile int&>();
|
||||
|
||||
test_with_modofiers<int&, const int>();
|
||||
test_with_modofiers<int&, const int&>();
|
||||
test_with_modofiers<int&, int>();
|
||||
test_with_modofiers<int&, volatile int>();
|
||||
test_with_modofiers<int&, volatile int&>();
|
||||
test_with_modofiers<int&, const volatile int>();
|
||||
test_with_modofiers<int&, const volatile int&>();
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
test_with_modofiers<int&&, const int>();
|
||||
test_with_modofiers<int&&, const int&>();
|
||||
test_with_modofiers<int&&, const int&&>();
|
||||
test_with_modofiers<int&&, int>();
|
||||
test_with_modofiers<int&&, volatile int>();
|
||||
test_with_modofiers<int&&, volatile int&>();
|
||||
test_with_modofiers<int&&, volatile int&&>();
|
||||
test_with_modofiers<int&&, const volatile int>();
|
||||
test_with_modofiers<int&&, const volatile int&>();
|
||||
test_with_modofiers<int&&, const volatile int&&>();
|
||||
#endif
|
||||
}
|
||||
|
||||
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_CHECK_EQUAL(t2.name_demangled(), t1.name_demangled());
|
||||
}
|
||||
|
||||
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_CHECK(t1.name_demangled() == "const int" || t1.name_demangled() == "int const");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_index_stream_operator_via_lexical_cast_testing)
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
std::string s_int2 = lexical_cast<std::string>(template_id<int>());
|
||||
BOOST_CHECK_EQUAL(s_int2, "int");
|
||||
|
||||
std::string s_double2 = lexical_cast<std::string>(template_id<double>());
|
||||
BOOST_CHECK_EQUAL(s_double2, "double");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_index_stripping_cvr_test)
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const int>());
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const volatile int>());
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<const volatile int&>());
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<int&>());
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<volatile int>());
|
||||
BOOST_CHECK_EQUAL(template_id<int>(), template_id<volatile int&>());
|
||||
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const double>());
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const volatile double>());
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<const volatile double&>());
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<double&>());
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<volatile double>());
|
||||
BOOST_CHECK_EQUAL(template_id<double>(), template_id<volatile double&>());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(template_index_user_defined_class_test)
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
BOOST_CHECK_EQUAL(template_id<my_namespace1::my_class>(), template_id<my_namespace1::my_class>());
|
||||
BOOST_CHECK_EQUAL(template_id<my_namespace2::my_class>(), template_id<my_namespace2::my_class>());
|
||||
|
||||
BOOST_CHECK_NE(template_id<my_namespace1::my_class>(), template_id<my_namespace2::my_class>());
|
||||
BOOST_CHECK_NE(
|
||||
template_id<my_namespace1::my_class>().name_demangled().find("my_namespace1::my_class"),
|
||||
std::string::npos);
|
||||
}
|
||||
|
@ -8,7 +8,10 @@
|
||||
#define BOOST_TEST_MODULE type_index_test_module
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <boost/type_index/type_index.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace my_namespace1 {
|
||||
class my_class{};
|
||||
@ -19,4 +22,193 @@ namespace my_namespace2 {
|
||||
class my_class{};
|
||||
}
|
||||
|
||||
#include "type_index_tests.ipp"
|
||||
|
||||
BOOST_AUTO_TEST_CASE(names_matches_type_id)
|
||||
{
|
||||
using namespace boost::typeind;
|
||||
BOOST_CHECK_EQUAL(type_id<int>().pretty_name(), "int");
|
||||
BOOST_CHECK_EQUAL(type_id<double>().pretty_name(), "double");
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<int>().name(), type_id<int>().name());
|
||||
BOOST_CHECK_NE(type_id<int>().name(), type_id<double>().name());
|
||||
BOOST_CHECK_NE(type_id<double>().name(), type_id<int>().name());
|
||||
BOOST_CHECK_EQUAL(type_id<double>().name(), type_id<double>().name());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(comparators_type_id)
|
||||
{
|
||||
using namespace boost::typeind;
|
||||
type_index t_int = type_id<int>();
|
||||
type_index t_double = type_id<double>();
|
||||
|
||||
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::typeind;
|
||||
std::size_t t_int1 = type_id<int>().hash_code();
|
||||
std::size_t t_double1 = type_id<double>().hash_code();
|
||||
|
||||
std::size_t t_int2 = type_id<int>().hash_code();
|
||||
std::size_t t_double2 = type_id<double>().hash_code();
|
||||
|
||||
BOOST_CHECK_EQUAL(t_int1, t_int2);
|
||||
BOOST_CHECK_NE(t_int1, t_double2);
|
||||
BOOST_CHECK_LE(t_double1, t_double2);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
static void test_with_modofiers() {
|
||||
using namespace boost::typeind;
|
||||
|
||||
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<int, const int>();
|
||||
test_with_modofiers<int, const int&>();
|
||||
test_with_modofiers<int, int&>();
|
||||
test_with_modofiers<int, volatile int>();
|
||||
test_with_modofiers<int, volatile int&>();
|
||||
test_with_modofiers<int, const volatile int>();
|
||||
test_with_modofiers<int, const volatile int&>();
|
||||
|
||||
test_with_modofiers<const int, int>();
|
||||
test_with_modofiers<const int, const int&>();
|
||||
test_with_modofiers<const int, int&>();
|
||||
test_with_modofiers<const int, volatile int>();
|
||||
test_with_modofiers<const int, volatile int&>();
|
||||
test_with_modofiers<const int, const volatile int>();
|
||||
test_with_modofiers<const int, const volatile int&>();
|
||||
|
||||
test_with_modofiers<const int&, int>();
|
||||
test_with_modofiers<const int&, const int>();
|
||||
test_with_modofiers<const int&, int&>();
|
||||
test_with_modofiers<const int&, volatile int>();
|
||||
test_with_modofiers<const int&, volatile int&>();
|
||||
test_with_modofiers<const int&, const volatile int>();
|
||||
test_with_modofiers<const int&, const volatile int&>();
|
||||
|
||||
test_with_modofiers<int&, const int>();
|
||||
test_with_modofiers<int&, const int&>();
|
||||
test_with_modofiers<int&, int>();
|
||||
test_with_modofiers<int&, volatile int>();
|
||||
test_with_modofiers<int&, volatile int&>();
|
||||
test_with_modofiers<int&, const volatile int>();
|
||||
test_with_modofiers<int&, const volatile int&>();
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
test_with_modofiers<int&&, const int>();
|
||||
test_with_modofiers<int&&, const int&>();
|
||||
test_with_modofiers<int&&, const int&&>();
|
||||
test_with_modofiers<int&&, int>();
|
||||
test_with_modofiers<int&&, volatile int>();
|
||||
test_with_modofiers<int&&, volatile int&>();
|
||||
test_with_modofiers<int&&, volatile int&&>();
|
||||
test_with_modofiers<int&&, const volatile int>();
|
||||
test_with_modofiers<int&&, const volatile int&>();
|
||||
test_with_modofiers<int&&, const volatile int&&>();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void test_storing_nonstoring_modifiers_templ() {
|
||||
using namespace boost::typeind;
|
||||
|
||||
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_CHECK_EQUAL(t2.pretty_name(), t1.pretty_name());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_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::typeind::type_index t1 = boost::typeind::type_id_with_cvr<const int>();
|
||||
boost::typeind::type_index t2 = boost::typeind::type_id<int>();
|
||||
BOOST_CHECK_NE(t2, t1);
|
||||
BOOST_CHECK(t1.pretty_name() == "const int" || t1.pretty_name() == "int const");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_index_stream_operator_via_lexical_cast_testing)
|
||||
{
|
||||
using namespace boost::typeind;
|
||||
|
||||
std::string s_int2 = boost::lexical_cast<std::string>(type_id<int>());
|
||||
BOOST_CHECK_EQUAL(s_int2, "int");
|
||||
|
||||
std::string s_double2 = boost::lexical_cast<std::string>(type_id<double>());
|
||||
BOOST_CHECK_EQUAL(s_double2, "double");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_index_stripping_cvr_test)
|
||||
{
|
||||
using namespace boost::typeind;
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const int>());
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const volatile int>());
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<const volatile int&>());
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<int&>());
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<volatile int>());
|
||||
BOOST_CHECK_EQUAL(type_id<int>(), type_id<volatile int&>());
|
||||
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const double>());
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const volatile double>());
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<const volatile double&>());
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<double&>());
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<volatile double>());
|
||||
BOOST_CHECK_EQUAL(type_id<double>(), type_id<volatile double&>());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(type_index_user_defined_class_test)
|
||||
{
|
||||
using namespace boost::typeind;
|
||||
|
||||
BOOST_CHECK_EQUAL(type_id<my_namespace1::my_class>(), type_id<my_namespace1::my_class>());
|
||||
BOOST_CHECK_EQUAL(type_id<my_namespace2::my_class>(), type_id<my_namespace2::my_class>());
|
||||
|
||||
BOOST_CHECK_NE(type_id<my_namespace1::my_class>(), type_id<my_namespace2::my_class>());
|
||||
BOOST_CHECK_NE(
|
||||
type_id<my_namespace1::my_class>().pretty_name().find("my_namespace1::my_class"),
|
||||
std::string::npos);
|
||||
}
|
||||
|
72
todos.txt
Normal file
72
todos.txt
Normal file
@ -0,0 +1,72 @@
|
||||
Sketch of TypeIndex v3 library interface:
|
||||
|
||||
// boost/type_index/type_index_base.hpp
|
||||
namespace boost{ namespace typeind {
|
||||
|
||||
namespce detail {
|
||||
|
||||
template <class TypeInfo>
|
||||
class type_index_base
|
||||
const TypeInfo* data_;
|
||||
|
||||
public:
|
||||
type_index_base(const TypeInfo&);
|
||||
|
||||
const char* raw_name() const noexcept;
|
||||
const char* name() const noexcept;
|
||||
const char* pretty_name() const;
|
||||
std::size_t hash_value() const noexcept;
|
||||
const TypeInfo& type_info() const noexcept;
|
||||
|
||||
// comparison operators
|
||||
};
|
||||
|
||||
}}} // namespace boost::typeind::detail
|
||||
|
||||
|
||||
// boost/type_index.hpp
|
||||
/// Contians core functionality for everyday use
|
||||
namespace boost{ namespace typeind {
|
||||
|
||||
// MSVC is capable of calling typeid(T) even when RTTI is off
|
||||
#if (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
|
||||
typedef std::type_info type_info; // RTTI on/off dependent
|
||||
typedef type_index_base<type_info> type_index;
|
||||
#else
|
||||
#else
|
||||
#endif
|
||||
|
||||
inline bool is_equal(const type_info&, const type_info&) noexcept;
|
||||
|
||||
template <class T>
|
||||
type_index type_id() noexcept;
|
||||
|
||||
template <class T>
|
||||
type_index type_id_with_cvr() noexcept;
|
||||
|
||||
template <class T>
|
||||
type_index type_id_runtime(const T&) noexcept;
|
||||
|
||||
template <class T>
|
||||
type_index type_id_runtime(const T*) noexcept;
|
||||
|
||||
/* macro that must be put inside class to allow `type_id_runtime` calls with RTTI disabled */
|
||||
/// Empty if RTTI is on
|
||||
#define BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
|
||||
}} // namespace boost::typeind
|
||||
|
||||
// boost/type_index/ctti.hpp
|
||||
/// Contians minimal functionality required by boost/type_index.hpp with RTTI off
|
||||
namespace boost { namespace detail {
|
||||
template <class T>
|
||||
struct ctti {
|
||||
/// Returns raw name. Must be as short, as possible, to avoid code bloat
|
||||
static const char* n() noexcept;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
namespace typeind {
|
||||
// Will be used instead of std::type_info when RTTI is off
|
||||
class ctti_data; // POD. Interface is close to std::type_info
|
||||
}}
|
Reference in New Issue
Block a user