1 [library Boost.TypeIndex
4 [copyright 2012-2016 Antony Polukhin]
5 [category Language Features Emulation]
7 Distributed under the Boost Software License, Version 1.0.
8 (See accompanying file LICENSE_1_0.txt or copy at
9 [@http://www.boost.org/LICENSE_1_0.txt])
14 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, which is where problems start:
16 * `typeid(T)` and `std::type_index` require Run Time Type Info (RTTI)
17 * some implementations of `typeid(T)` erroneously do not strip const, volatile and references from type
18 * some compilers have bugs and do not correctly compare `std::type_info` objects across shared libraries
19 * only a few implementations of Standard Library currently provide `std::type_index`
20 * no easy way to store type info without stripping const, volatile and references
21 * no nice and portable way to get human readable type names
22 * no way to easily make your own type info class
24 Boost.TypeIndex library was designed to work around all those issues.
26 [note `T` means type here. Think of it as of `T` in `template <class T>` ]
30 [section Getting started]
32 [classref boost::typeindex::type_info boost::typeindex::type_info] is a drop-in replacement for `std::type_info` and
33 [classref boost::typeindex::type_index boost::typeindex::type_index]
34 is a drop-in replacement for `std::type_index`. Unlike Standard Library versions those classes can work without RTTI.
36 `type_index` provides the full set of comparison operators, hashing functions and ostream
37 operators, so it can be used with any container class.
41 To start using Boost.TypeIndex:
44 [[Replace this:][With the following:][More Info]]
49 #include <boost/type_index.hpp>
51 [headerref boost/type_index.hpp more... ]
57 boost::typeindex::type_index
59 [classref boost::typeindex::type_index more... ]
64 typeid(T).name() // not human readable
67 boost::typeindex::type_id<T>()
68 boost::typeindex::type_id<T>().pretty_name() // human readable
69 boost::typeindex::type_id_runtime(variable)
71 [funcref boost::typeindex::type_id more... ]
73 [classref boost::typeindex::type_index more... ]
75 [funcref boost::typeindex::type_id_runtime more... ]
79 // attempt to save const, volatile, reference
80 typeid(please_save_modifiers<T>)
82 // cvr = const, volatile, reference
83 boost::typeindex::type_id_with_cvr<T>()
85 [funcref boost::typeindex::type_id_with_cvr more... ]
89 // when reference to `std::type_info` is required
90 const std::type_info& v1 = typeid(int);
93 const std::type_info* v2 = &typeid(int);
95 const boost::typeindex::type_info& v1
96 = boost::typeindex::type_id<int>().type_info();
98 boost::typeindex::type_index v2
99 = boost::typeindex::type_id<int>();
101 [classref boost::typeindex::type_index more... ]
103 [funcref boost::typeindex::type_id more... ]
107 If you are using [funcref boost::typeindex::type_id_runtime type_id_runtime()] methods
108 and RTTI is disabled, make sure that classes that are passed to
109 `type_id_runtime()` are marked with
110 [macroref BOOST_TYPE_INDEX_REGISTER_CLASS BOOST_TYPE_INDEX_REGISTER_CLASS] macro.
114 [section Example with Boost.Any]
116 Here is how TypeIndex could be used in `boost/any.hpp`:
118 [[Before] [With TypeIndex]]
119 [[``#include <typeinfo>``][``#include <boost/type_index.hpp>``]]
121 virtual const std::type_info & type() const BOOST_NOEXCEPT
124 return typeid(ValueType);
127 virtual const boost::typeindex::type_info & type() const BOOST_NOEXCEPT
129 // now works even with RTTI disabled
130 return boost::typeindex::type_id<ValueType>().type_info();
138 [section Example with Boost.Variant]
140 Here is how TypeIndex could be used in `boost/variant/variant.hpp`:
142 [[Before] [With TypeIndex]]
145 #if !defined(BOOST_NO_TYPEID)
146 #include <typeinfo> // for typeid, std::type_info
147 #endif // BOOST_NO_TYPEID
149 #include <boost/type_index.hpp>
152 #if !defined(BOOST_NO_TYPEID)
155 : public static_visitor<const std::type_info&>
157 public: // visitor interfaces
159 template <typename T>
160 const std::type_info& operator()(const T&) const BOOST_NOEXCEPT
167 #endif // BOOST_NO_TYPEID
170 : public static_visitor<const boost::typeindex::type_info&>
172 public: // visitor interfaces
174 template <typename T>
175 const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
177 return boost::typeindex::type_id<T>().type_info();
183 #if !defined(BOOST_NO_TYPEID)
184 const std::type_info& type() const
186 detail::variant::reflect visitor;
187 return this->apply_visitor(visitor);
191 const boost::typeindex::type_info& type() const
193 detail::variant::reflect visitor;
194 return this->apply_visitor(visitor);
202 [section:config Configuring and building the library]
204 TypeIndex is a header only library and it does not use Boost libraries that require
205 building. You just need to `#include <boost/type_index.hpp>` to start using it.
207 The library supports a number of configuration macros, defining which require full
208 rebuild of all the projects that use TypeIndex:
210 [table Configuration macros
211 [[Macro name] [Short description]]
212 [[[macroref BOOST_TYPE_INDEX_USER_TYPEINDEX]] [ Macro that allows you to use your
213 own implementation of TypeIndex instead of the default all around the projects and libraries.]]
215 [[[macroref BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY]] [ Macro that must be defined
216 if you are mixing RTTI-on and RTTI-off.]]
218 [[[macroref BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING] and
219 [macroref BOOST_TYPE_INDEX_FUNCTION_SIGNATURE]] [ Macros that allow you to specify
220 parsing options and type name generating macro for RTTI-off cases. ]]
223 You can define configuration macros in the `bjam` command line using one of the following
227 b2 variant=release define=BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY stage
231 b2 variant=release "define=BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, \\"T = \\")'" stage
234 However, it may be more convenient to define configuration macros in the "boost/config/user.hpp"
235 file in order to automatically define them both for the library and user's projects.
239 [section How it works]
240 `type_index` is just a typedef for [classref boost::typeindex::stl_type_index]
241 or [classref boost::typeindex::ctti_type_index].
243 Depending on the `typeid()` availability TypeIndex library will choose an optimal class for
244 `type_index`. In cases when at least basic support for `typeid()` is available `stl_type_index` will be used.
246 [macroref BOOST_TYPE_INDEX_REGISTER_CLASS] macro is a helper macro that places some virtual helper functions or
249 [macroref BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS] macro is a helper macro that places the same
250 helpers as BOOST_TYPE_INDEX_REGISTER_CLASS plus some additional helpers for boost::typeindex::runtime_cast
253 Issues with cross module type comparison on a bugged compilers are bypassed by directly comparing strings with type
254 (latest versions of those compilers resolved that issue using exactly the same approach).
260 [import ../examples/demangled_names.cpp]
261 [section Getting human readable and mangled type names] [type_index_names_example] [endsect]
263 [import ../examples/registry.cpp]
264 [section Storing information about a type in container ] [type_index_registry_example] [endsect]
266 [import ../examples/inheritance.cpp]
267 [section Getting through the inheritance to receive a real type name ] [type_index_derived_example] [endsect]
269 [import ../examples/runtime_cast.cpp]
270 [section Using runtime_cast where RTTI is unavailable or undesirable ] [type_index_runtime_cast_example] [endsect]
272 [import ../examples/exact_types_match.cpp]
273 [section Exact type matching: storing type with const, volatile and reference qualifiers] [type_index_exact_type_match_example] [endsect]
275 [import ../examples/table_of_names.cpp]
276 [section Table of raw_name() and pretty_name() outputs with and without RTTI ] [type_index_names_table] [endsect]
278 [import ../examples/constexpr14_namespace_check.cpp]
279 [section C++14: Checking namespace at compile time ] [type_index_constexpr14_namespace_example] [endsect]
281 [import ../examples/constexpr14_sort_check.cpp]
282 [section C++14: Checking lexigraphical order of provided types ] [type_index_constexpr14_sort_check_example] [endsect]
286 [xinclude autodoc.xml]
288 [section Making a custom type_index]
290 Sometimes there may be a need to create your own type info system. This may be useful if you wish to store some more info about types (PODness, size of a type, pointers to common functions...) or if you have an idea of a more compact types representations.
292 [import ../examples/user_defined_typeinfo.hpp]
293 [import ../examples/user_defined_typeinfo.cpp]
296 [type_index_userdefined_usertypes]
297 [type_index_userdefined_enum]
298 [type_index_my_type_index]
299 [type_index_my_type_index_usage]
302 [section Getting type infos at runtime]
303 [type_index_my_type_index_register_class]
304 [type_index_my_type_index_type_id_runtime_implmentation]
305 [type_index_my_type_index_type_id_runtime_classes]
306 [type_index_my_type_index_type_id_runtime_test]
309 [section Using new type infos all around the code]
310 [type_index_my_type_index_worldwide_macro]
311 [type_index_my_type_index_worldwide_typedefs]
312 [type_index_my_type_index_worldwide_usage]
318 [section Space and Performance]
320 * `ctti_type_index` uses macro for getting full text representation of function name which could lead to code bloat,
321 so prefer using `stl_type_index` type when possible.
322 * All the type_index classes hold a single pointer and are fast to copy.
323 * 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.
324 * Comparison operators are optimized as much as possible and execute a single `std::strcmp` in worst case.
325 * 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.
331 Without RTTI TypeIndex library will switch from using `boost::typeindex::stl_type_index` class to
332 `boost::typeindex::ctti_type_index`. `boost::typeindex::ctti_type_index` uses macro for getting full
333 text representation of function name for each type that is passed to `type_id()` and
334 `type_id_with_cvr()` functions.
336 This leads to big strings in binary file:
338 static const char* boost::detail::ctti<T>::n() [with T = int]
339 static const char* boost::detail::ctti<T>::n() [with T = user_defined_type]
341 While using RTTI, you'll get the following (more compact) string in binary file:
350 [section RTTI emulation limitations]
352 TypeIndex has been tested and successfully work on many compilers.
355 With RTTI off classes with exactly the same names defined in different modules in anonymous namespaces may collapse:
358 namespace { struct user_defined{}; }
359 type_index foo_a() { return type_id<user_defined>(); }
362 namespace { struct user_defined{}; }
363 type_index foo_b() { return type_id<user_defined>(); }
366 assert(foo_a() != foo_b()); // will fail on some compilers
369 *Compilers that have that limitation:* GCC, CLANG, Intel.
371 *Test:* you can test this issue by runing the `testing_crossmodule_anonymous_no_rtti` that can be build if you run `../../../b2` in `type_index/test/` folder.
374 [section Define the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro]
376 If you get the following error during compilation
378 TypeIndex library could not detect your compiler.
379 Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use
380 correct compiler macro for getting the whole function name.
381 Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that.
383 then you are using a compiler that was not tested with this library.
385 [macroref BOOST_TYPE_INDEX_FUNCTION_SIGNATURE] must be defined to a compiler specific macro, that outputs the *whole*
386 function signature including template parameters.
391 [section Fixing pretty_name() output]
393 If the output of `boost::typeindex::ctti_type_index::type_id<int>().name()`
394 * returns not just `int` but also a lot of text around the `int`
395 * or does not return type at all
396 then you are using a compiler that was not tested with this library and you need to setup the
397 [macroref BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING] macro.
399 Here is a short instruction:
401 # get the output of `boost::typeindex::ctti_type_index::type_id<int>().name()`
402 # define [macroref BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING] to
403 `(skip_at_begin, skip_at_end, false, "")`, where
404 * `skip_at_begin` is equal to characters count before the first occurrence of `int` in output
405 * `skip_at_end` is equal to characters count after last occurrence of `int` in output
406 # check that `boost::typeindex::ctti_type_index::type_id<int>().name_demangled()` returns "int"
407 # if it does not return `int`, then define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to
408 `(skip_at_begin, skip_at_end, true, "T = ")`, where
409 * `skip_at_begin` is equal to `skip_at_begin` at step 2
410 * `skip_at_end` is equal to `skip_at_end` at step 2
411 * `"T = "` is equal to characters that are right before the `int` in output
412 # (optional, but highly recommended) [@http://www.boost.org/support/bugs.html create ticket] with
413 feature request to add your compiler to supported compilers list. Include
414 parameters provided to `BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING` macro.
417 Consider the following example:
419 `boost::typeindex::ctti_type_index::type_id<int>().raw_name()` returns
420 "const char *__cdecl boost::detail::ctti<int>::n(void)". Then you shall set
421 `skip_at_begin` to `sizeof("const char *__cdecl boost::detail::ctti<") - 1`
422 and `skip_at_end` to `sizeof(">::n(void)") - 1`.
425 #define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (39, 6, false, "")
430 `boost::typeindex::ctti_type_index::type_id<int>().raw_name()` returns
431 "static const char *boost::detail::ctti<int>::n() [T = int]"". Then you shall set
432 `skip_at_begin` to `sizeof("static const char *boost::detail::ctti<") - 1`
433 and `skip_at_end` to `sizeof("]") - 1` and last parameter of macro to "T = ".
436 #define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (39, 1, true, "T = ")
443 [section Mixing sources with RTTI on and RTTI off]
445 Linking a binary from source files that were compiled with different RTTI flags is not a very good
446 idea and may lead to a lot of surprises. However if there is a very strong need, TypeIndex library
447 provides a solution for mixing sources: just define [macroref BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY]
448 macro. This would lead to usage of same type_index class (`boost::typeindex::ctti_type_index` or
449 `boost::typeindex::stl_type_index`) all around the project.
451 [note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro defined ]
453 You must know that linking RTTI on and RTTI off binaries may succeed even without defining the
454 `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro, but that does not mean that you'll get a
455 working binary. Such actions may break the One Definition Rule. Take a look at the table below,
456 that shows how the `boost::type_index get_integer();` function will look like with different
460 [[RTTI on] [RTTI off]]
461 [[`boost::typeindex::stl_type_index get_integer();`] [`boost::typeindex::ctti_type_index get_integer();`]]
464 Such differences are usually not detected by linker and lead to errors at runtime.
467 Even with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` defined there is no guarantee
468 that everything will be OK. Libraries that use their own workarounds for disabled RTTI
469 may fail to link or to work correctly.
474 [section Acknowledgements]
476 In order of helping and advising:
478 * Peter Dimov for writing source codes in late 2007, that gave me an idea of how to emulate RTTI.
479 * Agustín Bergé K-ballo for helping with docs and fixing a lot of typos.
480 * Niall Douglas for generating a lot of great ideas, reviewing the sources and being the review manager for the library.
481 * All the library reviewers, especially Andrey Semashev, for making good notes and proposing improvements to the library.