forked from boostorg/type_index
Docs improved
This commit is contained in:
+65
-39
@@ -19,6 +19,7 @@ Sometimes getting and storing information about a type at runtime is required. F
|
||||
* 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
|
||||
* no way to easily make your own type info class
|
||||
|
||||
Boost.TypeIndex library was designed to work around all those issues.
|
||||
|
||||
@@ -30,12 +31,17 @@ Boost.TypeIndex library was designed to work around all those issues.
|
||||
|
||||
[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::typeind::type_info` is a drop-in replacement for `std::type_info` and `boost::typeind::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
|
||||
`type_index` provides the full set of comparison operators, hashing functions and ostream
|
||||
operators, so it can be used with any container class.
|
||||
|
||||
Through all the examples, we'll assume that the following namespace alias is in effect:
|
||||
``using bti = boost::typeind;``
|
||||
|
||||
[section How to use]
|
||||
|
||||
To start using Boost.TypeIndex:
|
||||
|
||||
[table:porting
|
||||
@@ -48,18 +54,16 @@ To start using Boost.TypeIndex:
|
||||
``]]
|
||||
|
||||
[[``
|
||||
std::type_info
|
||||
std::type_index
|
||||
``][``
|
||||
boost::type_index
|
||||
bti::type_index
|
||||
``]]
|
||||
|
||||
[[``
|
||||
std::type_info&
|
||||
const std::type_info&
|
||||
``][``
|
||||
boost::type_index&
|
||||
const boost::type_index&
|
||||
const bti::type_info& // when reference to `std::type_info` is required
|
||||
bti::type_index // other cases
|
||||
``]]
|
||||
|
||||
[[``
|
||||
@@ -68,13 +72,19 @@ To start using Boost.TypeIndex:
|
||||
typeid(T).name() // not human readable
|
||||
typeid(variable)
|
||||
``][``
|
||||
boost::type_id<T>()
|
||||
boost::type_id_with_cvr<T>()
|
||||
boost::type_id<T>().pretty_name() // human readable
|
||||
boost::type_id_runtime(variable)
|
||||
bti::type_id<T>()
|
||||
bti::type_id_with_cvr<T>()
|
||||
bti::type_id<T>().pretty_name() // human readable
|
||||
bti::type_id_runtime(variable)
|
||||
``]]
|
||||
]
|
||||
|
||||
If you are using `type_id_runtime()` methods and RTTI is disabled, make sure that classes that are
|
||||
passed to `type_id_runtime()` are marked with `BOOST_TYPE_INDEX_REGISTER_CLASS` macro.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Example with Boost.Any]
|
||||
|
||||
Here is how TypeIndex could be used in `boost/any.hpp`:
|
||||
[table:any
|
||||
@@ -87,14 +97,18 @@ Here is how TypeIndex could be used in `boost/any.hpp`:
|
||||
return typeid(ValueType);
|
||||
}
|
||||
``] [``
|
||||
virtual const boost::type_info & type() const BOOST_NOEXCEPT
|
||||
virtual const bti::type_info & type() const BOOST_NOEXCEPT
|
||||
{
|
||||
// now works even with RTTI disabled
|
||||
return boost::type_id<ValueType>()->type_info();
|
||||
return bti::type_id<ValueType>()->type_info();
|
||||
}
|
||||
``]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Example with Boost.Variant]
|
||||
|
||||
Here is how TypeIndex could be used in `boost/variant/variant.hpp`:
|
||||
[table:variant
|
||||
@@ -126,14 +140,14 @@ public: // visitor interfaces
|
||||
#endif // BOOST_NO_TYPEID
|
||||
``][``
|
||||
class reflect
|
||||
: public static_visitor<const boost::type_info&>
|
||||
: public static_visitor<const bti::type_info&>
|
||||
{
|
||||
public: // visitor interfaces
|
||||
|
||||
template <typename T>
|
||||
const boost::type_info& operator()(const T&) const BOOST_NOEXCEPT
|
||||
const bti::type_info& operator()(const T&) const BOOST_NOEXCEPT
|
||||
{
|
||||
return boost::type_id<T>()->type_info();
|
||||
return bti::type_id<T>()->type_info();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -147,7 +161,7 @@ public: // visitor interfaces
|
||||
}
|
||||
#endif
|
||||
``] [``
|
||||
const boost::type_info& type() const
|
||||
const bti::type_info& type() const
|
||||
{
|
||||
detail::variant::reflect visitor;
|
||||
return this->apply_visitor(visitor);
|
||||
@@ -155,8 +169,20 @@ public: // visitor interfaces
|
||||
``]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[endsect]
|
||||
|
||||
[section How it works]
|
||||
`type_index` is just a typedef for `stl_type_index` or `ctti_type_index`.
|
||||
|
||||
Depending on the `typeid()` availability TypeIndex library will choose an optimal class for
|
||||
`type_index`. In cases when at least basic support for `typeid()` is available `boost::typeind::stl_type_index`
|
||||
will be used.
|
||||
|
||||
`BOOST_TYPE_INDEX_REGISTER_CLASS` macro is a helper macro that places some virtual helper functions or
|
||||
expands to nothing.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Examples]
|
||||
|
||||
@@ -178,11 +204,11 @@ public: // visitor interfaces
|
||||
|
||||
[section Space and Performance]
|
||||
|
||||
* `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`.
|
||||
* `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 when possible.
|
||||
* `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 pretty_name()` usually require dynamic memory allocation and some computations, so they are not recommended for usage in performance critical sections.
|
||||
|
||||
[endsect]
|
||||
@@ -191,15 +217,15 @@ so prefer using `stl_type_info` type.
|
||||
|
||||
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.
|
||||
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:
|
||||
While using RTTI, you'll get the following (more compact) string in binary file:
|
||||
|
||||
```
|
||||
i
|
||||
@@ -210,8 +236,8 @@ i
|
||||
|
||||
[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`,
|
||||
TypeIndex has been tested and successfully work on MSVC2010, GCC-4.6, 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*
|
||||
@@ -221,14 +247,14 @@ function signature, including template parameters
|
||||
# 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.
|
||||
# (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`,
|
||||
With `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` set to `0`,
|
||||
`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`
|
||||
@@ -239,17 +265,17 @@ and `BOOST_TYPE_INDEX_CTTI_END_SKIP` to `sizeof(">::n(void)") - 1`.
|
||||
[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`
|
||||
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::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 ]
|
||||
|
||||
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
|
||||
`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
|
||||
@@ -263,7 +289,7 @@ Such differences are usually not detected by linker and lead to errors at runtim
|
||||
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]
|
||||
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
#include <iostream>
|
||||
using bti = boost::typeind;
|
||||
|
||||
template <class T>
|
||||
void foo(T) {
|
||||
std::cout << "\n Short name: " << boost::typeind::type_id<T>().raw_name();
|
||||
std::cout << "\n Readable name: " << boost::typeind::type_id<T>().pretty_name();
|
||||
std::cout << "\n Short name: " << bti::type_id<T>().raw_name();
|
||||
std::cout << "\n Readable name: " << bti::type_id<T>().pretty_name();
|
||||
}
|
||||
|
||||
struct user_defined_type{};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
//[type_index_exact_type_match_example
|
||||
/*`
|
||||
The following example shows that `boost::type_index` (and `boost::type_info`) is able to store the exact type,
|
||||
The following example shows that `type_index` (and `type_info`) is able to store the exact type,
|
||||
without stripping const, volatile and references. Example works with and without RTTI.
|
||||
|
||||
In this example we'll create a class, that stores pointer to function and remembers the exact type of a
|
||||
@@ -18,21 +18,22 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
using bti = boost::typeind;
|
||||
|
||||
class type_erased_unary_function {
|
||||
void* function_ptr_;
|
||||
boost::typeind::type_index exact_param_t_;
|
||||
void* function_ptr_;
|
||||
bti::type_index exact_param_t_;
|
||||
|
||||
public:
|
||||
template <class ParamT>
|
||||
type_erased_unary_function(void(*ptr)(ParamT))
|
||||
: function_ptr_(reinterpret_cast<void*>(ptr)) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT`
|
||||
, exact_param_t_(boost::typeind::type_id_with_cvr<ParamT>())
|
||||
, exact_param_t_(bti::type_id_with_cvr<ParamT>())
|
||||
{}
|
||||
|
||||
template <class ParamT>
|
||||
void call(ParamT v) {
|
||||
if (exact_param_t_ != boost::typeind::type_id_with_cvr<ParamT>()) {
|
||||
if (exact_param_t_ != bti::type_id_with_cvr<ParamT>()) {
|
||||
throw std::runtime_error("Incorrect `ParamT`");
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
//[type_index_derived_example
|
||||
/*`
|
||||
The following example shows that `boost::type_info` is able to store the real type, successfully getting through
|
||||
The following example shows that `type_info` is able to store the real type, successfully getting through
|
||||
all the inheritances.
|
||||
|
||||
Example works with and without RTTI."
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <boost/type_index.hpp>
|
||||
#include <iostream>
|
||||
using bti = boost::typeind;
|
||||
|
||||
struct A {
|
||||
BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
@@ -23,7 +24,7 @@ struct B: public A { BOOST_TYPE_INDEX_REGISTER_CLASS };
|
||||
struct C: public B { BOOST_TYPE_INDEX_REGISTER_CLASS };
|
||||
|
||||
void print_real_type(const A& a) {
|
||||
std::cout << boost::typeind::type_id_runtime(a).pretty_name() << '\n';
|
||||
std::cout << bti::type_id_runtime(a).pretty_name() << '\n';
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -14,24 +14,25 @@
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <cassert>
|
||||
using bti = boost::typeind;
|
||||
|
||||
int main() {
|
||||
boost::unordered_set<boost::typeind::type_index> types;
|
||||
boost::unordered_set<bti::type_index> types;
|
||||
|
||||
// Storing some `boost::type_info`s
|
||||
types.insert(boost::typeind::type_id<int>());
|
||||
types.insert(boost::typeind::type_id<float>());
|
||||
types.insert(bti::type_id<int>());
|
||||
types.insert(bti::type_id<float>());
|
||||
|
||||
// `types` variable contains two `boost::type_index`es:
|
||||
assert(types.size() == 2);
|
||||
|
||||
// Const, volatile and reference will be striped from the type:
|
||||
bool is_inserted = types.insert(boost::typeind::type_id<const int>()).second;
|
||||
bool is_inserted = types.insert(bti::type_id<const int>()).second;
|
||||
assert(!is_inserted);
|
||||
assert(types.erase(boost::typeind::type_id<float&>()) == 1);
|
||||
assert(types.erase(bti::type_id<float&>()) == 1);
|
||||
|
||||
// We have erased the `float` type, only `int` remains
|
||||
assert(*types.begin() == boost::typeind::type_id<int>());
|
||||
assert(*types.begin() == bti::type_id<int>());
|
||||
}
|
||||
|
||||
//] [/type_index_registry_example]
|
||||
|
||||
Reference in New Issue
Block a user