Documented some of the classes and features

This commit is contained in:
Antony Polukhin
2014-02-07 17:10:36 +04:00
parent beaa53f460
commit 2ef8924510
5 changed files with 194 additions and 65 deletions

View File

@ -1,6 +1,6 @@
[library Boost.TypeIndex
[quickbook 1.6]
[version 2.1]
[version 3.0]
[copyright 2012-2013 Antony Polukhin]
[category Language Features Emulation]
[license
@ -24,7 +24,7 @@ Boost.TypeIndex library was designed to work around all those issues.
[note `T` means type here. Think of it as of `T` in `template <class T>` ]
[warning During the Boost review was decided, that it is better to use interface close to v1.0 of this library. Version 3.0 will attempt to fix all the issues found during the review. ]
[warning Version 3.0 of this library is waitning for Boost mini-review. ]
[endsect]
@ -44,9 +44,6 @@ To start using Boost.TypeIndex:
#include <typeinfo>
#include <typeindex>
``][``
#include <boost/type_index/type_info.hpp>
#include <boost/type_index/type_index.hpp>
`` or ``
#include <boost/type_index.hpp>
``]]
@ -54,10 +51,17 @@ To start using Boost.TypeIndex:
std::type_info
std::type_index
``][``
boost::type_info
boost::type_index
``]]
[[``
std::type_info&
const std::type_info&
``][``
boost::type_index&
const boost::type_index&
``]]
[[``
typeid(T)
typeid(please_save_modifiers<T>)
@ -66,8 +70,8 @@ To start using Boost.TypeIndex:
``][``
boost::type_id<T>()
boost::type_id_with_cvr<T>()
boost::type_id<T>().name_demangled() // human readable
boost::type_id_rtti_only(variable)
boost::type_id<T>().pretty_name() // human readable
boost::type_id_runtime(variable)
``]]
]
@ -75,7 +79,7 @@ To start using Boost.TypeIndex:
Here is how TypeIndex could be used in `boost/any.hpp`:
[table:any
[[Before] [With TypeIndex]]
[[``#include <typeinfo>``][``#include <boost/type_index/type_info.hpp>``]]
[[``#include <typeinfo>``][``#include <boost/type_index.hpp>``]]
[[``
virtual const std::type_info & type() const BOOST_NOEXCEPT
{
@ -86,7 +90,7 @@ Here is how TypeIndex could be used in `boost/any.hpp`:
virtual const boost::type_info & type() const BOOST_NOEXCEPT
{
// now works even with RTTI disabled
return boost::type_id<ValueType>();
return boost::type_id<ValueType>()->type_info();
}
``]]
]
@ -101,7 +105,7 @@ Here is how TypeIndex could be used in `boost/variant/variant.hpp`:
#include <typeinfo> // for typeid, std::type_info
#endif // BOOST_NO_TYPEID
``][``
#include <boost/type_info/type_info.hpp>
#include <boost/type_index.hpp>
``]]
[[``
#if !defined(BOOST_NO_TYPEID)
@ -129,7 +133,7 @@ public: // visitor interfaces
template <typename T>
const boost::type_info& operator()(const T&) const BOOST_NOEXCEPT
{
return boost::type_id<T>();
return boost::type_id<T>()->type_info();
}
};
@ -174,20 +178,21 @@ public: // visitor interfaces
[section Space and Performance]
* `template_info` uses macro for getting full text representation of function name which could lead to code bloat,
so prefer using `type_info` type.
* `type_index` and `template_index` classes hold a single pointer, so they are easy and fast to copy.
* Calls to `const char* name()` do not require dynamic memory allocation and usually just return a pointer to an array of chars in a read-only section of the binary image.
* `ctti_type_info` uses macro for getting full text representation of function name which could lead to code bloat,
so prefer using `stl_type_info` type.
* `type_index` class hold a single pointer, so it is easy and fast to copy.
* Calls to `const char* raw_name()` do not require dynamic memory allocation and usually just return a pointer to an array of chars in a read-only section of the binary image.
* Comparison operators are optimized as much as possible, and will at worst execute a single `std::strcmp`.
* Calls to `std::string name_demangled()` usually require dynamic memory allocation and some computations, so they are not recommended for usage in performance critical sections.
* Calls to `std::string pretty_name()` usually require dynamic memory allocation and some computations, so they are not recommended for usage in performance critical sections.
[endsect]
[section Code bloat]
Without RTTI TypeIndex library will switch from using `boost::type_info` class to `boost::template_info`.
`boost::template_info` uses macro for getting full text representation of function name for each type that
is passed to `type_id()` and `type_id_with_cvr()` functions.
Without RTTI TypeIndex library will switch from using `boost::typeind::stl_type_info` class to
`boost::typeind::ctti_type_info`. `boost::typeind::ctti_type_info` uses macro for getting full
text representation of function name for each type that is passed to `type_id()` and
`type_id_with_cvr()` functions.
This leads to big strings in binary file:
```
@ -224,10 +229,10 @@ feature request to add your compiler to supported compilers list. Include
Consider the following example:
With `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` set to `0`,
`boost::template_id<int>().name()` returns "const char *__cdecl boost::detail::ctti<int>::n(void)".
Then you shall set `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` to
`sizeof("const char *__cdecl boost::detail::ctti<") - 1` and `BOOST_TYPE_INDEX_CTTI_END_SKIP`
to `sizeof(">::n(void)") - 1`
`boost::typeind::ctti_type_info::construct<int>().raw_name()` returns
"const char *__cdecl boost::detail::ctti<int>::n(void)". Then you shall set
`BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` to `sizeof("const char *__cdecl boost::detail::ctti<") - 1`
and `BOOST_TYPE_INDEX_CTTI_END_SKIP` to `sizeof(">::n(void)") - 1`.
[endsect]
@ -236,8 +241,8 @@ to `sizeof(">::n(void)") - 1`
Linking a binary from source files that were compiled with different RTTI flags is not a very good
idea and may lead to a lot of surprises. However if there is a very strong need, TypeIndex library
provides a solution for mixing sources: just define `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY`
macro. This would lead to usage of `boost::template_index` instead of `boost::type_index` class
and `boost::template_info` instead of `boost::type_info` class.
macro. This would lead to usage of `boost::typeind::ctti_type_info` instead of
`boost::typeind::stl_type_info` class.
[note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro defined ]
@ -249,7 +254,7 @@ RTTI flags:
[table:diffs
[[RTTI on] [RTTI off]]
[[`boost::type_index get_integer();`] [`boost::template_index get_integer();`]]
[[`boost::typeind::stl_type_info get_integer();`] [`boost::typeind::ctti_type_info get_integer();`]]
]
Such differences are usually not detected by linker and lead to errors at runtime.
@ -266,8 +271,8 @@ Such differences are usually not detected by linker and lead to errors at runtim
In order of helping and advising:
* Peter Dimov for writing source codes in late 2007, ideas from which were refined and put into this library.
* Peter Dimov for writing source codes in late 2007, that gave me an idea of how to emulate RTTI.
* Agustín Bergé K-ballo for helping with docs and fixing a lot of typos.
* Niall Douglas for generating a lot of great ideas and reviewing the sources.
* Niall Douglas for generating a lot of great ideas, reviewing the sources and being the review manager for the library.
[endsect]

View File

@ -9,16 +9,10 @@
#define BOOST_TYPE_INDEX_HPP
/// \file boost/type_index.hpp
/// \brief Includes all the headers of the Boost.TypeIndex library.
/// \brief Includes minimal set of headers required to use the Boost.TypeIndex library.
///
/// By inclusion of this file all classes (boost::type_info + boost::type_index if RTTI is on
/// and boost::template_info + boost::template_index) will be available.
///
/// Consider including <boost/type_index/type_index.hpp> if you do not want to include
/// boost::template_info and boost::template_index class while RTTI is available.
///
/// Consider including <boost/type_index/type_info.hpp> if you need only boost::type_info class
/// and boost::type_id* functions.
/// By inclusion of this file most optimal type index classes will be included and used
/// as a boost::typeind::type_index and boost::typeind::type_info.
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
@ -27,8 +21,8 @@
#include <boost/config.hpp>
#if defined(BOOST_TYPE_INDEX_USER_TYPEINFO) && defined(BOOST_TYPE_INDEX_USER_TYPEINFO_NAME)
# include BOOST_TYPE_INDEX_USER_TYPEINFO
#if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX) && defined(BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME)
# include BOOST_TYPE_INDEX_USER_TYPEINDEX
#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
# include <boost/type_index/stl_type_index.hpp>
#else
@ -37,44 +31,134 @@
namespace boost { namespace typeind {
#if defined(BOOST_TYPE_INDEX_USER_TYPEINFO) && defined(BOOST_TYPE_INDEX_USER_TYPEINFO_NAME)
typedef BOOST_TYPE_INDEX_USER_TYPEINFO_NAME type_index;
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// Depending on a compiler flags, optimal implementation of type_index will be used
/// as a default boost::typeind::type_index.
///
/// Could be a boost::typeind::stl_type_index, boost::typeind::ctti_type_index or
/// user defined type_index class.
typedef platform-specific type_index;
#elif defined(BOOST_TYPE_INDEX_USER_TYPEINDEX) && defined(BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME)
typedef BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME type_index;
#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
typedef boost::typeind::stl_type_index type_index;
#else
typedef boost::typeind::ctti_type_index type_index;
#endif
/// Depending on a compiler flags, optimal implementation of type_info will be used
/// as a default boost::typeind::type_info.
///
/// Could be a std::type_info, boost::typeind::detail::ctti_data or
/// some user defined class.
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;
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// Function to get boost::type_index for a type T.
/// Strips const, volatile and & modifiers from T.
/// \def BOOST_TYPE_INDEX_USER_TYPEINFO
/// BOOST_TYPE_INDEX_USER_TYPEINFO can be defined to the path to header file
/// with user provided implementation of type_index.
///
/// BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME must be also defined!
#define BOOST_TYPE_INDEX_USER_TYPEINDEX <full/absolute/path/to/header/with/type_index>
/// \def BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME
/// BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME can be defined to the fullty
/// qualified name of the user's type_index implementation.
///
/// BOOST_TYPE_INDEX_USER_TYPEINDEX must be also defined!
#define BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME my_namespace::my_type_index
#endif // defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// Function to get boost::type_index for a type T.
/// Removes const, volatile && and & modifiers from T.
///
/// \b Example:
/// \code
/// type_index ti = type_id<int&>();
/// std::cout << ti.pretty_name(); // Outputs 'int'
/// \endcode
///
/// \throw Nothing.
/// \return boost::typeind::type_index with information about the specified type 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.
/// Function for constructing boost::type_index instance for type T.
/// Does not remove 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>()`.
///
/// \b Example:
/// \code
/// type_index ti = type_id_with_cvr<int&>();
/// std::cout << ti.pretty_name(); // Outputs 'int&'
/// \endcode
///
/// \throw Nothing.
/// \return boost::typeind::type_index with information about the specified type 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.
///
/// Retunrs runtime information about specified type.
///
/// \b Requirements: RTTI available or specially designed user type_info class must be provided
/// via BOOST_TYPE_INDEX_USER_TYPEINDEX and BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME macro.
///
/// \b Example:
/// \code
/// struct Base { virtual ~Base(){} };
/// struct Derived: public Base {};
/// ...
/// Derived d;
/// Base& b = d;
/// type_index ti = type_id_runtime(b);
/// std::cout << ti.pretty_name(); // Outputs 'Derived'
/// \endcode
///
/// \param runtime_val Varaible which runtime type must be returned.
/// \throw Nothing.
/// \return boost::typeind::type_index with information about the specified variable.
template <class T>
inline type_index type_id_runtime(const 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.
/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
///
/// Retunrs runtime information about specified type.
///
/// \b Requirements: RTTI available or specially designed user type_info class must be provided
/// via BOOST_TYPE_INDEX_USER_TYPEINDEX and BOOST_TYPE_INDEX_USER_TYPEINDEX_NAME macro.
///
/// \b Example:
/// \code
/// struct Base { virtual ~Base(){} };
/// struct Derived: public Base {};
/// ...
/// Base* b = new Derived();
/// type_index ti = type_id_runtime(b);
/// std::cout << ti.pretty_name(); // Outputs 'Derived*'
/// \endcode
///
/// \param runtime_val Varaible which runtime type must be returned.
/// \throw Nothing.
/// \return boost::typeind::type_index with information about the specified variable.
template <class T>
inline type_index type_id_runtime(const T* runtime_val) {
return type_index::construct_runtime(runtime_val);
@ -83,5 +167,6 @@ inline type_index type_id_runtime(const T* runtime_val) {
}} // namespace boost::typeind
#endif // BOOST_TYPE_INDEX_HPP

View File

@ -14,16 +14,14 @@
# pragma once
#endif
/// \file stl_type_index.ipp
/// \brief Contains specialization of boost::type_index_base<std::type_info>.
/// \file ctti_type_index.hpp
/// \brief Contains boost::typeind::ctti_type_index class.
///
/// boost::type_index_base<std::type_info> class can be used as a drop-in replacement
/// boost::typeind::ctti_type_index 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).
/// It is used in situations when typeid() method is not available or
/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined.
#include <boost/type_index/type_index_facade.hpp>
#include <boost/type_index/detail/compile_time_type_info.hpp>
@ -50,6 +48,7 @@ inline const ctti_data& ctti_construct() BOOST_NOEXCEPT {
} // namespace detail
/// \class ctti_type_index
class ctti_type_index: public type_index_facade<ctti_type_index, detail::ctti_data> {
const detail::ctti_data* data_;

View File

@ -14,16 +14,15 @@
# pragma once
#endif
/// \file stl_type_index.ipp
/// \brief Contains specialization of boost::type_index_base<std::type_info>.
/// \file stl_type_index.hpp
/// \brief Contains boost::typeind::stl_type_index class.
///
/// boost::type_index_base<std::type_info> class can be used as a drop-in replacement
/// boost::typeind::stl_type_index 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).
/// When typeid() is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro
/// is defined boost::typeind::ctti is usually used instead of boost::typeind::stl_type_index.
#include <boost/type_index/type_index_facade.hpp>
@ -61,6 +60,7 @@
namespace boost { namespace typeind {
/// \class stl_type_index
class stl_type_index
: public type_index_facade<
stl_type_index,

View File

@ -27,12 +27,35 @@
namespace boost { namespace typeind {
/// type_index_facade - use as a public base class for defining new
/// standard-conforming iterators.
/// \class type_index_facade
///
/// This class takes care about the comparison operators, hash functions and
/// ostream operators. Use this class as a public base class for defining new
/// type_info-conforming classes.
///
/// \b Example:
/// \code
/// class stl_type_index: public type_index_facade<stl_type_index, std::type_info>
/// {
/// public:
/// typedef std::type_info type_info_t;
/// private:
/// const type_info_t* data_;
///
/// public:
/// stl_type_index(const type_info_t& data) noexcept
/// : data_(&data)
/// {}
/// // ...
/// };
/// \endcode
///
/// \tparam Derived Class derived from type_index_facade.
/// \tparam TypeInfo Class that will be used as a base type_info class.
template <class Derived, class TypeInfo>
class type_index_facade {
private:
/// @cond
Derived& derived() BOOST_NOEXCEPT {
return *static_cast<Derived*>(this);
}
@ -40,7 +63,7 @@ private:
const Derived & derived() const BOOST_NOEXCEPT {
return *static_cast<Derived const*>(this);
}
/// @endcond
public:
typedef TypeInfo type_info_t;
typedef type_index_facade<Derived, TypeInfo> this_type;
@ -74,7 +97,7 @@ public:
}
};
/// @cond
template <class Derived, class TypeInfo>
inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
return lhs.equal(rhs);
@ -171,17 +194,33 @@ inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const
// ######################### COMPARISONS with Derived END ############################ //
/// @endcond
#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
/// noexcept comparison operators for type_index_facade classes.
bool operator ? (const type_index_facade& lhs, const type_index_facade& rhs) noexcept;
/// noexcept comparison operators for type_index_facade and it's TypeInfo classes.
bool operator ? (const type_index_facade& lhs, const TypeInfo& rhs) noexcept;
/// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes.
bool operator ? (const TypeInfo& lhs, const type_index_facade& rhs) noexcept;
#endif
#ifndef BOOST_NO_IOSTREAM
#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
/// @cond
/// Ostream operator that will output demangled name
template <class Derived, class TypeInfo>
inline std::ostream& operator<<(std::ostream& ostr, const type_index_facade<Derived, TypeInfo>& ind) {
ostr << ind.pretty_name();
return ostr;
}
/// @endcond
#else
/// Ostream operator that will output demangled name
/// Ostream operator that will output demangled name.
template <class CharT, class TriatT, class Derived, class TypeInfo>
inline std::basic_ostream<CharT, TriatT>& operator<<(
std::basic_ostream<CharT, TriatT>& ostr,
@ -193,6 +232,7 @@ inline std::basic_ostream<CharT, TriatT>& operator<<(
#endif // BOOST_NO_TEMPLATED_IOSTREAMS
#endif // BOOST_NO_IOSTREAM
/// This free function is used by Boost's unordered containers.
template <class Derived, class TypeInfo>
inline std::size_t hash_value(const type_index_facade<Derived, TypeInfo>& lhs) BOOST_NOEXCEPT {
return lhs.hash_code();