]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/type_index/doc/type_index.qbk
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / type_index / doc / type_index.qbk
1 [library Boost.TypeIndex
2 [quickbook 1.6]
3 [version 4.1]
4 [copyright 2012-2016 Antony Polukhin]
5 [category Language Features Emulation]
6 [license
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])
10 ]
11 ]
12
13 [section Motivation]
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:
15
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
23
24 Boost.TypeIndex library was designed to work around all those issues.
25
26 [note `T` means type here. Think of it as of `T` in `template <class T>` ]
27
28 [endsect]
29
30 [section Getting started]
31
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.
35
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.
38
39 [section How to use]
40
41 To start using Boost.TypeIndex:
42
43 [table:porting
44 [[Replace this:][With the following:][More Info]]
45 [[``
46 #include <typeinfo>
47 #include <typeindex>
48 ``][``
49 #include <boost/type_index.hpp>
50 ``][
51 [headerref boost/type_index.hpp more... ]
52 ]]
53
54 [[``
55 std::type_index
56 ``][``
57 boost::typeindex::type_index
58 ``][
59 [classref boost::typeindex::type_index more... ]
60 ]]
61
62 [[``
63 typeid(T)
64 typeid(T).name() // not human readable
65 typeid(variable)
66 ``][``
67 boost::typeindex::type_id<T>()
68 boost::typeindex::type_id<T>().pretty_name() // human readable
69 boost::typeindex::type_id_runtime(variable)
70 ``][
71 [funcref boost::typeindex::type_id more... ]
72
73 [classref boost::typeindex::type_index more... ]
74
75 [funcref boost::typeindex::type_id_runtime more... ]
76 ]]
77
78 [[``
79 // attempt to save const, volatile, reference
80 typeid(please_save_modifiers<T>)
81 ``][``
82 // cvr = const, volatile, reference
83 boost::typeindex::type_id_with_cvr<T>()
84 ``][
85 [funcref boost::typeindex::type_id_with_cvr more... ]
86 ]]
87
88 [[``
89 // when reference to `std::type_info` is required
90 const std::type_info& v1 = typeid(int);
91
92 // other cases
93 const std::type_info* v2 = &typeid(int);
94 ``][``
95 const boost::typeindex::type_info& v1
96 = boost::typeindex::type_id<int>().type_info();
97
98 boost::typeindex::type_index v2
99 = boost::typeindex::type_id<int>();
100 ``][
101 [classref boost::typeindex::type_index more... ]
102
103 [funcref boost::typeindex::type_id more... ]
104 ]]
105 ]
106
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.
111
112 [endsect]
113
114 [section Example with Boost.Any]
115
116 Here is how TypeIndex could be used in `boost/any.hpp`:
117 [table:any
118 [[Before] [With TypeIndex]]
119 [[``#include <typeinfo>``][``#include <boost/type_index.hpp>``]]
120 [[``
121 virtual const std::type_info & type() const BOOST_NOEXCEPT
122 {
123 // requires RTTI
124 return typeid(ValueType);
125 }
126 ``] [``
127 virtual const boost::typeindex::type_info & type() const BOOST_NOEXCEPT
128 {
129 // now works even with RTTI disabled
130 return boost::typeindex::type_id<ValueType>().type_info();
131 }
132 ``]]
133 ]
134
135 [endsect]
136
137
138 [section Example with Boost.Variant]
139
140 Here is how TypeIndex could be used in `boost/variant/variant.hpp`:
141 [table:variant
142 [[Before] [With TypeIndex]]
143
144 [[``
145 #if !defined(BOOST_NO_TYPEID)
146 #include <typeinfo> // for typeid, std::type_info
147 #endif // BOOST_NO_TYPEID
148 ``][``
149 #include <boost/type_index.hpp>
150 ``]]
151 [[``
152 #if !defined(BOOST_NO_TYPEID)
153
154 class reflect
155 : public static_visitor<const std::type_info&>
156 {
157 public: // visitor interfaces
158
159 template <typename T>
160 const std::type_info& operator()(const T&) const BOOST_NOEXCEPT
161 {
162 return typeid(T);
163 }
164
165 };
166
167 #endif // BOOST_NO_TYPEID
168 ``][``
169 class reflect
170 : public static_visitor<const boost::typeindex::type_info&>
171 {
172 public: // visitor interfaces
173
174 template <typename T>
175 const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
176 {
177 return boost::typeindex::type_id<T>().type_info();
178 }
179
180 };
181 ``]]
182 [[``
183 #if !defined(BOOST_NO_TYPEID)
184 const std::type_info& type() const
185 {
186 detail::variant::reflect visitor;
187 return this->apply_visitor(visitor);
188 }
189 #endif
190 ``] [``
191 const boost::typeindex::type_info& type() const
192 {
193 detail::variant::reflect visitor;
194 return this->apply_visitor(visitor);
195 }
196 ``]]
197 ]
198
199 [endsect]
200 [endsect]
201
202 [section:config Configuring and building the library]
203
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.
206
207 The library supports a number of configuration macros, defining which require full
208 rebuild of all the projects that use TypeIndex:
209
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.]]
214
215 [[[macroref BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY]] [ Macro that must be defined
216 if you are mixing RTTI-on and RTTI-off.]]
217
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. ]]
221 ]
222
223 You can define configuration macros in the `bjam` command line using one of the following
224 approaches:
225
226 [pre
227 b2 variant=release define=BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY stage
228 ]
229
230 [pre
231 b2 variant=release "define=BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, \\"T = \\")'" stage
232 ]
233
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.
236
237 [endsect]
238
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].
242
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.
245
246 [macroref BOOST_TYPE_INDEX_REGISTER_CLASS] macro is a helper macro that places some virtual helper functions or
247 expands to nothing.
248
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
251 to function.
252
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).
255
256 [endsect]
257
258 [section Examples]
259
260 [import ../examples/demangled_names.cpp]
261 [section Getting human readable and mangled type names] [type_index_names_example] [endsect]
262
263 [import ../examples/registry.cpp]
264 [section Storing information about a type in container ] [type_index_registry_example] [endsect]
265
266 [import ../examples/inheritance.cpp]
267 [section Getting through the inheritance to receive a real type name ] [type_index_derived_example] [endsect]
268
269 [import ../examples/runtime_cast.cpp]
270 [section Using runtime_cast where RTTI is unavailable or undesirable ] [type_index_runtime_cast_example] [endsect]
271
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]
274
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]
277
278 [import ../examples/constexpr14_namespace_check.cpp]
279 [section C++14: Checking namespace at compile time ] [type_index_constexpr14_namespace_example] [endsect]
280
281 [import ../examples/constexpr14_sort_check.cpp]
282 [section C++14: Checking lexigraphical order of provided types ] [type_index_constexpr14_sort_check_example] [endsect]
283
284 [endsect]
285
286 [xinclude autodoc.xml]
287
288 [section Making a custom type_index]
289
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.
291
292 [import ../examples/user_defined_typeinfo.hpp]
293 [import ../examples/user_defined_typeinfo.cpp]
294
295 [section Basics]
296 [type_index_userdefined_usertypes]
297 [type_index_userdefined_enum]
298 [type_index_my_type_index]
299 [type_index_my_type_index_usage]
300 [endsect]
301
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]
307 [endsect]
308
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]
313 [endsect]
314
315 [endsect]
316
317
318 [section Space and Performance]
319
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.
326
327 [endsect]
328
329 [section Code bloat]
330
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.
335
336 This leads to big strings in binary file:
337 ```
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]
340 ```
341 While using RTTI, you'll get the following (more compact) string in binary file:
342
343 ```
344 i
345 17user_defined_type
346 ```
347
348 [endsect]
349
350 [section RTTI emulation limitations]
351
352 TypeIndex has been tested and successfully work on many compilers.
353
354 [warning
355 With RTTI off classes with exactly the same names defined in different modules in anonymous namespaces may collapse:
356 ```
357 // In A.cpp
358 namespace { struct user_defined{}; }
359 type_index foo_a() { return type_id<user_defined>(); }
360
361 // In B.cpp
362 namespace { struct user_defined{}; }
363 type_index foo_b() { return type_id<user_defined>(); }
364
365 // In main.cpp
366 assert(foo_a() != foo_b()); // will fail on some compilers
367 ```
368
369 *Compilers that have that limitation:* GCC, CLANG, Intel.
370
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.
372 ]
373
374 [section Define the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro]
375
376 If you get the following error during compilation
377 ``
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.
382 ``
383 then you are using a compiler that was not tested with this library.
384
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.
387
388
389 [endsect]
390
391 [section Fixing pretty_name() output]
392
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.
398
399 Here is a short instruction:
400
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.
415
416
417 Consider the following example:
418
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`.
423
424 ``
425 #define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (39, 6, false, "")
426 ``
427
428 Another example:
429
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 = ".
434
435 ``
436 #define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (39, 1, true, "T = ")
437 ``
438
439 [endsect]
440
441 [endsect]
442
443 [section Mixing sources with RTTI on and RTTI off]
444
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.
450
451 [note Do not forget to rebuild *all* the projects with `BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY` macro defined ]
452
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
457 RTTI flags:
458
459 [table:diffs
460 [[RTTI on] [RTTI off]]
461 [[`boost::typeindex::stl_type_index get_integer();`] [`boost::typeindex::ctti_type_index get_integer();`]]
462 ]
463
464 Such differences are usually not detected by linker and lead to errors at runtime.
465
466 [warning
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.
470 ]
471
472 [endsect]
473
474 [section Acknowledgements]
475
476 In order of helping and advising:
477
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.
482
483 [endsect]