mirror of
https://github.com/boostorg/type_index.git
synced 2025-08-03 22:24:27 +02:00
New project structure to satisfy Modular Boost requirements.
This commit is contained in:
37
doc/Jamfile.v2
Normal file
37
doc/Jamfile.v2
Normal file
@@ -0,0 +1,37 @@
|
||||
# Copyright Antony Polukhin 2011-2013.
|
||||
# Use, modification, and distribution are
|
||||
# subject to 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)
|
||||
|
||||
using quickbook ;
|
||||
import boostbook : boostbook ;
|
||||
import doxygen ;
|
||||
|
||||
doxygen autodoc
|
||||
:
|
||||
[ glob ../../../boost/type_index.hpp ]
|
||||
[ glob ../../../boost/type_index/*.hpp ]
|
||||
:
|
||||
<doxygen:param>EXTRACT_ALL=NO
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
<doxygen:param>ENABLE_PREPROCESSING=YES
|
||||
<doxygen:param>EXPAND_ONLY_PREDEF=YES
|
||||
<doxygen:param>MACRO_EXPANSION=YES
|
||||
<doxygen:param>"PREDEFINED=\"stl_type_info=std::type_info\" \\
|
||||
\"BOOST_TYPE_INDEX_DOXYGEN_INVOKED\" \\
|
||||
\"detail::stl_type_info=std::type_info\""
|
||||
<xsl:param>"boost.doxygen.reftitle=Boost.TypeIndex Header Reference"
|
||||
;
|
||||
|
||||
xml type_index : type_index.qbk ;
|
||||
boostbook standalone
|
||||
:
|
||||
type_index
|
||||
:
|
||||
<xsl:param>boost.root=http://www.boost.org/doc/libs/1_53_0
|
||||
# <xsl:param>boost.root=../../../..
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
|
||||
<dependency>autodoc
|
||||
;
|
||||
|
273
doc/type_index.qbk
Normal file
273
doc/type_index.qbk
Normal file
@@ -0,0 +1,273 @@
|
||||
[library Boost.TypeIndex
|
||||
[quickbook 1.6]
|
||||
[version 2.1]
|
||||
[copyright 2012-2013 Antony Polukhin]
|
||||
[category Language Features Emulation]
|
||||
[license
|
||||
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])
|
||||
]
|
||||
]
|
||||
|
||||
[section Motivation]
|
||||
Sometimes getting and storing information about a type at runtime is required. For such cases a construction like `&typeid(T)` or C++11 class `std::type_index` is usually used. And that is the point, where problems start:
|
||||
|
||||
* `typeid(T)` and `std::type_index` require Run Time Type Info (RTTI)
|
||||
* some implementations of `typeid(T)` strip const, volatile and references from type, while others don't
|
||||
* some compilers have bugs and do not correctly compare `std::type_info` objects across shared libraries
|
||||
* only a few implementations of Standard Library currently provide `std::type_index`
|
||||
* no easy way to store type info without stripping const, volatile and references
|
||||
* no nice and portable way to get human readable type names
|
||||
|
||||
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. ]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Getting started]
|
||||
|
||||
`boost::type_info` is a drop-in replacement for `std::type_info` and `boost::type_index` is a drop-in
|
||||
replacement for `std::type_index`. Unlike Standard Library versions those classes may work without RTTI.
|
||||
|
||||
`boost::type_index` provides the full set of comparison operators, hashing functions and ostream
|
||||
operators, so it can be used with any container class.
|
||||
|
||||
To start using Boost.TypeIndex:
|
||||
|
||||
[table:porting
|
||||
[[Replace this:][With the following:]]
|
||||
[[``
|
||||
#include <typeinfo>
|
||||
#include <typeindex>
|
||||
``][``
|
||||
#include <boost/type_index/type_info.hpp>
|
||||
#include <boost/type_index/type_index.hpp>
|
||||
`` or ``
|
||||
#include <boost/type_index.hpp>
|
||||
``]]
|
||||
|
||||
[[``
|
||||
std::type_info
|
||||
std::type_index
|
||||
``][``
|
||||
boost::type_info
|
||||
boost::type_index
|
||||
``]]
|
||||
|
||||
[[``
|
||||
typeid(T)
|
||||
typeid(please_save_modifiers<T>)
|
||||
typeid(T).name() // not human readable
|
||||
typeid(variable)
|
||||
``][``
|
||||
boost::type_id<T>()
|
||||
boost::type_id_with_cvr<T>()
|
||||
boost::type_id<T>().name_demangled() // human readable
|
||||
boost::type_id_rtti_only(variable)
|
||||
``]]
|
||||
]
|
||||
|
||||
|
||||
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>``]]
|
||||
[[``
|
||||
virtual const std::type_info & type() const BOOST_NOEXCEPT
|
||||
{
|
||||
// requires RTTI
|
||||
return typeid(ValueType);
|
||||
}
|
||||
``] [``
|
||||
virtual const boost::type_info & type() const BOOST_NOEXCEPT
|
||||
{
|
||||
// now works even with RTTI disabled
|
||||
return boost::type_id<ValueType>();
|
||||
}
|
||||
``]]
|
||||
]
|
||||
|
||||
|
||||
Here is how TypeIndex could be used in `boost/variant/variant.hpp`:
|
||||
[table:variant
|
||||
[[Before] [With TypeIndex]]
|
||||
|
||||
[[``
|
||||
#if !defined(BOOST_NO_TYPEID)
|
||||
#include <typeinfo> // for typeid, std::type_info
|
||||
#endif // BOOST_NO_TYPEID
|
||||
``][``
|
||||
#include <boost/type_info/type_info.hpp>
|
||||
``]]
|
||||
[[``
|
||||
#if !defined(BOOST_NO_TYPEID)
|
||||
|
||||
class reflect
|
||||
: public static_visitor<const std::type_info&>
|
||||
{
|
||||
public: // visitor interfaces
|
||||
|
||||
template <typename T>
|
||||
const std::type_info& operator()(const T&) const BOOST_NOEXCEPT
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_TYPEID
|
||||
``][``
|
||||
class reflect
|
||||
: public static_visitor<const boost::type_info&>
|
||||
{
|
||||
public: // visitor interfaces
|
||||
|
||||
template <typename T>
|
||||
const boost::type_info& operator()(const T&) const BOOST_NOEXCEPT
|
||||
{
|
||||
return boost::type_id<T>();
|
||||
}
|
||||
|
||||
};
|
||||
``]]
|
||||
[[``
|
||||
#if !defined(BOOST_NO_TYPEID)
|
||||
const std::type_info& type() const
|
||||
{
|
||||
detail::variant::reflect visitor;
|
||||
return this->apply_visitor(visitor);
|
||||
}
|
||||
#endif
|
||||
``] [``
|
||||
const boost::type_info& type() const
|
||||
{
|
||||
detail::variant::reflect visitor;
|
||||
return this->apply_visitor(visitor);
|
||||
}
|
||||
``]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Examples]
|
||||
|
||||
[import ../examples/demangled_names.cpp]
|
||||
[section Getting human readable and mangled type names] [type_index_names_example] [endsect]
|
||||
|
||||
[import ../examples/registry.cpp]
|
||||
[section Storing information about a type in container ] [type_index_registry_example] [endsect]
|
||||
|
||||
[import ../examples/inheritance.cpp]
|
||||
[section Getting through the inheritance to receive a real type name ] [type_index_derived_example] [endsect]
|
||||
|
||||
[import ../examples/exact_types_match.cpp]
|
||||
[section Exact type match: storing type with const, volatile and reference ] [type_index_exact_type_match_example] [endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[xinclude autodoc.xml]
|
||||
|
||||
[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.
|
||||
* 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.
|
||||
|
||||
[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.
|
||||
|
||||
This leads to big strings in binary file:
|
||||
```
|
||||
static const char* boost::detail::ctti<T>::n() [with T = int]
|
||||
static const char* boost::detail::ctti<T>::n() [with T = user_defined_type]
|
||||
```
|
||||
While using RTTI, you'll get the following (more compact) string in binary file:
|
||||
|
||||
```
|
||||
i
|
||||
17user_defined_type
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Compiler support]
|
||||
|
||||
TypeIndex has been tested and successfully work on MSVC2010, GCC-4.5, Clang-2.9. If your compiler is not
|
||||
in a list of tested compilers, you must correctly define `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE`,
|
||||
`BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` macroses:
|
||||
|
||||
# define `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE` to a compiler specific macro, that outputs the *whole*
|
||||
function signature, including template parameters
|
||||
# define `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` to `0`
|
||||
# get the output of `boost::template_id<int>().name()`
|
||||
# set `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` equal to characters count before last occurrence of `int` in output
|
||||
# set `BOOST_TYPE_INDEX_CTTI_END_SKIP` equal to characters count after last occurrence of `int` in output
|
||||
# check that `boost::template_id<int>().name_demangled()` returns "int"
|
||||
# (optional, but highly recomended) [@http://www.boost.org/support/bugs.html create ticket] with
|
||||
feature request to add your compiler to supported compilers list. Include
|
||||
`BOOST_TYPE_INDEX_FUNCTION_SIGNATURE`, `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and
|
||||
`BOOST_TYPE_INDEX_CTTI_END_SKIP` values.
|
||||
|
||||
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`
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Mixing sources with RTTI on and RTTI off]
|
||||
|
||||
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.
|
||||
|
||||
[note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro defined ]
|
||||
|
||||
You must know that linking RTTI on and RTTI off binaries may succeed even without defining the
|
||||
`BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro, but that does not mean that you'll get a
|
||||
working binary. Such actions may break the One Definition Rule. Take a look at the table below,
|
||||
that shows how the `boost::type_index get_integer();` function will look like with different
|
||||
RTTI flags:
|
||||
|
||||
[table:diffs
|
||||
[[RTTI on] [RTTI off]]
|
||||
[[`boost::type_index get_integer();`] [`boost::template_index get_integer();`]]
|
||||
]
|
||||
|
||||
Such differences are usually not detected by linker and lead to errors at runtime.
|
||||
|
||||
[warning
|
||||
Even with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` defined there is no guarantee
|
||||
that everything will be OK. Libraries that use their own workarounds for disabled RTTI
|
||||
may fail to link or to work correctly.
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Acknowledgements]
|
||||
|
||||
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.
|
||||
* 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.
|
||||
|
||||
[endsect]
|
Reference in New Issue
Block a user